Commit 30992d3a authored by gejun's avatar gejun
parents d4f2b4db 89a311c3
......@@ -6,9 +6,9 @@ include config.mk
# 2. Added -D__const__= : Avoid over-optimizations of TLS variables by GCC>=4.8
# 3. Removed -Werror: Not block compilation for non-vital warnings, especially when the
# code is tested on newer systems. If the code is used in production, add -Werror back
CPPFLAGS=-DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__= -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DBRPC_REVISION=\"$(shell git rev-parse --short HEAD)\"
CXXFLAGS=$(CPPFLAGS) -g -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer -std=c++0x
CFLAGS=$(CPPFLAGS) -g -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-unused-parameter -fno-omit-frame-pointer
CPPFLAGS+=-DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__= -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DBRPC_REVISION=\"$(shell git rev-parse --short HEAD)\"
CXXFLAGS+=$(CPPFLAGS) -g -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer -std=c++0x
CFLAGS+=$(CPPFLAGS) -g -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-unused-parameter -fno-omit-frame-pointer
HDRPATHS=-I./src $(addprefix -I, $(HDRS))
LIBPATHS = $(addprefix -L, $(LIBS))
COMMA = ,
......@@ -270,7 +270,7 @@ output/bin:protoc-gen-mcpack
%.dbg.o:%.cpp
@echo "Compiling $@"
@$(CXX) -c $(HDRPATHS) $(CXXFLAGS) $< -o $@
@$(CXX) -c $(HDRPATHS) $(CXXFLAGS) -DBVAR_NOT_LINK_DEFAULT_VARIABLES $< -o $@
%.o:%.cc
@echo "Compiling $@"
......
......@@ -5,7 +5,8 @@ else
fi
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o v: --long headers:,libs:,cc:,cxx: -n 'config_brpc' -- "$@"`
TEMP=`getopt -o v: --long headers:,libs:,cc:,cxx:,with-glog -n 'config_brpc' -- "$@"`
WITH_GLOG=0
if [ $? != 0 ] ; then >&2 $ECHO "Terminating..."; exit 1 ; fi
......@@ -19,10 +20,12 @@ while true; do
--libs ) LIBS_IN="$(readlink -f $2)"; shift 2 ;;
--cc ) CC=$2; shift 2 ;;
--cxx ) CXX=$2; shift 2 ;;
--with-glog ) WITH_GLOG=1; shift 1 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
if [ -z "$CC" ]; then
if [ ! -z "$CXX" ]; then
>&2 $ECHO "--cc and --cxx must be both set or unset"
......@@ -82,8 +85,17 @@ find_bin_or_die() {
find_dir_of_header() {
find ${HDRS_IN} -path "*/$1" | head -n1 | sed "s|$1||g"
}
find_dir_of_header_excluding() {
find ${HDRS_IN} -path "*/$1" | grep -v "$2\$" | head -n1 | sed "s|$1||g"
}
find_dir_of_header_or_die() {
local dir=$(find_dir_of_header $1)
if [ -z "$2" ]; then
local dir=$(find_dir_of_header $1)
else
local dir=$(find_dir_of_header_excluding $1 $2)
fi
if [ -z "$dir" ]; then
>&2 $ECHO "Fail to find $1 from --headers"
exit 1
......@@ -243,6 +255,23 @@ else
fi
append_to_output "endif"
if [ $WITH_GLOG != 0 ]; then
GLOG_LIB=$(find_dir_of_lib glog)
GLOG_HDR=$(find_dir_of_header_or_die glog/logging.h windows/glog/logging.h)
append_to_output_headers "$GLOG_HDR" " "
if [ -z "$GLOG_LIB" ]; then
append_to_output " \$(error \"Fail to find glog\")"
else
append_to_output_libs "$GLOG_LIB" " "
if [ -f $GLOG_LIB/libglog.a ]; then
append_to_output " STATIC_LINKINGS+=-lglog"
else
append_to_output " DYNAMIC_LINKINGS+=-lglog"
fi
fi
fi
append_to_output "CPPFLAGS+=-DBRPC_WITH_GLOG=$WITH_GLOG"
# required by UT
#gtest
GTEST_LIB=$(find_dir_of_lib gtest)
......@@ -276,5 +305,19 @@ else
fi
append_to_output "endif"
# generate src/butil/config.h
cat << EOF > src/butil/config.h
// This file is auto-generated by $(basename "$0"). DON'T edit it!
#ifndef BUTIL_CONFIG_H
#define BUTIL_CONFIG_H
#ifdef BRPC_WITH_GLOG
#undef BRPC_WITH_GLOG
#endif
#define BRPC_WITH_GLOG $WITH_GLOG
#endif // BUTIL_CONFIG_H
EOF
# write to config.mk
$ECHO "$OUTPUT_CONTENT" > config.mk
......@@ -2,21 +2,22 @@ bthread([代码](http://icode.baidu.com/repo/baidu/opensource/baidu-rpc/files/ma
# Goals
- 用户可以延续同步的编程模式,能很快地建立bthread,可以用多种原语同步。
- bthread所有接口可在pthread中被调用并有合理的行为,使用bthread的代码可以在pthread中正常执行。
- 用户可以延续同步的编程模式,能在数百纳秒内建立bthread,可以用多种原语同步。
- bthread所有接口可在pthread中被调用并有合理的行为,使用bthread的代码可以在pthread中正常执行。
- 能充分利用多核。
- 更好的cache locality,更低的延时。
- better cache locality, supporting NUMA is a plus.
# NonGoals
- 提供pthread的兼容接口,只需链接即可使用。拒绝理由:bthread没有优先级,不适用于所有的场景,链接的方式容易使用户在不知情的情况下误用bthread,造成bug。
- 修改内核让pthread支持同核快速切换。拒绝理由:拥有大量pthread后,每个线程对资源的需求被稀释了,基于thread-local cache的代码效果都会很差,比如tcmalloc。而独立的bthread不会有这个问题,因为它最终还是被映射到了少量的pthread。
- 提供pthread的兼容接口,只需链接即可使用。**拒绝理由**: bthread没有优先级,不适用于所有的场景,链接的方式容易使用户在不知情的情况下误用bthread,造成bug。
- 覆盖各类可能阻塞的glibc函数和系统调用,让原本阻塞系统线程的函数改为阻塞bthread。**拒绝理由**: 1. bthread阻塞可能切换系统线程,依赖系统TLS的函数的行为未定义。2. 和阻塞pthread的函数混用时可能死锁。3. 这类hook函数本身的效率一般更差,因为往往还需要额外的系统调用,如epoll。但这类覆盖对N:1合作式线程库(fiber)有一定意义:虽然函数本身慢了,但若不覆盖会更慢(系统线程阻塞会导致所有fiber阻塞)。
- 修改内核让pthread支持同核快速切换。**拒绝理由**: 拥有大量pthread后,每个线程对资源的需求被稀释了,基于thread-local cache的代码效果会很差,比如tcmalloc。而独立的bthread不会有这个问题,因为它最终还是被映射到了少量的pthread。bthread相比pthread的性能提升很大一部分来自更集中的线程资源。另一个考量是可移植性,bthread更倾向于纯用户态代码。
# FAQ
##### Q:bthread是协程(coroutine)吗?
不是。我们常说的协程是N:1线程库,即所有的协程都运行于一个系统线程中,计算能力和各种eventloop等价。由于不跨线程,协程之间的切换不需要系统调用,可以非常快(100ns-200ns),受cache同步的影响也小。但相应的代价是协程无法高效地利用多核,代码必须非阻塞,否则所有的协程都被卡住,对开发者要求苛刻。协程的这个特点使其适合写运行时间确定的IO服务器,典型如http server,在一些精心调试的场景中,可以达到非常高的吞吐。但百度内大部分在线服务的运行时间并不确定,一个缓慢的函数很容易卡住所有的协程。在这点上eventloop是类似的,一个回调卡住整个loop就卡住了,比如ub**a**server(注意那个a,不是ubserver)是公司内对异步框架的尝试,由多个并行的eventloop组成,真实表现糟糕:回调里打日志慢一些,访问下redis,计算重一点,等待中的其他请求就会大量超时。所以这个框架从未流行起来。
不是。我们常说的协程特指N:1线程库,即所有的协程运行于一个系统线程中,计算能力和各类eventloop库等价。由于不跨线程,协程之间的切换不需要系统调用,可以非常快(100ns-200ns),受cache一致性的影响也小。但代价是协程无法高效地利用多核,代码必须非阻塞,否则所有的协程都被卡住,对开发者要求苛刻。协程的这个特点使其适合写运行时间确定的IO服务器,典型如http server,在一些精心调试的场景中,可以达到非常高的吞吐。但百度内大部分在线服务的运行时间并不确定,且很多检索由几十人合作完成,一个缓慢的函数会卡住所有的协程。在这点上eventloop是类似的,一个回调卡住整个loop就卡住了,比如ub**a**server(注意那个a,不是ubserver)是百度对异步框架的尝试,由多个并行的eventloop组成,真实表现糟糕:回调里打日志慢一些,访问redis卡顿,计算重一点,等待中的其他请求就会大量超时。所以这个框架从未流行起来。
bthread是一个M:N线程库,一个bthread被卡住不会影响其他bthread。关键技术两点:work stealing调度和butex,前者让bthread更快地被调度到更多的核心上,后者让bthread和pthread可以相互等待和唤醒。这两点协程都不需要。更多线程的知识查看[这里](threading_overview.md)
......@@ -26,7 +27,7 @@ bthread是一个M:N线程库,一个bthread被卡住不会影响其他bthread
##### Q:bthread和pthread worker如何对应?
pthread worker在任何时间只会运行一个bthread,当前bthread挂起时,pthread worker先尝试从本地(runqueue)弹出一个待运行的bthread,若没有,则随机偷另一个worker的待运行bthread,仍然没有才睡眠并会在有新的待运行bthread时被唤醒。
pthread worker在任何时间只会运行一个bthread,当前bthread挂起时,pthread worker先尝试从本地runqueue弹出一个待运行的bthread,若没有,则随机偷另一个worker的待运行bthread,仍然没有才睡眠并会在有新的待运行bthread时被唤醒。
##### Q:bthread中能调用阻塞的pthread或系统函数吗?
......@@ -42,19 +43,16 @@ pthread worker在任何时间只会运行一个bthread,当前bthread挂起时
##### Q:若有大量的bthread调用了阻塞的pthread或系统函数,会影响RPC运行么?
会。比如有8个pthread worker,当有8个bthread都调用了系统usleep()后,处理网络收发的RPC代码就暂时无法运行了。只要阻塞时间不太长, 这一般没什么影响, 毕竟worker都用完了, 除了排队也没有什么好方法.
会。比如有8个pthread worker,当有8个bthread都调用了系统usleep()后,处理网络收发的RPC代码就暂时无法运行了。只要阻塞时间不太长, 这一般**没什么影响**, 毕竟worker都用完了, 除了排队也没有什么好方法.
在brpc中用户可以选择调大worker数来缓解问题, 在server端可设置[ServerOptions.num_threads](server.md#id-创建和设置Server-worker线程数)[-bthread_concurrency](http://brpc.baidu.com:8765/flags/bthread_concurrency), 在client端可设置[-bthread_concurrency](http://brpc.baidu.com:8765/flags/bthread_concurrency).
那有没有完全规避的方法呢?
- 一个容易想到的方法是动态增加worker数. 但实际未必如意, 当大量的worker同时被阻塞时,
它们很可能在等待同一个资源(比如同一把锁), 增加worker可能只是增加了更多的等待者.
- 大部分RPC框架采取的方法是区分io线程和worker线程, io线程专门处理收发, worker线程调用用户逻辑,
即使worker线程全部阻塞也不会影响io线程. 但这个方法使得每个请求都要从io线程跳转至worker线程,
增加了一次上下文切换, 在机器繁忙时, 切换都有一定概率无法被及时调度, 会导致更多的延时长尾.
另一个问题是增加一层处理环节(io线程)并不能缓解拥塞, 如果worker线程全部卡住, 程序仍然会卡住,
- 那区分io线程和worker线程? io线程专门处理收发, worker线程调用用户逻辑, 即使worker线程全部阻塞也不会影响io线程. 但增加一层处理环节(io线程)并不能缓解拥塞, 如果worker线程全部卡住, 程序仍然会卡住,
只是卡的地方从socket缓冲转移到了io线程和worker线程之间的消息队列. 换句话说, 在worker卡住时,
还在运行的io线程做的可能是无用功. 事实上, 这正是上面提到的"没什么影响"真正的含义.
还在运行的io线程做的可能是无用功. 事实上, 这正是上面提到的**没什么影响**真正的含义. 另一个问题是每个请求都要从io线程跳转至worker线程, 增加了一次上下文切换, 在机器繁忙时, 切换都有一定概率无法被及时调度, 会导致更多的延时长尾.
- 一个实际的解决方法是[限制最大并发](server.md#限制最大并发), 只要同时被处理的请求数低于worker数, 自然可以规避掉"所有worker被阻塞"的情况.
- 另一个解决方法当被阻塞的worker超过阈值时(比如8个中的6个), 就不在原地调用用户代码了, 而是扔到一个独立的线程池中运行. 这样即使用户代码全部阻塞, 也总能保留几个worker处理rpc的收发. 不过目前bthread模式并没有这个机制, 但类似的机制在[打开pthread模式](server.md#pthread模式)时已经被实现了. 那像上面提到的, 这个机制是不是在用户代码都阻塞时也在做"无用功"呢? 可能是的. 但这个机制更多是为了规避在一些极端情况下的死锁, 比如所有的用户代码都lock在一个pthread mutex上, 并且这个mutex需要在某个RPC回调中unlock, 如果所有的worker都被阻塞, 那么就没有线程来处理RPC回调了, 整个程序就死锁了. 虽然绝大部分的RPC实现都有这个潜在问题, 但实际出现频率似乎很低, 只要养成不在锁内做RPC的好习惯, 这是完全可以规避的.
......
This diff is collapsed.
......@@ -89,6 +89,10 @@ If you want to use [cpu profiler](cpu_profiler.md) or [heap profiler](heap_profi
When you remove tcmalloc, not only remove the linking with tcmalloc but also the macros: `-DBRPC_ENABLE_CPU_PROFILER` and `-DBRPC_ENABLE_HEAP_PROFILER`.
## glog: 3.3+
brpc implementes a default [logging utility](../../src/butil/logging.h) which conflicts with glog. To replace this with glog, add *--with-glog* to config_brpc.sh
## valgrind: 3.8+
brpc detects valgrind automatically (and registers stacks of bthread). Older valgrind (say 3.2) is not supported.
......
This diff is collapsed.
......@@ -13,11 +13,11 @@
// limitations under the License.
// - Access pb services via HTTP
// ./http_client http://db-rpc-dev00.db01.baidu.com:8765/EchoService/Echo -d '{"message":"hello"}'
// ./http_client http://www.foo.com:8765/EchoService/Echo -d '{"message":"hello"}'
// - Access builtin services
// ./http_client http://db-rpc-dev00.db01.baidu.com:8765/vars/rpc_server*
// - Access www.baidu.com
// ./http_client www.baidu.com
// ./http_client http://www.foo.com:8765/vars/rpc_server*
// - Access www.foo.com
// ./http_client www.foo.com
#include <gflags/gflags.h>
#include <butil/logging.h>
......@@ -38,7 +38,7 @@ int main(int argc, char* argv[]) {
google::ParseCommandLineFlags(&argc, &argv, true);
if (argc != 2) {
LOG(ERROR) << "Usage: ./http_client \"www.baidu.com\"";
LOG(ERROR) << "Usage: ./http_client \"www.foo.com\"";
return -1;
}
char* url = argv[1];
......
......@@ -15,6 +15,7 @@
// Authors: Rujie Jiang(jiangrujie@baidu.com)
// Ge,Jun(gejun@baidu.com)
#include <inttypes.h>
#include <gflags/gflags.h>
#include "butil/fd_guard.h" // fd_guard
#include "butil/fd_utility.h" // make_close_on_exec
......
......@@ -22,6 +22,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/message.h>
#include "butil/sys_byteorder.h"
#include "butil/strings/string_piece.h"
namespace brpc {
......
......@@ -547,17 +547,18 @@ static void DoProfiling(ProfilingType type,
}
// Log requester
LOG(INFO) << cntl->remote_side() << noflush;
std::ostringstream client_info;
client_info << cntl->remote_side();
if (cntl->auth_context()) {
LOG(INFO) << "(auth=" << cntl->auth_context()->user() << ')' << noflush;
client_info << "(auth=" << cntl->auth_context()->user() << ')';
} else {
LOG(INFO) << "(no auth)" << noflush;
client_info << "(no auth)";
}
LOG(INFO) << " requests for profiling " << ProfilingType2String(type) << noflush;
client_info << " requests for profiling " << ProfilingType2String(type);
if (type == PROFILING_CPU || type == PROFILING_CONTENTION) {
LOG(INFO) << " for " << seconds << " seconds";
LOG(INFO) << client_info.str() << " for " << seconds << " seconds";
} else {
LOG(INFO);
LOG(INFO) << client_info.str();
}
int64_t prof_id = 0;
const std::string* prof_id_str =
......
......@@ -108,13 +108,15 @@ void PProfService::profile(
return;
}
// Log requester
LOG(INFO) << cntl->remote_side() << noflush;
std::ostringstream client_info;
client_info << cntl->remote_side();
if (cntl->auth_context()) {
LOG(INFO) << "(auth=" << cntl->auth_context()->user() << ')' << noflush;
client_info << "(auth=" << cntl->auth_context()->user() << ')';
} else {
LOG(INFO) << "(no auth)" << noflush;
client_info << "(no auth)";
}
LOG(INFO) << " requests for cpu profile for " << sleep_sec << " seconds";
LOG(INFO) << client_info.str() << " requests for cpu profile for "
<< sleep_sec << " seconds";
char prof_name[256];
if (MakeProfName(PROFILING_CPU, prof_name, sizeof(prof_name)) != 0) {
......@@ -163,13 +165,15 @@ void PProfService::contention(
return;
}
// Log requester
LOG(INFO) << cntl->remote_side() << noflush;
std::ostringstream client_info;
client_info << cntl->remote_side();
if (cntl->auth_context()) {
LOG(INFO) << "(auth=" << cntl->auth_context()->user() << ')' << noflush;
client_info << "(auth=" << cntl->auth_context()->user() << ')';
} else {
LOG(INFO) << "(no auth)" << noflush;
client_info << "(no auth)";
}
LOG(INFO) << " requests for contention profile for " << sleep_sec << " seconds";
LOG(INFO) << client_info.str() << " requests for contention profile for "
<< sleep_sec << " seconds";
char prof_name[256];
if (MakeProfName(PROFILING_CONTENTION, prof_name, sizeof(prof_name)) != 0) {
......@@ -210,13 +214,14 @@ void PProfService::heap(
return;
}
// Log requester
LOG(INFO) << cntl->remote_side() << noflush;
std::ostringstream client_info;
client_info << cntl->remote_side();
if (cntl->auth_context()) {
LOG(INFO) << "(auth=" << cntl->auth_context()->user() << ')' << noflush;
client_info << "(auth=" << cntl->auth_context()->user() << ')';
} else {
LOG(INFO) << "(no auth)" << noflush;
client_info << "(no auth)";
}
LOG(INFO) << " requests for heap profile";
LOG(INFO) << client_info.str() << " requests for heap profile";
std::string obj;
malloc_ext->GetHeapSample(&obj);
......@@ -239,13 +244,14 @@ void PProfService::growth(
return;
}
// Log requester
LOG(INFO) << cntl->remote_side() << noflush;
std::ostringstream client_info;
client_info << cntl->remote_side();
if (cntl->auth_context()) {
LOG(INFO) << "(auth=" << cntl->auth_context()->user() << ')' << noflush;
client_info << "(auth=" << cntl->auth_context()->user() << ')';
} else {
LOG(INFO) << "(no auth)" << noflush;
client_info << "(no auth)";
}
LOG(INFO) << " requests for growth profile";
LOG(INFO) << client_info.str() << " requests for growth profile";
std::string obj;
malloc_ext->GetHeapGrowthStacks(&obj);
......
......@@ -14,13 +14,14 @@
// Authors: Ge,Jun (gejun@baidu.com)
#if !BRPC_WITH_GLOG
#include "brpc/log.h"
#include "brpc/controller.h" // Controller
#include "brpc/closure_guard.h" // ClosureGuard
#include "brpc/builtin/vlog_service.h"
#include "brpc/builtin/common.h"
namespace brpc {
class VLogPrinter : public VLogSitePrinter {
......@@ -91,3 +92,6 @@ void VLogService::default_method(::google::protobuf::RpcController* cntl_base,
}
} // namespace brpc
#endif
......@@ -17,6 +17,7 @@
#ifndef BRPC_VLOG_SERVICE_H
#define BRPC_VLOG_SERVICE_H
#if !BRPC_WITH_GLOG
#include <ostream>
#include "brpc/builtin_service.pb.h"
......@@ -34,5 +35,6 @@ public:
} // namespace brpc
#endif // BRPC_WITH_GLOG
#endif //BRPC_VLOG_SERVICE_H
......@@ -16,6 +16,7 @@
// Rujie Jiang(jiangrujie@baidu.com)
// Zhangyi Chen(chenzhangyi01@baidu.com)
#include <inttypes.h>
#include <google/protobuf/descriptor.h>
#include <gflags/gflags.h>
#include "butil/time.h" // milliseconds_from_now
......
......@@ -108,10 +108,10 @@ struct ChannelOptions {
const NamingServiceFilter* ns_filter;
};
// A Channel represents a communication line to a server which can be used
// to call that Server's services. The server may be running on another
// machine. Normally, you should not call a Channel directly, but instead
// construct a stub Service wrapping it.
// A Channel represents a communication line to one server or multiple servers
// which can be used to call that Server's services. Servers may be running
// on another machines. Normally, you should not call a Channel directly, but
// instead construct a stub Service wrapping it.
// Example:
// brpc::Channel channel;
// channel.Init("bns://rdev.matrix.all", "rr", NULL/*default options*/);
......
......@@ -168,15 +168,16 @@ void NamingServiceThread::Actions::ResetServers(
}
if (!_removed.empty() || !_added.empty()) {
LOG(INFO) << butil::class_name_str(*_owner->_ns) << "(\""
<< _owner->_service_name << "\"):" << noflush;
std::ostringstream info;
info << butil::class_name_str(*_owner->_ns) << "(\""
<< _owner->_service_name << "\"):";
if (!_added.empty()) {
LOG(INFO) << " added "<< _added.size() << noflush;
info << " added "<< _added.size();
}
if (!_removed.empty()) {
LOG(INFO) << " removed " << _removed.size() << noflush;
info << " removed " << _removed.size();
}
LOG(INFO);
LOG(INFO) << info.str();
}
EndWait(servers.empty() ? ENODATA : 0);
......
......@@ -228,19 +228,19 @@ static void BaiduStreamingLogHandler(google::protobuf::LogLevel level,
const std::string& message) {
switch (level) {
case google::protobuf::LOGLEVEL_INFO:
LOG_AT(INFO, filename, line) << message;
LOG(INFO) << filename << ':' << line << ' ' << message;
return;
case google::protobuf::LOGLEVEL_WARNING:
LOG_AT(WARNING, filename, line) << message;
LOG(WARNING) << filename << ':' << line << ' ' << message;
return;
case google::protobuf::LOGLEVEL_ERROR:
LOG_AT(ERROR, filename, line) << message;
LOG(ERROR) << filename << ':' << line << ' ' << message;
return;
case google::protobuf::LOGLEVEL_FATAL:
LOG_AT(FATAL, filename, line) << message;
LOG(FATAL) << filename << ':' << line << ' ' << message;
return;
}
LOG_AT(FATAL, filename, line) << message;
CHECK(false) << filename << ':' << line << ' ' << message;
}
static void GlobalInitializeOrDieImpl() {
......
......@@ -171,14 +171,14 @@ ProtocolType StringToProtocolType(const butil::StringPiece& name,
// "channel doesn't support protocol=unknown"
// Some callsite may not need this log, so we keep a flag.
if (print_log_on_unknown) {
LOG(ERROR) << "Unknown protocol `" << name << "', supported protocols:"
<< noflush;
std::ostringstream err;
err << "Unknown protocol `" << name << "', supported protocols:";
for (size_t i = 0; i < MAX_PROTOCOL_SIZE; ++i) {
if (protocol_map[i].valid.load(butil::memory_order_acquire)) {
LOG(ERROR) << ' ' << protocol_map[i].protocol.name << noflush;
err << ' ' << protocol_map[i].protocol.name;
}
}
LOG(ERROR);
LOG(ERROR) << err.str();
}
return PROTOCOL_UNKNOWN;
}
......
......@@ -491,10 +491,14 @@ int Server::AddBuiltinServices() {
LOG(ERROR) << "Fail to add ThreadsService";
return -1;
}
#if !BRPC_WITH_GLOG
if (AddBuiltinService(new (std::nothrow) VLogService)) {
LOG(ERROR) << "Fail to add VLogService";
return -1;
}
#endif
if (AddBuiltinService(new (std::nothrow) PProfService)) {
LOG(ERROR) << "Fail to add PProfService";
return -1;
......@@ -578,14 +582,15 @@ Acceptor* Server::BuildAcceptor() {
}
}
if (!whitelist.empty()) {
LOG(ERROR) << "ServerOptions.enabled_protocols has unknown protocols=`"
<< noflush;
std::ostringstream err;
err << "ServerOptions.enabled_protocols has unknown protocols=`";
for (std::set<std::string>::const_iterator it = whitelist.begin();
it != whitelist.end(); ++it) {
LOG(ERROR) << *it << ' ' << noflush;
err << *it << ' ';
}
LOG(ERROR) << '\'';
err << '\'';
delete acceptor;
LOG(ERROR) << err.str();
return NULL;
}
return acceptor;
......@@ -950,13 +955,14 @@ int Server::StartInternal(const butil::ip_t& ip,
// Print tips to server launcher.
int http_port = _listen_addr.port;
LOG(INFO) << "Server[" << version() << "] is serving on port="
<< _listen_addr.port << noflush;
std::ostringstream server_info;
server_info << "Server[" << version() << "] is serving on port="
<< _listen_addr.port;
if (_options.internal_port >= 0 && _options.has_builtin_services) {
http_port = _options.internal_port;
LOG(INFO) << " and internal_port=" << _options.internal_port << noflush;
server_info << " and internal_port=" << _options.internal_port;
}
LOG(INFO) << '.';
LOG(INFO) << server_info.str() << '.';
if (_options.has_builtin_services) {
LOG(INFO) << "Check out http://" << butil::my_hostname() << ':'
......
......@@ -138,6 +138,7 @@ SocketMap::~SocketMap() {
bthread_join(_close_idle_thread, NULL);
}
if (!_map.empty()) {
std::ostringstream err;
int nleft = 0;
for (Map::iterator it = _map.begin(); it != _map.end(); ++it) {
SingleConnection* sc = &it->second;
......@@ -146,13 +147,13 @@ SocketMap::~SocketMap() {
sc->ref_count != 0) {
++nleft;
if (nleft == 0) {
LOG(ERROR) << "Left in SocketMap(" << this << "):" << noflush;
err << "Left in SocketMap(" << this << "):";
}
LOG(ERROR) << ' ' << *sc->socket << noflush;
err << ' ' << *sc->socket;
}
}
if (nleft) {
LOG(ERROR);
LOG(ERROR) << err.str();
}
}
if (_this_map_bvar) {
......
......@@ -93,10 +93,10 @@ class LeakTracker : public LinkNode<LeakTracker<T> > {
stacktraces[count] = allocation_stack;
++count;
if (LOG_IS_ON(ERROR)) {
LOG_STREAM(ERROR) << "Leaked " << node << " which was allocated by:";
allocation_stack.OutputToStream(&LOG_STREAM(ERROR));
}
std::ostringstream err;
err << "Leaked " << node << " which was allocated by:";
allocation_stack.OutputToStream(&err);
LOG(ERROR) << err.str();
}
CHECK_EQ(0u, count);
......
......@@ -26,6 +26,7 @@
#include "butil/endpoint.h" // ip_t
#include "butil/logging.h"
#include "butil/memory/singleton_on_pthread_once.h"
#include "butil/strings/string_piece.h"
__BEGIN_DECLS
int BAIDU_WEAK bthread_connect(
......
......@@ -17,6 +17,8 @@
#include "butil/logging.h"
#if !BRPC_WITH_GLOG
#if defined(OS_WIN)
#include <io.h>
#include <windows.h>
......@@ -116,17 +118,17 @@ DEFINE_bool(crash_on_fatal_log, false,
DEFINE_bool(print_stack_on_check, true,
"Print the stack trace when a CHECK was failed");
DEFINE_int32(verbose, 0, "Show all VLOG(m) messages for m <= this."
" Overridable by --verbose_module.");
DEFINE_string(verbose_module, "", "per-module verbose level."
DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this."
" Overridable by --vmodule.");
DEFINE_string(vmodule, "", "per-module verbose level."
" Argument is a comma-separated list of MODULE_NAME=LOG_LEVEL."
" MODULE_NAME is a glob pattern, matched against the filename base"
" (that is, name ignoring .cpp/.h)."
" LOG_LEVEL overrides any value given by --verbose.");
" LOG_LEVEL overrides any value given by --v.");
DEFINE_bool(log_process_id, false, "Log process id");
DEFINE_int32(min_log_level, 0, "Any log at or above this level will be "
DEFINE_int32(minloglevel, 0, "Any log at or above this level will be "
"displayed. Anything below this level will be silently ignored. "
"0=INFO 1=NOTICE 2=WARNING 3=ERROR 4=FATAL");
......@@ -432,11 +434,11 @@ bool BaseInitLoggingImpl(const LoggingSettings& settings) {
}
void SetMinLogLevel(int level) {
FLAGS_min_log_level = std::min(BLOG_FATAL, level);
FLAGS_minloglevel = std::min(BLOG_FATAL, level);
}
int GetMinLogLevel() {
return FLAGS_min_log_level;
return FLAGS_minloglevel;
}
void SetShowErrorDialogs(bool enable_dialogs) {
......@@ -1019,7 +1021,7 @@ void CloseLogFile() {
}
void RawLog(int level, const char* message) {
if (level >= FLAGS_min_log_level) {
if (level >= FLAGS_minloglevel) {
size_t bytes_written = 0;
const size_t message_len = strlen(message);
int rv;
......@@ -1126,7 +1128,7 @@ private:
// Next site in the list. NULL means no next.
butil::subtle::AtomicWord _next;
// --verbose_module > --verbose
// --vmodule > --v
int _v;
// vlog is on iff _v >= _required_v
......@@ -1270,12 +1272,12 @@ private:
// vlog_site_list. To keep the critical area small, we use optimistic
// locking : Assign local site w/o locking, then insert the site into
// global list w/ locking, if local_module_list != global_vmodule_list or
// local_default_v != FLAGS_verbose, repeat the assigment.
// local_default_v != FLAGS_v, repeat the assigment.
// An important property of vlog_site_list is that: It does not remove sites.
// When we need to iterate the list, we don't have to hold the lock. What we
// do is to get the head of the list inside lock and iterate the list w/o
// lock. If new sites is inserted during the iteration, it should see and
// use the updated vmodule_list and FLAGS_verbose, nothing will be missed.
// use the updated vmodule_list and FLAGS_v, nothing will be missed.
static int vlog_site_list_add(VLogSite* site,
VModuleList** expected_module_list,
......@@ -1285,8 +1287,8 @@ static int vlog_site_list_add(VLogSite* site,
*expected_module_list = vmodule_list;
return -1;
}
if (*expected_default_v != FLAGS_verbose) {
*expected_default_v = FLAGS_verbose;
if (*expected_default_v != FLAGS_v) {
*expected_default_v = FLAGS_v;
return -1;
}
site->set_next(vlog_site_list);
......@@ -1301,7 +1303,7 @@ bool add_vlog_site(const int** v, const char* filename, int line_no,
return false;
}
VModuleList* module_list = vmodule_list;
int default_v = FLAGS_verbose;
int default_v = FLAGS_v;
do {
site->v() = default_v;
if (module_list) {
......@@ -1329,8 +1331,8 @@ void print_vlog_sites(VLogSitePrinter* printer) {
}
}
// [Thread-safe] Reset FLAGS_verbose_module.
static int on_reset_verbose_module(const char* vmodule) {
// [Thread-safe] Reset FLAGS_vmodule.
static int on_reset_vmodule(const char* vmodule) {
// resetting must be serialized.
BAIDU_SCOPED_LOCK(reset_vmodule_and_v_mutex);
......@@ -1355,7 +1357,7 @@ static int on_reset_verbose_module(const char* vmodule) {
old_vlog_site_list = vlog_site_list;
}
for (VLogSite* p = old_vlog_site_list; p; p = p->next()) {
p->v() = FLAGS_verbose;
p->v() = FLAGS_v;
module_list->find_verbose_level(
p->module(), p->full_module(), &p->v());
}
......@@ -1380,13 +1382,13 @@ static int on_reset_verbose_module(const char* vmodule) {
}
static bool validate_vmodule(const char*, const std::string& vmodule) {
return on_reset_verbose_module(vmodule.c_str()) == 0;
return on_reset_vmodule(vmodule.c_str()) == 0;
}
const bool ALLOW_UNUSED validate_vmodule_dummy = google::RegisterFlagValidator(
&FLAGS_verbose_module, &validate_vmodule);
&FLAGS_vmodule, &validate_vmodule);
// [Thread-safe] Reset FLAGS_verbose.
// [Thread-safe] Reset FLAGS_v.
static void on_reset_verbose(int default_v) {
VModuleList* cur_module_list = NULL;
VLogSite* cur_vlog_site_list = NULL;
......@@ -1414,7 +1416,7 @@ static bool validate_v(const char*, int32_t v) {
}
const bool ALLOW_UNUSED validate_v_dummy = google::RegisterFlagValidator(
&FLAGS_verbose, &validate_v);
&FLAGS_v, &validate_v);
static bool PassValidate(const char*, bool) {
return true;
......@@ -1431,10 +1433,12 @@ static bool NonNegativeInteger(const char*, int32_t v) {
}
const bool ALLOW_UNUSED validate_min_log_level = google::RegisterFlagValidator(
&FLAGS_min_log_level, NonNegativeInteger);
&FLAGS_minloglevel, NonNegativeInteger);
} // namespace logging
std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) {
return out << butil::WideToUTF8(std::wstring(wstr));
}
#endif // BRPC_WITH_GLOG
This diff is collapsed.
......@@ -94,7 +94,7 @@ bool FileDescriptorTableInjection::Move(int src, int dest) {
void FileDescriptorTableInjection::Close(int fd) {
int ret = IGNORE_EINTR(close(fd));
DPCHECK(ret == 0);
DCHECK(ret == 0);
}
} // namespace butil
......@@ -91,9 +91,9 @@ sigset_t SetSignalMask(const sigset_t& new_sigmask) {
// but Android's pthread_sigmask() was broken until 4.1:
// https://code.google.com/p/android/issues/detail?id=15337
// http://stackoverflow.com/questions/13777109/pthread-sigmask-on-android-not-working
RAW_CHECK(sigprocmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0);
RAW_CHECK(sigprocmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0, "");
#else
RAW_CHECK(pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0);
RAW_CHECK(pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0, "");
#endif
return old_sigmask;
}
......@@ -157,7 +157,7 @@ void ResetChildSignalHandlersToDefaults(void) {
// If the number of signals in the Linux kernel changes, someone should
// look at this code.
const int kNumberOfSignals = 64;
RAW_CHECK(signum == kNumberOfSignals + 1);
RAW_CHECK(signum == kNumberOfSignals + 1, "");
#endif // !defined(NDEBUG)
break;
}
......@@ -311,7 +311,7 @@ bool LaunchProcess(const std::vector<std::string>& argv,
// process, so we check that a thread is not being created by mistake
// and that signal handling follows the process-creation rules.
RAW_CHECK(
!(options.clone_flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM)));
!(options.clone_flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM)), "");
pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0);
} else
#endif
......
......@@ -16,7 +16,7 @@
// and we should _never_ include any logging code that is active in production
// builds. Most notably, we should not include these logging functions in
// unofficial release builds, even though those builds would otherwise have
// DCHECKS() enabled.
// DEBUG_CHECKS() enabled.
// In other words; please do not remove the #ifdef around this #include.
// Instead, in production builds we opt for returning a degraded result,
// whenever an error is encountered.
......@@ -31,7 +31,7 @@
#include "butil/logging.h"
#define DEBUG_CHECK RAW_CHECK
#else
#define DEBUG_CHECK(x) do { if (x) { } } while (0)
#define DEBUG_CHECK(x, msg) do { if (x) { } } while (0)
#endif
namespace butil {
......@@ -118,8 +118,8 @@ class Buffer {
static_cast<size_t>(std::numeric_limits<ssize_t>::max()),
kSSizeMax_is_the_max_value_of_an_ssize_t);
#endif
DEBUG_CHECK(size > 0);
DEBUG_CHECK(size <= kSSizeMax);
DEBUG_CHECK(size > 0, "");
DEBUG_CHECK(size <= kSSizeMax, "");
}
~Buffer() {
......@@ -144,7 +144,7 @@ class Buffer {
// |size_|, if the caller provided an insufficiently large output buffer.
// But it will never be bigger than |kSSizeMax-1|.
inline ssize_t GetCount() const {
DEBUG_CHECK(count_ < kSSizeMax);
DEBUG_CHECK(count_ < kSSizeMax, "");
return static_cast<ssize_t>(count_);
}
......@@ -173,8 +173,8 @@ class Buffer {
// Returns "false", iff the the |buffer_| filled up (i.e. |count_|
// overflowed |size_|) at any time during padding.
inline bool Pad(char pad, size_t padding, size_t len) {
DEBUG_CHECK(pad);
DEBUG_CHECK(padding <= kSSizeMax);
DEBUG_CHECK(pad, "");
DEBUG_CHECK(padding <= kSSizeMax, "");
for (; padding > len; --padding) {
if (!Out(pad)) {
if (--padding) {
......@@ -229,7 +229,7 @@ class Buffer {
// the range 1..kSSizeMax-1.
// This allows us to compute "kSSizeMax - 1 - inc" without incurring any
// integer overflows.
DEBUG_CHECK(inc <= kSSizeMax - 1);
DEBUG_CHECK(inc <= kSSizeMax - 1, "");
if (count_ > kSSizeMax - 1 - inc) {
count_ = kSSizeMax - 1;
return false;
......@@ -276,12 +276,12 @@ bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base,
char pad, size_t padding, const char* prefix) {
// Sanity check for parameters. None of these should ever fail, but see
// above for the rationale why we can't call CHECK().
DEBUG_CHECK(base >= 2);
DEBUG_CHECK(base <= 16);
DEBUG_CHECK(!sign || base == 10);
DEBUG_CHECK(pad == '0' || pad == ' ');
DEBUG_CHECK(padding <= kSSizeMax);
DEBUG_CHECK(!(sign && prefix && *prefix));
DEBUG_CHECK(base >= 2, "");
DEBUG_CHECK(base <= 16, "");
DEBUG_CHECK(!sign || base == 10, "");
DEBUG_CHECK(pad == '0' || pad == ' ', "");
DEBUG_CHECK(padding <= kSSizeMax, "");
DEBUG_CHECK(!(sign && prefix && *prefix), "");
// Handle negative numbers, if the caller indicated that |i| should be
// treated as a signed number; otherwise treat |i| as unsigned (even if the
......@@ -461,7 +461,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
if (padding > max_padding/10 ||
10*padding > max_padding - (ch - '0')) {
DEBUG_CHECK(padding <= max_padding/10 &&
10*padding <= max_padding - (ch - '0'));
10*padding <= max_padding - (ch - '0'), "");
// Integer overflow detected. Skip the rest of the width until
// we find the format character, then do the normal error handling.
padding_overflow:
......@@ -479,7 +479,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
// kSSizeMax gets smaller than about 10, our earlier range checks
// are incomplete. Unittests do trigger this artificial corner
// case.
DEBUG_CHECK(padding <= max_padding);
DEBUG_CHECK(padding <= max_padding, "");
goto padding_overflow;
}
ch = *fmt++;
......@@ -493,14 +493,14 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
case 'c': { // Output an ASCII character.
// Check that there are arguments left to be inserted.
if (cur_arg >= max_args) {
DEBUG_CHECK(cur_arg < max_args);
DEBUG_CHECK(cur_arg < max_args, "");
goto fail_to_expand;
}
// Check that the argument has the expected type.
const Arg& arg = args[cur_arg++];
if (arg.type != Arg::INT && arg.type != Arg::UINT) {
DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT);
DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT, "");
goto fail_to_expand;
}
......@@ -521,7 +521,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
case 'p': { // Output a pointer value.
// Check that there are arguments left to be inserted.
if (cur_arg >= max_args) {
DEBUG_CHECK(cur_arg < max_args);
DEBUG_CHECK(cur_arg < max_args, "");
goto fail_to_expand;
}
......@@ -531,7 +531,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
if (ch != 'p') {
// Check that the argument has the expected type.
if (arg.type != Arg::INT && arg.type != Arg::UINT) {
DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT);
DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT, "");
goto fail_to_expand;
}
i = arg.i;
......@@ -558,7 +558,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
arg.i == 0) { // Allow C++'s version of NULL
i = 0;
} else {
DEBUG_CHECK(arg.type == Arg::POINTER || arg.type == Arg::STRING);
DEBUG_CHECK(arg.type == Arg::POINTER || arg.type == Arg::STRING, "");
goto fail_to_expand;
}
......@@ -579,7 +579,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
case 's': {
// Check that there are arguments left to be inserted.
if (cur_arg >= max_args) {
DEBUG_CHECK(cur_arg < max_args);
DEBUG_CHECK(cur_arg < max_args, "");
goto fail_to_expand;
}
......@@ -592,7 +592,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
arg.i == 0) { // Allow C++'s version of NULL
s = "<NULL>";
} else {
DEBUG_CHECK(arg.type == Arg::STRING);
DEBUG_CHECK(arg.type == Arg::STRING, "");
goto fail_to_expand;
}
......@@ -631,7 +631,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
// Unknown or unsupported format character. Just copy verbatim to
// output.
buffer.Out('%');
DEBUG_CHECK(ch);
DEBUG_CHECK(ch, "");
if (!ch) {
goto end_of_format_string;
}
......@@ -670,7 +670,7 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt) {
const char* src = fmt;
for (; *src; ++src) {
buffer.Out(*src);
DEBUG_CHECK(src[0] != '%' || src[1] == '%');
DEBUG_CHECK(src[0] != '%' || src[1] == '%', "");
if (src[0] == '%' && src[1] == '%') {
++src;
}
......
......@@ -81,6 +81,7 @@
#endif
#include <errno.h> /* for EINVAL */
#include <time.h>
#include <limits.h> /* INT_MAX */
/* Implements the Unix localtime_r() function for windows */
#if defined(OS_WIN)
......
......@@ -16,9 +16,10 @@
// Date: Mon. Nov 7 14:47:36 CST 2011
#include <errno.h> // errno
#include <vector> // std::vector
#include <algorithm> // std::find
#include <pthread.h> // pthread_key_t
#include <stdio.h>
#include <algorithm> // std::find
#include <vector> // std::vector
namespace butil {
namespace detail {
......
......@@ -65,7 +65,6 @@ public:
}
}
~SamplerCollector() {
VLOG(99) << "SamplerCollector is quiting";
if (_created) {
_stop = true;
pthread_join(_tid, NULL);
......@@ -93,7 +92,6 @@ private:
};
void SamplerCollector::run() {
VLOG(99) << "SamplerCollector starts to run";
butil::LinkNode<Sampler> root;
int consecutive_nosleep = 0;
PassiveStatus<double> cumulated_time(get_cumulated_time, this);
......
......@@ -232,24 +232,25 @@ private:
inline IntRecorder& IntRecorder::operator<<(int64_t sample) {
if (BAIDU_UNLIKELY((int64_t)(int)sample != sample)) {
const char* reason = NULL;
if (sample > std::numeric_limits<int>::max()) {
reason = "overflows";
sample = std::numeric_limits<int>::max();
} else {
reason = "underflows";
sample = std::numeric_limits<int>::min();
}
// Truncate to be max or min of int. We're using 44 bits to store the
// sum thus following aggregations are not likely to be over/underflow.
if (!name().empty()) {
LOG(WARNING) << "Input=" << sample << " to `" << name()
<< '\'' << noflush;
<< "\' " << reason;
} else if (!_debug_name.empty()) {
LOG(WARNING) << "Input=" << sample << " to `" << _debug_name
<< '\'' << noflush;
<< "\' " << reason;
} else {
LOG(WARNING) << "Input=" << sample << " to IntRecorder("
<< (void*)this << ')' << noflush;
}
if (sample > std::numeric_limits<int>::max()) {
LOG(WARNING) << " overflows";
sample = std::numeric_limits<int>::max();
} else {
LOG(WARNING) << " underflows";
sample = std::numeric_limits<int>::min();
<< (void*)this << ") " << reason;
}
}
agent_type* agent = _combiner.get_or_create_tls_agent();
......
......@@ -2,9 +2,9 @@ NEED_GPERFTOOLS=1
NEED_GTEST=1
NEED_GMOCK=1
include ../config.mk
CPPFLAGS=-DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__= -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
CPPFLAGS+=-DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__= -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
CPPFLAGS+=-DUNIT_TEST -Dprivate=public -Dprotected=public -DBVAR_NOT_LINK_DEFAULT_VARIABLES
CXXFLAGS=$(CPPFLAGS) -g -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer -std=c++0x
CXXFLAGS+=$(CPPFLAGS) -g -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer -std=c++0x
#required by butil/crc32.cc to boost performance for 10x
ifeq ($(shell test $(GCC_VERSION) -ge 40400; echo $$?),0)
......
......@@ -8,7 +8,7 @@
#include <sys/socket.h>
#include <fstream>
#include <gtest/gtest.h>
#include <google/gflags.h>
#include <gflags/gflags.h>
#include <gperftools/profiler.h>
#include <google/protobuf/descriptor.h>
#include "butil/time.h"
......@@ -182,6 +182,7 @@ protected:
}
void TestVLog(bool use_html) {
#if !BRPC_WITH_GLOG
std::string expect_type = (use_html ? "text/html" : "text/plain");
brpc::VLogService service;
brpc::VLogRequest req;
......@@ -194,6 +195,7 @@ protected:
EXPECT_FALSE(cntl.Failed());
EXPECT_EQ(expect_type, cntl.http_response().content_type());
CheckContent(cntl, "test_builtin_service");
#endif
}
void TestConnections(bool use_html) {
......
......@@ -218,7 +218,7 @@ void* select_server(void* arg) {
}
++(*selected_count)[ptr->id()];
}
LOG_IF(TRACE, ret != 0) << "select_server[" << pthread_self()
LOG_IF(INFO, ret != 0) << "select_server[" << pthread_self()
<< "] quits before of " << berror(ret);
return selected_count;
}
......
......@@ -1194,7 +1194,9 @@ TEST_F(ServerTest, add_builtin_service) {
if (brpc::FLAGS_enable_threads_service) {
TestAddBuiltinService(brpc::ThreadsService::descriptor());
}
#if !BRPC_WITH_GLOG
TestAddBuiltinService(brpc::VLogService::descriptor());
#endif
TestAddBuiltinService(brpc::FlagsService::descriptor());
TestAddBuiltinService(brpc::VarsService::descriptor());
TestAddBuiltinService(brpc::RpczService::descriptor());
......@@ -1247,8 +1249,10 @@ TEST_F(ServerTest, too_big_message) {
brpc::SERVER_DOESNT_OWN_SERVICE));
ASSERT_EQ(0, server.Start(8613, NULL));
#if !BRPC_WITH_GLOG
logging::StringSink log_str;
logging::LogSink* old_sink = logging::SetLogSink(&log_str);
#endif
brpc::Channel chan;
ASSERT_EQ(0, chan.Init("localhost:8613", NULL));
......@@ -1260,12 +1264,14 @@ TEST_F(ServerTest, too_big_message) {
stub.Echo(&cntl, &req, &res, NULL);
EXPECT_TRUE(cntl.Failed());
#if !BRPC_WITH_GLOG
ASSERT_EQ(&log_str, logging::SetLogSink(old_sink));
std::ostringstream expected_log;
expected_log << " is bigger than " << brpc::FLAGS_max_body_size
<< " bytes, the connection will be closed."
" Set max_body_size to allow bigger messages";
ASSERT_NE(std::string::npos, log_str.find(expected_log.str()));
#endif
server.Stop(0);
server.Join();
......
......@@ -4,7 +4,7 @@
// Date: Sun Jul 13 15:04:18 CST 2014
#include <gtest/gtest.h>
#include <google/gflags.h>
#include <gflags/gflags.h>
#include <gperftools/profiler.h>
#include "brpc/socket.h"
#include "brpc/socket_map.h"
......
......@@ -207,7 +207,7 @@ static void* locker(void* arg) {
bthread_usleep(2000);
EXPECT_EQ(0, bthread_id_unlock(id));
tm.stop();
LOG(TRACE) << "Unlocked, tm=" << tm.u_elapsed();
LOG(INFO) << "Unlocked, tm=" << tm.u_elapsed();
return NULL;
}
......
......@@ -53,12 +53,8 @@ public:
_sleep_ms = 0;
bthread::futex_wake_private(&_sleep_ms, 1);
} else {
LOG(ERROR) << "No need to wakeup " << noflush;
if (_name) {
LOG(ERROR) << "`" << _name << "' task_id=" << _task_id;
} else {
LOG(ERROR) << "task_id=" << _task_id;
}
LOG(ERROR) << "No need to wakeup "
<< (_name ? _name : "") << " task_id=" << _task_id;
}
}
......
......@@ -33,6 +33,8 @@ int main(int argc, char** argv) {
core_limit.rlim_max = 0;
setrlimit(RLIMIT_CORE, &core_limit);
}
#if !BRPC_WITH_GLOG
CHECK(!google::SetCommandLineOption("crash_on_fatal_log", "true").empty());
#endif
return RUN_ALL_TESTS();
}
......@@ -192,6 +192,7 @@ void ReducerTest_window() {
bvar::Window<bvar::Miner<int> > w8(&c3, 2);
bvar::Window<bvar::Miner<int> > w9(&c3, 3);
#if !BRPC_WITH_GLOG
logging::StringSink log_str;
logging::LogSink* old_sink = logging::SetLogSink(&log_str);
c2.get_value();
......@@ -200,6 +201,7 @@ void ReducerTest_window() {
"You should not call Reducer<int, bvar::detail::MaxTo<int>>"
"::get_value() when a Window<> is used because the operator"
" does not have inverse."));
#endif
const int N = 6000;
int count = 0;
int total_count = 0;
......@@ -233,6 +235,7 @@ void ReducerTest_window() {
}
TEST_F(ReducerTest, window) {
#if !BRPC_WITH_GLOG
ReducerTest_window();
logging::StringSink log_str;
logging::LogSink* old_sink = logging::SetLogSink(&log_str);
......@@ -241,6 +244,7 @@ TEST_F(ReducerTest, window) {
if (log_str.find("Removed ") != std::string::npos) {
ASSERT_NE(std::string::npos, log_str.find("Removed 3, sampled 0")) << log_str;
}
#endif
}
struct Foo {
......
......@@ -51,8 +51,10 @@ private:
int DebugSampler::_s_ndestroy = 0;
TEST(SamplerTest, single_threaded) {
#if !BRPC_WITH_GLOG
logging::StringSink log_str;
logging::LogSink* old_sink = logging::SetLogSink(&log_str);
#endif
const int N = 100;
DebugSampler* s[N];
for (int i = 0; i < N; ++i) {
......@@ -69,11 +71,13 @@ TEST(SamplerTest, single_threaded) {
}
usleep(1010000);
EXPECT_EQ(N, DebugSampler::_s_ndestroy);
#if !BRPC_WITH_GLOG
ASSERT_EQ(&log_str, logging::SetLogSink(old_sink));
if (log_str.find("Removed ") != std::string::npos) {
ASSERT_NE(std::string::npos, log_str.find("Removed 0, sampled 100"));
ASSERT_NE(std::string::npos, log_str.find("Removed 100, sampled 0"));
}
#endif
}
void* check(void*) {
......@@ -94,8 +98,10 @@ void* check(void*) {
}
TEST(SamplerTest, multi_threaded) {
#if !BRPC_WITH_GLOG
logging::StringSink log_str;
logging::LogSink* old_sink = logging::SetLogSink(&log_str);
#endif
pthread_t th[10];
DebugSampler::_s_ndestroy = 0;
for (size_t i = 0; i < arraysize(th); ++i) {
......@@ -106,10 +112,12 @@ TEST(SamplerTest, multi_threaded) {
}
sleep(1);
EXPECT_EQ(100 * arraysize(th), (size_t)DebugSampler::_s_ndestroy);
#if !BRPC_WITH_GLOG
ASSERT_EQ(&log_str, logging::SetLogSink(old_sink));
if (log_str.find("Removed ") != std::string::npos) {
ASSERT_NE(std::string::npos, log_str.find("Removed 0, sampled 1000"));
ASSERT_NE(std::string::npos, log_str.find("Removed 1000, sampled 0"));
}
#endif
}
} // namespace
......@@ -24,7 +24,7 @@ protected:
TEST_F(ClassNameTest, demangle) {
ASSERT_EQ("add_something", butil::demangle("add_something"));
ASSERT_EQ("guard variable for butil::my_ip()::ip",
butil::demangle("_ZGVZN4base5my_ipEvE2ip"));
butil::demangle("_ZGVZN5butil5my_ipEvE2ip"));
ASSERT_EQ("dp::FiberPBCommand<proto::PbRouteTable, proto::PbRouteAck>::marshal(dp::ParamWriter*)::__FUNCTION__",
butil::demangle("_ZZN2dp14FiberPBCommandIN5proto12PbRouteTableENS1_10PbRouteAckEE7marshalEPNS_11ParamWriterEE12__FUNCTION__"));
ASSERT_EQ("7&8", butil::demangle("7&8"));
......
......@@ -23,7 +23,6 @@ TEST_F(FileWatcherTest, random_op)
for (int i=0; i<30; ++i) {
if (rand() % 2) {
LOG(INFO) << "watch: " << noflush;
const butil::FileWatcher::Change ret = fw.check_and_consume();
switch (ret) {
case butil::FileWatcher::UPDATED:
......@@ -39,7 +38,6 @@ TEST_F(FileWatcherTest, random_op)
LOG(INFO) << fw.filepath() << " does not change or still not exist";
break;
}
LOG(INFO);
}
switch (rand() % 2) {
......
......@@ -9,9 +9,11 @@
#include <gtest/gtest.h>
#include <gflags/gflags.h>
#if !BRPC_WITH_GLOG
namespace logging {
DECLARE_bool(crash_on_fatal_log);
DECLARE_int32(verbose);
DECLARE_int32(v);
namespace {
......@@ -52,10 +54,10 @@ public:
}
virtual void TearDown() {
::logging::FLAGS_crash_on_fatal_log = _old_crash_on_fatal_log;
if (::logging::FLAGS_verbose != 0) {
if (::logging::FLAGS_v != 0) {
// Clear -verbose to avoid affecting other tests.
ASSERT_FALSE(google::SetCommandLineOption("verbose", "0").empty());
ASSERT_FALSE(google::SetCommandLineOption("verbose_module", "").empty());
ASSERT_FALSE(google::SetCommandLineOption("v", "0").empty());
ASSERT_FALSE(google::SetCommandLineOption("vmodule", "").empty());
}
}
private:
......@@ -203,7 +205,7 @@ TEST_F(LoggingTest, DebugLoggingReleaseBehavior) {
TEST_F(LoggingTest, DcheckStreamsAreLazy) {
MockLogSource mock_log_source;
EXPECT_CALL(mock_log_source, Log()).Times(0);
#if DCHECK_IS_ON
#if DCHECK_IS_ON()
DCHECK(true) << mock_log_source.Log();
DCHECK_EQ(0, 0) << mock_log_source.Log();
#else
......@@ -218,27 +220,27 @@ TEST_F(LoggingTest, DcheckStreamsAreLazy) {
TEST_F(LoggingTest, Dcheck) {
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
// Release build.
EXPECT_FALSE(DCHECK_IS_ON);
EXPECT_FALSE(DCHECK_IS_ON());
EXPECT_FALSE(DLOG_IS_ON(DCHECK));
#elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
// Release build with real DCHECKS.
SetLogAssertHandler(&LogSink);
EXPECT_TRUE(DCHECK_IS_ON);
EXPECT_TRUE(DCHECK_IS_ON());
EXPECT_FALSE(DLOG_IS_ON(DCHECK));
#else
// Debug build.
SetLogAssertHandler(&LogSink);
EXPECT_TRUE(DCHECK_IS_ON);
EXPECT_TRUE(DCHECK_IS_ON());
EXPECT_TRUE(DLOG_IS_ON(DCHECK));
#endif
EXPECT_EQ(0, log_sink_call_count);
DCHECK(false);
EXPECT_EQ(DCHECK_IS_ON ? 1 : 0, log_sink_call_count);
EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count);
DPCHECK(false);
EXPECT_EQ(DCHECK_IS_ON ? 2 : 0, log_sink_call_count);
EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count);
DCHECK_EQ(0, 1);
EXPECT_EQ(DCHECK_IS_ON ? 3 : 0, log_sink_call_count);
EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count);
}
TEST_F(LoggingTest, DcheckReleaseBehavior) {
......@@ -312,11 +314,11 @@ TEST_F(LoggingTest, log_at) {
TEST_F(LoggingTest, vlog_sanity) {
::logging::FLAGS_crash_on_fatal_log = false;
EXPECT_FALSE(google::SetCommandLineOption("verbose", "1").empty());
EXPECT_FALSE(google::SetCommandLineOption("v", "1").empty());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"logging_unittest=1").empty());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"logging_UNITTEST=2").empty());
for (int i = 0; i < 10; ++i) {
......@@ -332,7 +334,7 @@ TEST_F(LoggingTest, vlog_sanity) {
VLOG_NE(0) << "always on";
EXPECT_EQ("always on", LOG_STREAM(INFO).content_str());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"logging_unittest=0").empty());
for (int i = 0; i < 10; ++i) {
VLOG_NE(i) << "vlog " << i;
......@@ -340,7 +342,7 @@ TEST_F(LoggingTest, vlog_sanity) {
EXPECT_EQ("", LOG_STREAM(VERBOSE).content_str());
EXPECT_EQ("vlog 0", LOG_STREAM(INFO).content_str());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"logging_unittest=0,logging_unittest=1").empty());
for (int i = 0; i < 10; ++i) {
VLOG_NE(i) << "vlog " << i;
......@@ -348,7 +350,7 @@ TEST_F(LoggingTest, vlog_sanity) {
EXPECT_EQ("vlog 1", LOG_STREAM(VERBOSE).content_str());
EXPECT_EQ("vlog 0", LOG_STREAM(INFO).content_str());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"logging_unittest=1,logging_unittest=0").empty());
for (int i = 0; i < 10; ++i) {
VLOG_NE(i) << "vlog " << i;
......@@ -356,14 +358,14 @@ TEST_F(LoggingTest, vlog_sanity) {
EXPECT_EQ("", LOG_STREAM(VERBOSE).content_str());
EXPECT_EQ("vlog 0", LOG_STREAM(INFO).content_str());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module", "").empty());
EXPECT_FALSE(google::SetCommandLineOption("vmodule", "").empty());
for (int i = 0; i < 10; ++i) {
VLOG_NE(i) << "vlog " << i;
}
EXPECT_EQ("vlog 1", LOG_STREAM(VERBOSE).content_str());
EXPECT_EQ("vlog 0", LOG_STREAM(INFO).content_str());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"logg?ng_*=2").empty());
for (int i = 0; i < 10; ++i) {
VLOG_NE(i) << "vlog " << i;
......@@ -371,7 +373,7 @@ TEST_F(LoggingTest, vlog_sanity) {
EXPECT_EQ("vlog 1vlog 2", LOG_STREAM(VERBOSE).content_str());
EXPECT_EQ("vlog 0", LOG_STREAM(INFO).content_str());
EXPECT_FALSE(google::SetCommandLineOption("verbose_module",
EXPECT_FALSE(google::SetCommandLineOption("vmodule",
"foo=3,logging_unittest=3, logg?ng_*=2 , logging_*=1 ").empty());
for (int i = 0; i < 10; ++i) {
VLOG_NE(i) << "vlog " << i;
......@@ -385,7 +387,7 @@ TEST_F(LoggingTest, vlog_sanity) {
EXPECT_EQ("vlog 1vlog 3", LOG_STREAM(VERBOSE).content_str());
EXPECT_FALSE(google::SetCommandLineOption(
"verbose_module",
"vmodule",
"foo/bar0/0=2,foo/bar/1=3, 2=4, foo/*/3=5, */ba?/4=6,"
"/5=7,/foo/bar/6=8,foo2/bar/7=9,foo/bar/8=9").empty());
VLOG2_NE("foo/bar/0", 2) << " vlog0";
......@@ -461,8 +463,8 @@ TEST_F(LoggingTest, debug_level) {
DLOG(NOTICE) << foo(&run_foo);
DLOG(DEBUG) << foo(&run_foo);
EXPECT_FALSE(google::SetCommandLineOption("verbose_module", "").empty());
EXPECT_FALSE(google::SetCommandLineOption("verbose", "1").empty());
EXPECT_FALSE(google::SetCommandLineOption("vmodule", "").empty());
EXPECT_FALSE(google::SetCommandLineOption("v", "1").empty());
DVLOG(1) << foo(&run_foo);
DVLOG2("a/b/c", 1) << foo(&run_foo);
......@@ -522,3 +524,4 @@ TEST_F(LoggingTest, limited_logging) {
} // namespace
} // namespace logging
#endif
......@@ -209,10 +209,10 @@ TEST(RandUtilTest, fast_rand_perf) {
}
tm.stop();
LOG(INFO) << "Each fast_rand_less_than took " << tm.n_elapsed() / kTestIterations
<< " ns, " << s << noflush;
<< " ns, "
#if !defined(NDEBUG)
LOG(INFO) << " (debugging version)";
<< " (debugging version)";
#else
LOG(INFO);
;
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment