├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── build.sh ├── example ├── CMakeLists.txt ├── ace │ ├── CMakeLists.txt │ ├── logging │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ ├── logrecord.proto │ │ └── server.cpp │ └── ttcp │ │ ├── CMakeLists.txt │ │ ├── common.cpp │ │ ├── common.h │ │ ├── main.cpp │ │ ├── ttcp.cpp │ │ └── ttcp_blocking.cpp ├── asio │ ├── CMakeLists.txt │ ├── chat │ │ ├── CMakeLists.txt │ │ ├── ChatClient.cpp │ │ ├── ChatClientLoadTest.cpp │ │ ├── ChatServer.cpp │ │ ├── ChatServerEfficient.cpp │ │ ├── ChatServerHighPerformance.cpp │ │ ├── ChatServerThreaded.cpp │ │ └── Codec.h │ └── timer │ │ ├── CMakeLists.txt │ │ ├── timer2.cpp │ │ ├── timer3.cpp │ │ ├── timer4.cpp │ │ ├── timer5.cpp │ │ └── timer6.cpp ├── cdns │ ├── CMakeLists.txt │ ├── Resolver.cpp │ ├── Resolver.h │ └── dns.cpp ├── curl │ ├── CMakeLists.txt │ ├── Curl.cpp │ ├── Curl.h │ ├── download.cpp │ └── mcurl.cpp ├── fastcgi │ ├── CMakeLists.txt │ ├── FastCgi.cpp │ ├── FastCgi.h │ └── FastCgiTest.cpp ├── filetransfer │ ├── CMakeLists.txt │ ├── Download.cpp │ ├── Download2.cpp │ └── Download3.cpp ├── hiredis │ ├── CMakeLists.txt │ ├── Hiredis.cpp │ ├── Hiredis.h │ └── mredis_client.cpp ├── hub │ ├── CMakeLists.txt │ ├── Codec.cpp │ ├── Codec.h │ ├── Pub.cpp │ ├── PubSubClient.cpp │ ├── PubSubClient.h │ ├── PubSubServer.cpp │ └── Sub.cpp ├── idleconnection │ ├── CMakeLists.txt │ ├── EchoServer.cpp │ ├── EchoServer.h │ ├── EchoServer_sorted.cpp │ └── main.cpp ├── maxconnection │ ├── CMakeLists.txt │ └── MaxConnection.cpp ├── memcached │ ├── CMakeLists.txt │ ├── client │ │ ├── CMakeLists.txt │ │ └── client.cpp │ └── server │ │ ├── CMakeLists.txt │ │ ├── Item.cpp │ │ ├── Item.h │ │ ├── MemcacheServer.cpp │ │ ├── MemcacheServer.h │ │ ├── Session.cpp │ │ ├── Session.h │ │ ├── footprint_test.cpp │ │ └── server.cpp ├── multiplexer │ ├── CMakeLists.txt │ ├── Demux.cpp │ ├── MultiplexServer.cpp │ └── MultiplexServer_simple.cpp ├── netty │ ├── CMakeLists.txt │ ├── discard │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ └── server.cpp │ ├── echo │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── server2.cpp │ └── uptime │ │ ├── CMakeLists.txt │ │ └── client.cpp ├── pingpong │ ├── BenchMark.cpp │ ├── CMakeLists.txt │ ├── client.cpp │ └── server.cpp ├── procmon │ ├── CMakeLists.txt │ ├── dummyload.cpp │ ├── plot.cpp │ ├── plot.h │ ├── plot_test.cpp │ └── procmon.cpp ├── protobuf │ ├── CMakeLists.txt │ ├── codec │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ ├── codec.cpp │ │ ├── codec.h │ │ ├── codec_test.cpp │ │ ├── dispatcher.h │ │ ├── dispatcher_lite.h │ │ ├── dispatcher_lite_test.cpp │ │ ├── dispatcher_test.cpp │ │ ├── query.proto │ │ └── server.cpp │ ├── resolver │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ ├── resolver.proto │ │ └── server.cpp │ ├── rpc │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── sudoku.proto │ ├── rpcbalancer │ │ ├── CMakeLists.txt │ │ ├── balancer.cpp │ │ └── balancer_raw.cpp │ └── rpcbench │ │ ├── CMakeLists.txt │ │ ├── client.cpp │ │ ├── echo.proto │ │ └── server.cpp ├── roundtrip │ ├── CMakeLists.txt │ ├── Roundtrip.cpp │ └── RoundtripUdp.cpp ├── shorturl │ ├── CMakeLists.txt │ └── ShortUrl.cpp ├── simple │ ├── CMakeLists.txt │ ├── all_in_one │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── chargen │ │ ├── CMakeLists.txt │ │ ├── ChargenClient.cpp │ │ ├── ChargenClient.h │ │ ├── ChargenServer.cpp │ │ ├── ChargenServer.h │ │ ├── client.cpp │ │ └── server.cpp │ ├── daytime │ │ ├── CMakeLists.txt │ │ ├── DaytimeServer.cpp │ │ ├── DaytimeServer.h │ │ ├── client.cpp │ │ └── server.cpp │ ├── discard │ │ ├── CMakeLists.txt │ │ ├── DiscardServer.cpp │ │ ├── DiscardServer.h │ │ ├── client.cpp │ │ └── server.cpp │ ├── echo │ │ ├── CMakeLists.txt │ │ ├── EchoClient.cpp │ │ ├── EchoClient.h │ │ ├── EchoServer.cpp │ │ ├── EchoServer.h │ │ ├── client.cpp │ │ └── server.cpp │ └── time │ │ ├── CMakeLists.txt │ │ ├── TimeServer.cpp │ │ ├── TimeServer.h │ │ ├── client.cpp │ │ └── server.cpp ├── socks4a │ ├── CMakeLists.txt │ ├── balancer.cpp │ ├── socks4a.cpp │ ├── tcprelay.cpp │ └── tunnel.h ├── twisted │ ├── CMakeLists.txt │ └── finger │ │ ├── CMakeLists.txt │ │ ├── finger1.cpp │ │ ├── finger2.cpp │ │ ├── finger3.cpp │ │ ├── finger4.cpp │ │ ├── finger5.cpp │ │ ├── finger6.cpp │ │ └── finger7.cpp ├── wordcount │ ├── CMakeLists.txt │ ├── gen.py │ ├── hash.cpp │ ├── hash.h │ ├── receiver.cpp │ └── slowsink.py └── zeromq │ ├── CMakeLists.txt │ ├── codec.h │ ├── local_lat.cpp │ └── remote_lat.cpp ├── src ├── CMakeLists.txt └── blink │ ├── Acceptor.cpp │ ├── Acceptor.h │ ├── AsyncLog.cpp │ ├── AsyncLog.h │ ├── Atomic.h │ ├── BlockingQueue.h │ ├── BoundedBlockingQueue.h │ ├── Buffer.cpp │ ├── Buffer.h │ ├── CMakeLists.txt │ ├── Callbacks.h │ ├── Channel.cpp │ ├── Channel.h │ ├── Condition.cpp │ ├── Condition.h │ ├── Connector.cpp │ ├── Connector.h │ ├── Copyable.h │ ├── CountDownLatch.cpp │ ├── CountDownLatch.h │ ├── CurrentThread.cpp │ ├── CurrentThread.h │ ├── Date.cpp │ ├── Date.h │ ├── Endian.h │ ├── EventLoop.cpp │ ├── EventLoop.h │ ├── EventLoopThread.cpp │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cpp │ ├── EventLoopThreadPool.h │ ├── Exception.cpp │ ├── Exception.h │ ├── FileTool.cpp │ ├── FileTool.h │ ├── GzipFile.h │ ├── InetAddress.cpp │ ├── InetAddress.h │ ├── Log.cpp │ ├── Log.h │ ├── LogFile.cpp │ ├── LogFile.h │ ├── LogStream.cpp │ ├── LogStream.h │ ├── MutexLock.cpp │ ├── MutexLock.h │ ├── Nocopyable.h │ ├── Poller.cpp │ ├── Poller.h │ ├── ProcessBase.cpp │ ├── ProcessBase.h │ ├── ProcessInfo.cpp │ ├── ProcessInfo.h │ ├── Rio.cpp │ ├── Rio.h │ ├── Singleton.h │ ├── Socket.cpp │ ├── Socket.h │ ├── SocketBase.cpp │ ├── SocketBase.h │ ├── StringPiece.h │ ├── TcpClient.cpp │ ├── TcpClient.h │ ├── TcpConnection.cpp │ ├── TcpConnection.h │ ├── TcpServer.cpp │ ├── TcpServer.h │ ├── Thread.cpp │ ├── Thread.h │ ├── ThreadBase.cpp │ ├── ThreadBase.h │ ├── ThreadLocal.h │ ├── ThreadLocalSingleton.h │ ├── ThreadPool.cpp │ ├── ThreadPool.h │ ├── TimeZone.cpp │ ├── TimeZone.h │ ├── Timer.cpp │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cpp │ ├── TimerQueue.h │ ├── Timestamp.cpp │ ├── Timestamp.h │ ├── Types.h │ ├── WeakCallback.h │ ├── ZlibStream.h │ ├── http │ ├── CMakeLists.txt │ ├── HttpContext.cpp │ ├── HttpContext.h │ ├── HttpRequest.cpp │ ├── HttpRequest.h │ ├── HttpResponse.cpp │ ├── HttpResponse.h │ ├── HttpServer.cpp │ └── HttpServer.h │ ├── inspect │ ├── CMakeLists.txt │ ├── Inspector.cpp │ ├── Inspector.h │ ├── PerformanceInspector.cpp │ ├── PerformanceInspector.h │ ├── ProcessInspector.cpp │ ├── ProcessInspector.h │ ├── SystemInspector.cpp │ └── SystemInspector.h │ ├── protobuf │ ├── BufferStream.h │ ├── CMakeLists.txt │ ├── ProtobufCodecLite.cpp │ └── ProtobufCodecLite.h │ └── protorpc │ ├── CMakeLists.txt │ ├── RpcChannel.cpp │ ├── RpcChannel.h │ ├── RpcCodec.cpp │ ├── RpcCodec.h │ ├── RpcServer.cpp │ ├── RpcServer.h │ ├── google-inl.h │ ├── rpc.proto │ └── rpcservice.proto └── test ├── AcceptorTest.cpp ├── AsyncLogTest.cpp ├── AtomicTest.cpp ├── BlockingQueueTest.cpp ├── BoundedBlockingQueueTest.cpp ├── Buffer_BoostTest.cpp ├── Buffer_GoogleTest.cpp ├── CMakeLists.txt ├── CountDownLatchTest.cpp ├── DateTest.cpp ├── EventLoopTest.cpp ├── EventLoopThreadPoolTest.cpp ├── EventLoopThreadTest.cpp ├── ExceptionTest.cpp ├── FileToolTest.cpp ├── GzipFileTest.cpp ├── HttpRequest_unittest.cpp ├── HttpServerTest.cpp ├── InetAddressTest.cpp ├── InspectorTest.cpp ├── LogFileTest.cpp ├── LogStreamTest.cpp ├── LogTest.cpp ├── ProcessInfoTest.cpp ├── RpcCodecTest.cpp ├── SingletonTest.cpp ├── StringPieceTest.cpp ├── TcpClientTest.cpp ├── TcpServerTest.cpp ├── ThreadLocalSingletonTest.cpp ├── ThreadLocalTest.cpp ├── ThreadPoolTest.cpp ├── ThreadTest.cpp ├── TimeZoneTest.cpp ├── TimerQueueTest.cpp ├── TimestampTest.cpp ├── WeakCallbackTest.cpp ├── ZlibStreamTest.cpp ├── echoclient_test.cpp └── echoserver_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | *.pb.* 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blink 2 | ------- 3 | * A C++ network library imitate muduo. 4 | * Add some features for personal preference. 5 | 6 | #Evironment 7 | ----------- 8 | 9 | * **Linux only**. 10 | * It runs on Linux with kernel 2.6.28 at least for epoll, new syscall, new flag. 11 | * eg. eventfd, timerfd, O_CLOEXEC. 12 | 13 | * **It also need boost library**. 14 | 15 | #Compiler 16 | --------- 17 | 18 | * **g++ only**. 19 | 20 | # Build 21 | ------- 22 | 23 | **It must be built by cmake >= 2.6 at least** 24 | 25 | **To compile release library into /lib/release, release examples and test into bin/release:** 26 | 27 | ``` 28 | ./build.sh 29 | BUILD_TYPE=release ./build.sh 30 | ``` 31 | 32 | **To compile library into /lib/debug(release), examples and test into bin/debug(release):** 33 | 34 | ``` 35 | BUILD_TYPE=debug ./build.sh 36 | ``` 37 | 38 | **To install libraries and headers into the specified directory, such as:** 39 | 40 | ``` 41 | INSTALL_DIR=/usr/local ./build.sh install 42 | BUILD_TYPE=debug INSTALL_DIR=/usr ./build.sh install 43 | ``` 44 | 45 | Libraries and headers will be installed into `debug(release)-install` default, if you haven't specified any directory. 46 | 47 | **You can also add BUILD_NO_EXAMPLES or BUILD_NO_TEST in head, if you don't wanna build exmaples or test. Such as:** 48 | 49 | ``` 50 | BUILD_TYPE=debug BUILD_NO_EXAMPLES=true ./build.sh 51 | BUILD_NO_TEST=true ./build.sh 52 | BUILD_TYPE=debug BUILD_NO_EXAMPLES=true BUILD_NO_TEST=true ./build.sh 53 | ``` 54 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | CURRENT_DIR=`pwd` 6 | BUILD_TYPE=${BUILD_TYPE:-release} 7 | BUILD_BIR=${CURRENT_DIR}/build/${BUILD_TYPE} 8 | BUILD_NO_EXAMPLES=${BUILD_NO_EXAMPLES:-0} 9 | BUILD_NO_TEST=${BUILD_NO_TEST:-0} 10 | INSTALL_DIR=${INSTALL_DIR:-${CURRENT_DIR}/${BUILD_TYPE}-install} 11 | 12 | if [ ${BUILD_TYPE} != "release" ] && [ ${BUILD_TYPE} != "debug" ] 13 | then 14 | echo "Usage: BUILD_TYPE=debug/release" 15 | else 16 | mkdir -p ${BUILD_BIR} 17 | cd ${BUILD_BIR} 18 | cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ 19 | -DCMAKE_BUILD_NO_EXAMPLES=${BUILD_NO_EXAMPLES} \ 20 | -DCMAKE_BUILD_NO_TEST=${BUILD_NO_TEST} \ 21 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 22 | ${CURRENT_DIR} 23 | make $* 24 | fi 25 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(ace) 2 | add_subdirectory(asio) 3 | 4 | if(CARES_INCLUDE_DIR AND CARES_LIBRARY) 5 | add_subdirectory(cdns) 6 | else() 7 | add_subdirectory(cdns EXCLUDE_FROM_ALL) 8 | endif() 9 | 10 | if(CURL_FOUND) 11 | add_subdirectory(curl) 12 | else() 13 | add_subdirectory(curl EXCLUDE_FROM_ALL) 14 | endif() 15 | 16 | add_subdirectory(fastcgi) 17 | add_subdirectory(filetransfer) 18 | 19 | if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY) 20 | add_subdirectory(hiredis) 21 | else() 22 | add_subdirectory(hiredis EXCLUDE_FROM_ALL) 23 | endif() 24 | 25 | add_subdirectory(hub) 26 | add_subdirectory(idleconnection) 27 | add_subdirectory(maxconnection) 28 | add_subdirectory(memcached) 29 | add_subdirectory(multiplexer) 30 | add_subdirectory(netty) 31 | add_subdirectory(pingpong) 32 | 33 | if(GD_INCLUDE_DIR AND GD_LIBRARY) 34 | add_subdirectory(procmon) 35 | else() 36 | add_subdirectory(procmon EXCLUDE_FROM_ALL) 37 | endif() 38 | 39 | if(PROTOBUF_FOUND) 40 | add_subdirectory(protobuf) 41 | else() 42 | add_subdirectory(protobuf EXCLUDE_FROM_ALL) 43 | endif() 44 | 45 | add_subdirectory(roundtrip) 46 | add_subdirectory(shorturl) 47 | add_subdirectory(simple) 48 | add_subdirectory(socks4a) 49 | add_subdirectory(twisted) 50 | add_subdirectory(wordcount) 51 | add_subdirectory(zeromq) 52 | -------------------------------------------------------------------------------- /example/ace/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(PROTOBUF_FOUND) 2 | add_subdirectory(logging) 3 | else() 4 | add_subdirectory(logging EXCLUDE_FROM_ALL) 5 | endif() 6 | 7 | if(BOOSTPO_LIBRARY) 8 | add_subdirectory(ttcp) 9 | else() 10 | add_subdirectory(ttcp EXCLUDE_FROM_ALL) 11 | endif() 12 | -------------------------------------------------------------------------------- /example/ace/logging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/ace/logging) 2 | 3 | include_directories(${CMAKE_BINARY_DIR}) 4 | 5 | add_custom_command(OUTPUT logrecord.pb.h logrecord.pb.cc 6 | COMMAND protoc 7 | ARGS -I=${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/logrecord.proto 8 | DEPENDS logrecord.proto 9 | VERBATIM) 10 | 11 | add_executable(logging_client client.cpp logrecord.pb.cc) 12 | set_target_properties(logging_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow -Wno-conversion") 13 | target_link_libraries(logging_client blink_protobuf) 14 | 15 | add_executable(logging_server server.cpp logrecord.pb.cc) 16 | set_target_properties(logging_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow -Wno-conversion") 17 | target_link_libraries(logging_server blink_protobuf) 18 | -------------------------------------------------------------------------------- /example/ace/logging/logrecord.proto: -------------------------------------------------------------------------------- 1 | package logging; 2 | 3 | message LogRecord 4 | { 5 | // must present in first message 6 | message HeartBeat 7 | { 8 | required string hostname = 1; 9 | required string process_name = 2; 10 | required int32 process_id = 3; 11 | required int64 process_start_time = 4; // microseconds since epoch 12 | required string username = 5; 13 | } 14 | 15 | optional HeartBeat heartbeat = 1; 16 | 17 | // blink/Log.h 18 | // enum LogLevel 19 | // { 20 | // TRACE, // 0 21 | // DEBUG, // 1 22 | // INFO, // 2 23 | // WARN, // 3 24 | // ERROR, // 4 25 | // FATAL, // 5 26 | // }; 27 | 28 | required int32 level = 2; 29 | required int32 thread_id = 3; 30 | required int64 timestamp = 4; // microseconds since epoch 31 | required string message = 5; 32 | 33 | // optional: source file, source line, function name 34 | } 35 | -------------------------------------------------------------------------------- /example/ace/ttcp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/ace/ttcp) 2 | 3 | add_executable(ttcp_blink main.cpp common.cpp ttcp.cpp) 4 | target_link_libraries(ttcp_blink blink boost_program_options) 5 | 6 | add_executable(ttcp_blocking main.cpp common.cpp ttcp_blocking.cpp) 7 | target_link_libraries(ttcp_blocking blink boost_program_options) 8 | -------------------------------------------------------------------------------- /example/ace/ttcp/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_ACE_TTCP_COMMON_H__ 2 | #define __EXAMPLE_ACE_TTCP_COMMON_H__ 3 | 4 | #include 5 | #include 6 | 7 | struct Options 8 | { 9 | uint16_t port; 10 | int length; 11 | int number; 12 | bool transmit; 13 | bool receive; 14 | bool nodelay; 15 | std::string host; 16 | 17 | Options() 18 | : port(0), length(0), number(0), 19 | transmit(false), receive(false), nodelay(false) 20 | { 21 | } 22 | }; 23 | 24 | struct SessionMessage 25 | { 26 | int32_t number; 27 | int32_t length; 28 | } __attribute__ ((__packed__)); 29 | 30 | struct PayloadMessage 31 | { 32 | int32_t length; 33 | char data[0]; 34 | }; 35 | 36 | bool parseCommandLine(int argc, char* argv[], Options* opt); 37 | struct sockaddr_in resolveOrDie(const char* host, uint16_t port); 38 | void transmit(const Options& opt); 39 | void receive(const Options& opt); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /example/ace/ttcp/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | Options options; 8 | if (parseCommandLine(argc, argv, &options)) 9 | { 10 | if (options.transmit) 11 | { 12 | transmit(options); 13 | } 14 | else if (options.receive) 15 | { 16 | receive(options); 17 | } 18 | else 19 | { 20 | assert(0); 21 | } 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /example/asio/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(chat) 2 | add_subdirectory(timer) 3 | -------------------------------------------------------------------------------- /example/asio/chat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/asio/chat) 2 | 3 | add_executable(ChatClient ChatClient.cpp) 4 | target_link_libraries(ChatClient blink) 5 | 6 | add_executable(ChatClientLoadTest ChatClientLoadTest.cpp) 7 | target_link_libraries(ChatClientLoadTest blink) 8 | 9 | add_executable(ChatServer ChatServer.cpp) 10 | target_link_libraries(ChatServer blink) 11 | 12 | add_executable(ChatServerEfficient ChatServerEfficient.cpp) 13 | target_link_libraries(ChatServerEfficient blink) 14 | 15 | add_executable(ChatServerHighPerformance ChatServerHighPerformance.cpp) 16 | target_link_libraries(ChatServerHighPerformance blink) 17 | 18 | add_executable(ChatServerThreaded ChatServerThreaded.cpp) 19 | target_link_libraries(ChatServerThreaded blink) 20 | -------------------------------------------------------------------------------- /example/asio/chat/Codec.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_CODEC_H__ 2 | #define __EXAMPLE_CODEC_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | class Codec : blink::Nocopyable 13 | { 14 | public: 15 | typedef boost::function StringMessageCallback; 18 | 19 | explicit Codec(const StringMessageCallback& cb) 20 | : message_callback_(cb) 21 | { 22 | } 23 | 24 | void onMessage(const blink::TcpConnectionPtr& connection, 25 | blink::Buffer* buf, 26 | blink::Timestamp receive_time) 27 | { 28 | while (buf->readableSize() >= kHeaderlen) 29 | { 30 | const int32_t len = buf->peekInt32(); 31 | if (len > 65536 || len < 0) 32 | { 33 | LOG_ERROR << "Invalid length " << len; 34 | connection->shutdown(); 35 | break; 36 | } 37 | else if (buf->readableSize() >= len + kHeaderlen) 38 | { 39 | buf->reset(kHeaderlen); 40 | blink::string message(buf->peek(), len); 41 | message_callback_(connection, message, receive_time); 42 | buf->reset(len); 43 | } 44 | else 45 | { 46 | break; 47 | } 48 | } 49 | } 50 | 51 | void send(blink::TcpConnection* connection, blink::string message) 52 | { 53 | blink::Buffer buf; 54 | buf.append(&*message.begin(), message.size()); 55 | buf.prependInt32(static_cast(message.size())); 56 | connection->send(&buf); 57 | } 58 | 59 | private: 60 | StringMessageCallback message_callback_; 61 | static const size_t kHeaderlen = sizeof(int32_t); 62 | }; 63 | 64 | const size_t Codec::kHeaderlen; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /example/asio/timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/asio/timer) 2 | 3 | add_executable(timer2 timer2.cpp) 4 | target_link_libraries(timer2 blink) 5 | 6 | add_executable(timer3 timer3.cpp) 7 | target_link_libraries(timer3 blink) 8 | 9 | add_executable(timer4 timer4.cpp) 10 | target_link_libraries(timer4 blink) 11 | 12 | add_executable(timer5 timer5.cpp) 13 | target_link_libraries(timer5 blink) 14 | 15 | add_executable(timer6 timer6.cpp) 16 | target_link_libraries(timer6 blink) 17 | -------------------------------------------------------------------------------- /example/asio/timer/timer2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | void print(blink::EventLoop& loop) 8 | { 9 | std::cout << "hey boy!" << std::endl; 10 | loop.quit(); 11 | } 12 | 13 | int main(int argc, char* argv[]) 14 | { 15 | blink::EventLoop loop; 16 | loop.runAfter(3.0, boost::bind(print, boost::ref(loop))); 17 | loop.loop(); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /example/asio/timer/timer3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | void print(blink::EventLoop& loop, int& count) 8 | { 9 | if (count < 5) 10 | { 11 | std::cout << count << std::endl; 12 | ++count; 13 | loop.runAfter(1.0, boost::bind(print, boost::ref(loop), boost::ref(count))); 14 | } 15 | else 16 | { 17 | loop.quit(); 18 | } 19 | } 20 | 21 | int main(int argc, char const *argv[]) 22 | { 23 | blink::EventLoop loop; 24 | int count = 0; 25 | loop.runAfter(1.0, boost::bind(print, boost::ref(loop), boost::ref(count))); 26 | loop.loop(); 27 | std::cout << "Final count is " << count << std::endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /example/asio/timer/timer4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | class Printer : blink::Nocopyable 9 | { 10 | public: 11 | Printer(blink::EventLoop* loop) 12 | : loop_(loop), count_(0) 13 | { 14 | loop_->runAfter(1.0, boost::bind(&Printer::print, this)); 15 | } 16 | 17 | ~Printer() 18 | { 19 | std::cout << "Final count is " << count_ << std::endl; 20 | } 21 | 22 | private: 23 | void print() 24 | { 25 | if (count_ < 5) 26 | { 27 | std::cout << count_ << std::endl; 28 | ++count_; 29 | loop_->runAfter(1.0, boost::bind(&Printer::print, this)); 30 | } 31 | else 32 | { 33 | loop_->quit(); 34 | } 35 | } 36 | 37 | blink::EventLoop* loop_; 38 | int count_; 39 | }; 40 | 41 | int main(int argc, char const *argv[]) 42 | { 43 | blink::EventLoop loop; 44 | Printer print(&loop); 45 | loop.loop(); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /example/asio/timer/timer5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class Printer : blink::Nocopyable 12 | { 13 | public: 14 | Printer(blink::EventLoop* loop1, blink::EventLoop* loop2) 15 | : loop1_(loop1), loop2_(loop2), count_(0) 16 | { 17 | loop1_->runAfter(1.0, boost::bind(&Printer::print1, this)); 18 | loop2_->runAfter(1.0, boost::bind(&Printer::print2, this)); 19 | } 20 | 21 | ~Printer() 22 | { 23 | std::cout << "Final count is " << count_ << std::endl; 24 | } 25 | 26 | private: 27 | void print1() 28 | { 29 | blink::MutexLockGuard guard(mutex_); 30 | if (count_ < 10) 31 | { 32 | std::cout << "Timer 1: " << count_ << std::endl; 33 | ++count_; 34 | loop1_->runAfter(1.0, boost::bind(&Printer::print1, this)); 35 | } 36 | else 37 | { 38 | loop1_->quit(); 39 | } 40 | } 41 | 42 | void print2() 43 | { 44 | blink::MutexLockGuard guard(mutex_); 45 | if (count_ < 10) 46 | { 47 | std::cout << "Timer 2: " << count_ << std::endl; 48 | ++count_; 49 | loop2_->runAfter(1.0, boost::bind(&Printer::print2, this)); 50 | } 51 | else 52 | { 53 | loop2_->quit(); 54 | } 55 | } 56 | 57 | blink::EventLoop* loop1_; 58 | blink::EventLoop* loop2_; 59 | blink::MutexLock mutex_; 60 | int count_; 61 | }; 62 | 63 | int main(int argc, char const *argv[]) 64 | { 65 | // The scoped_ptr make sure Printer lives than two loops, 66 | // to avoid race condition of calling print2() on destructed Printer object. 67 | boost::scoped_ptr printer; 68 | blink::EventLoop loop; 69 | blink::EventLoopThread loop_thread; 70 | blink::EventLoop* loop_in_another_thread = loop_thread.startLoop(); 71 | printer.reset(new Printer(&loop, loop_in_another_thread)); 72 | loop.loop(); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /example/cdns/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/cdns) 2 | 3 | add_executable(dns dns.cpp Resolver.cpp) 4 | target_link_libraries(dns blink cares) 5 | -------------------------------------------------------------------------------- /example/cdns/dns.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | using namespace blink; 10 | 11 | EventLoop* g_loop = NULL; 12 | int g_count = 0; 13 | int g_total = 0; 14 | 15 | void quit() 16 | { 17 | g_loop->quit(); 18 | } 19 | 20 | void resolveCallback(const string& hostname, const InetAddress& addr) 21 | { 22 | printf("resolveCallback: %s -> %s\n", hostname.c_str(), addr.toIp().c_str()); 23 | if (++g_count == g_total) 24 | { 25 | quit(); 26 | } 27 | } 28 | 29 | void resolve(Resolver* resolver, const string& hostname) 30 | { 31 | resolver->resolve(hostname, boost::bind(resolveCallback, hostname, _1)); 32 | } 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | EventLoop loop; 37 | loop.runAfter(10, quit); 38 | g_loop = &loop; 39 | Resolver resolver(&loop, argc == 1 ? Resolver::kDnsOnly : Resolver::kDnsAndHostFile); 40 | if (argc == 1) 41 | { 42 | g_total = 3; 43 | resolve(&resolver, "liyuanlife.com"); 44 | resolve(&resolver, "github.com"); 45 | resolve(&resolver, "stackoverflow.com"); 46 | } 47 | else 48 | { 49 | g_total = argc - 1; 50 | for (int i = 1; i < argc; ++i) 51 | { 52 | resolve(&resolver, argv[i]); 53 | } 54 | } 55 | loop.loop(); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /example/curl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/curl) 2 | 3 | add_executable(mcurl mcurl.cpp Curl.cpp) 4 | target_link_libraries(mcurl blink curl) 5 | 6 | add_executable(download download.cpp Curl.cpp) 7 | target_link_libraries(download blink curl) 8 | -------------------------------------------------------------------------------- /example/curl/mcurl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | using namespace blink; 10 | 11 | EventLoop* g_loop = NULL; 12 | 13 | void onData(const char* data, int len) 14 | { 15 | printf("len %d\n", len); 16 | // string content(data, len); 17 | // printf("%s\n", content.c_str()); 18 | } 19 | 20 | void done(Request* request, int code) 21 | { 22 | printf("done %p %s %d\n", request, request->getEffectiveUrl(), code); 23 | } 24 | 25 | void done2(Request* request, int code) 26 | { 27 | printf("donw2 %p %s %d %d\n", request, request->getRedirectUrl(), request->getResponseCode(), code); 28 | } 29 | 30 | int main(int argc, char* argv[]) 31 | { 32 | EventLoop loop; 33 | g_loop = &loop; 34 | loop.runAfter(30.0, boost::bind(&EventLoop::quit, &loop)); 35 | Curl::initialize(Curl::kCurlSsl); 36 | Curl curl(&loop); 37 | 38 | RequestPtr request = curl.getUrl("http://liyuanlife.com"); 39 | request->setDataCallback(onData); 40 | request->setDoneCallback(done); 41 | 42 | RequestPtr request2 = curl.getUrl("https://github.com"); 43 | request2->setDataCallback(onData); 44 | request2->setDoneCallback(done); 45 | 46 | RequestPtr request3 = curl.getUrl("http://example.com"); 47 | request3->setDataCallback(onData); 48 | request3->setDoneCallback(done2); 49 | 50 | loop.loop(); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /example/fastcgi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/fastcgi) 2 | 3 | add_executable(FastCgiTest FastCgiTest.cpp FastCgi.cpp) 4 | target_link_libraries(FastCgiTest blink) 5 | -------------------------------------------------------------------------------- /example/fastcgi/FastCgi.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_FASTCGI_H__ 2 | #define __EXAMPLE_FASTCGI_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | // One FastCgiCodec per TcpConnection 10 | class FastCgiCodec : blink::Nocopyable 11 | { 12 | public: 13 | typedef std::map ParamMap; 14 | typedef boost::function Callback; 17 | 18 | explicit FastCgiCodec(const Callback& cb) 19 | : callback_(cb), 20 | got_request_(false), 21 | keep_connection_(false) 22 | { 23 | } 24 | 25 | void onMessage(const blink::TcpConnectionPtr& connection, 26 | blink::Buffer* buf, 27 | blink::Timestamp receive_time) 28 | { 29 | parseRequest(buf); 30 | if (got_request_) 31 | { 32 | callback_(connection, params_, &stdin_); 33 | stdin_.resetAll(); 34 | params_stream_.resetAll(); 35 | params_.clear(); 36 | got_request_ = false; 37 | if (!keep_connection_) 38 | { 39 | connection->shutdown(); 40 | } 41 | } 42 | } 43 | 44 | static void respond(blink::Buffer* response); 45 | 46 | private: 47 | struct RecordHeader; 48 | 49 | bool onParams(const char* content, uint16_t length); 50 | void onStdin(const char* content, uint16_t length); 51 | bool onBeginRequest(const RecordHeader& header, const blink::Buffer* buf); 52 | bool parseRequest(blink::Buffer* buf); 53 | bool parseAllParams(); 54 | uint32_t readLen(); 55 | 56 | static void endStdout(blink::Buffer* buf); 57 | static void endRequest(blink::Buffer* buf); 58 | 59 | Callback callback_; 60 | bool got_request_; 61 | bool keep_connection_; 62 | blink::Buffer stdin_; 63 | blink::Buffer params_stream_; 64 | ParamMap params_; 65 | 66 | static const unsigned kRecordHeader; 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /example/fastcgi/FastCgiTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | using namespace blink; 10 | 11 | void onRequest(const TcpConnectionPtr& connection, 12 | FastCgiCodec::ParamMap& params, 13 | Buffer* in) 14 | { 15 | LOG_INFO << connection->name() << ": " << params["REQUEST_URI"]; 16 | for (FastCgiCodec::ParamMap::iterator it = params.begin(); 17 | it != params.end(); ++it) 18 | { 19 | LOG_DEBUG << it->first << " = " << it->second; 20 | } 21 | Buffer response; 22 | response.append("Content-Type: text/plain\r\n\r\n"); 23 | response.append("Hello FastCgi"); 24 | FastCgiCodec::respond(&response); 25 | connection->send(&response); 26 | } 27 | 28 | void onConnection(const TcpConnectionPtr& connection) 29 | { 30 | if (connection->connected()) 31 | { 32 | boost::shared_ptr codec(new FastCgiCodec(onRequest)); 33 | connection->setContext(codec); 34 | connection->setMessageCallback(boost::bind(&FastCgiCodec::onMessage, codec, _1, _2, _3)); 35 | } 36 | }; 37 | 38 | int main(int argc, char const *argv[]) 39 | { 40 | EventLoop loop; 41 | TcpServer server(&loop, InetAddress(9600), "FastCgi"); 42 | server.setConnectionCallback(onConnection); 43 | server.start(); 44 | loop.loop(); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /example/filetransfer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/filetransfer) 2 | 3 | add_executable(Download Download.cpp) 4 | target_link_libraries(Download blink) 5 | 6 | add_executable(Download2 Download2.cpp) 7 | target_link_libraries(Download2 blink) 8 | 9 | add_executable(Download3 Download3.cpp) 10 | target_link_libraries(Download3 blink) 11 | -------------------------------------------------------------------------------- /example/hiredis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/hiredis) 2 | 3 | add_executable(mredis_client mredis_client.cpp Hiredis.cpp) 4 | target_link_libraries(mredis_client blink hiredis) 5 | -------------------------------------------------------------------------------- /example/hub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/hub) 2 | 3 | add_executable(Pub Pub.cpp PubSubClient.cpp Codec.cpp) 4 | target_link_libraries(Pub blink) 5 | 6 | add_executable(Sub Sub.cpp PubSubClient.cpp Codec.cpp) 7 | target_link_libraries(Sub blink) 8 | 9 | add_executable(PubSubServer PubSubServer.cpp Codec.cpp) 10 | target_link_libraries(PubSubServer blink) 11 | -------------------------------------------------------------------------------- /example/hub/Codec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace blink; 4 | 5 | ParseResult parseMessage(Buffer* buf, 6 | string* command, 7 | string* topic, 8 | string* content) 9 | { 10 | ParseResult result = kError; 11 | const char* crlf = buf->findCRLF(); 12 | if (crlf) 13 | { 14 | const char* space = std::find(buf->peek(), crlf, ' '); 15 | if (space != crlf) 16 | { 17 | command->assign(buf->peek(), space); 18 | topic->assign(space + 1, crlf); 19 | if (*command == "pub") 20 | { 21 | const char* start = crlf + 2; 22 | crlf = buf->findCRLF(start); 23 | if (crlf) 24 | { 25 | content->assign(start, crlf); 26 | buf->resetUntil(crlf + 2); 27 | result = kSuccess; 28 | } 29 | else 30 | { 31 | result = kContinue; 32 | } 33 | } 34 | else 35 | { 36 | buf->resetUntil(crlf + 2); 37 | result = kSuccess; 38 | } 39 | } 40 | else 41 | { 42 | result = kError; 43 | } 44 | } 45 | else 46 | { 47 | result = kContinue; 48 | } 49 | return result; 50 | } 51 | -------------------------------------------------------------------------------- /example/hub/Codec.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_HUB_CODEC_H__ 2 | #define __EXAMPLE_HUB_CODEC_H__ 3 | 4 | #include 5 | 6 | enum ParseResult 7 | { 8 | kError, 9 | kSuccess, 10 | kContinue, 11 | }; 12 | 13 | ParseResult parseMessage(blink::Buffer* buf, 14 | blink::string* command, 15 | blink::string* topic, 16 | blink::string* content); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /example/hub/PubSubClient.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_HUB_PUBSUB_H__ 2 | #define __EXAMPLE_HUB_PUBSUB_H__ 3 | 4 | #include 5 | #include 6 | 7 | // FIXME: destructor is not thread safe. 8 | class PubSubClient : blink::Nocopyable 9 | { 10 | public: 11 | typedef boost::function ConnectionCallback; 12 | typedef boost::function SubscribeCallback; 15 | 16 | PubSubClient(blink::EventLoop* loop, 17 | const blink::InetAddress& server_addr, 18 | const blink::string& name); 19 | 20 | void start(); 21 | void stop(); 22 | bool connected(); 23 | bool subscribe(const blink::string& topic, const SubscribeCallback& cb); 24 | void unsubscribe(const blink::string& topic); 25 | bool publish(const blink::string& topic, const blink::string& content); 26 | 27 | void setConnectionCallback(const ConnectionCallback& cb) 28 | { 29 | connection_callback_ = cb; 30 | } 31 | 32 | private: 33 | void onConnection(const blink::TcpConnectionPtr& connection); 34 | void onMessage(const blink::TcpConnectionPtr& connection, 35 | blink::Buffer* buf, 36 | blink::Timestamp receive_time); 37 | bool send(const blink::string& message); 38 | 39 | blink::TcpClient client_; 40 | blink::TcpConnectionPtr connection_; 41 | ConnectionCallback connection_callback_; 42 | SubscribeCallback subscribe_callback_; 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /example/hub/Sub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace blink; 10 | 11 | EventLoop* g_loop = NULL; 12 | std::vector g_topics; 13 | 14 | void subscription(const string& topic, const string& content, Timestamp) 15 | { 16 | printf("%s: %s\n", topic.c_str(), content.c_str()); 17 | } 18 | 19 | void connection(PubSubClient* client) 20 | { 21 | if (client->connected()) 22 | { 23 | for (std::vector::iterator it = g_topics.begin(); 24 | it != g_topics.end(); ++it) 25 | { 26 | client->subscribe(*it, subscription); 27 | } 28 | } 29 | else 30 | { 31 | g_loop->quit(); 32 | } 33 | } 34 | 35 | int main(int argc, char const *argv[]) 36 | { 37 | if (argc < 3) 38 | { 39 | printf("Usage: %s : [topic ...]>\n", argv[0]); 40 | return 1; 41 | } 42 | string hostport = argv[1]; 43 | size_t colon = hostport.find(':'); 44 | if (colon != string::npos) 45 | { 46 | string ip = hostport.substr(0, colon); 47 | uint16_t port = static_cast(atoi(hostport.c_str() + colon + 1)); 48 | for (int i = 2; i < argc; ++i) 49 | { 50 | g_topics.push_back(argv[i]); 51 | } 52 | EventLoop loop; 53 | g_loop = &loop; 54 | string name = process_info::username() + "@" + process_info::hostName(); 55 | name += ":" + process_info::pidString(); 56 | PubSubClient client(g_loop, InetAddress(ip, port), name); 57 | client.setConnectionCallback(connection); 58 | client.start(); 59 | loop.loop(); 60 | } 61 | else 62 | { 63 | printf("Usage : %s : [topic ...]>\n", argv[0]); 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /example/idleconnection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/idleconnection) 2 | 3 | add_executable(EchoServer main.cpp EchoServer.cpp) 4 | target_link_libraries(EchoServer blink) 5 | 6 | add_executable(EchoServer_sorted EchoServer_sorted.cpp) 7 | target_link_libraries(EchoServer_sorted blink) 8 | -------------------------------------------------------------------------------- /example/idleconnection/EchoServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_IDLECONNECTION_ECHOSERVER_H__ 2 | #define __EXAMPLE_IDLECONNECTION_ECHOSERVER_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #if BOOST_VERSION < 104700 12 | 13 | namespace boost 14 | { 15 | 16 | template 17 | inline size_t hash_value(const shared_ptr& p) 18 | { 19 | return hash_value(p.get()); 20 | } 21 | 22 | } // namespace boost 23 | 24 | #endif 25 | 26 | class EchoServer : blink::Nocopyable 27 | { 28 | public: 29 | EchoServer(blink::EventLoop* loop, 30 | const blink::InetAddress& listen_addr, 31 | int idle_seconds); 32 | 33 | void start(); 34 | 35 | private: 36 | void onConnection(const blink::TcpConnectionPtr& connection); 37 | void onMessage(const blink::TcpConnectionPtr& connection, 38 | blink::Buffer* buf, 39 | blink::Timestamp receive_time); 40 | void onTimer(); 41 | void dumpConnectionBuckets() const; 42 | 43 | typedef boost::weak_ptr WeakTcpConnectionPtr; 44 | 45 | class Entry 46 | { 47 | public: 48 | Entry(const WeakTcpConnectionPtr& weak_connection) 49 | : weak_connection_(weak_connection) 50 | { 51 | } 52 | 53 | ~Entry() 54 | { 55 | blink::TcpConnectionPtr connection = weak_connection_.lock(); 56 | if (connection) 57 | { 58 | connection->shutdown(); 59 | } 60 | } 61 | 62 | WeakTcpConnectionPtr weak_connection_; // use weak_ptr to avoid circular reference. 63 | }; 64 | 65 | typedef boost::shared_ptr EntryPtr; 66 | typedef boost::weak_ptr WeakEntryPtr; 67 | typedef boost::unordered_set Bucket; 68 | typedef boost::circular_buffer WeakConnectionList; 69 | 70 | blink::TcpServer server_; 71 | WeakConnectionList connection_buckets_; 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /example/idleconnection/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | void testHash() 13 | { 14 | boost::hash > h; 15 | boost::shared_ptr p1(new int(100)); 16 | boost::shared_ptr p2(new int(100)); 17 | h(p1); 18 | assert(h(p1) != h(p2)); 19 | p1 = p2; 20 | assert(h(p1) == h(p2)); 21 | p1.reset(); 22 | assert(h(p1) != h(p2)); 23 | p2.reset(); 24 | assert(h(p1) == h(p2)); 25 | } 26 | 27 | int main(int argc, char const *argv[]) 28 | { 29 | testHash(); 30 | EventLoop loop; 31 | InetAddress listen_addr(9600); 32 | int idle_seconds = 10; 33 | if (argc > 1) 34 | { 35 | idle_seconds = atoi(argv[1]); 36 | } 37 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid() 38 | << "idle seconds = " << idle_seconds; 39 | EchoServer server(&loop, listen_addr, idle_seconds); 40 | server.start(); 41 | loop.loop(); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /example/maxconnection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/maxconnection) 2 | 3 | add_executable(MaxConnection MaxConnection.cpp) 4 | target_link_libraries(MaxConnection blink) 5 | -------------------------------------------------------------------------------- /example/memcached/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(server) 2 | add_subdirectory(client) 3 | -------------------------------------------------------------------------------- /example/memcached/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/memcached/client) 2 | 3 | if(BOOSTPO_LIBRARY) 4 | add_executable(memcached_client client.cpp) 5 | target_link_libraries(memcached_client blink boost_program_options) 6 | endif() 7 | -------------------------------------------------------------------------------- /example/memcached/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/memcached/server) 2 | 3 | if(BOOSTPO_LIBRARY) 4 | add_executable(memcached_server server.cpp MemcacheServer.cpp Session.cpp Item.cpp) 5 | target_link_libraries(memcached_server blink_inspect boost_program_options) 6 | endif() 7 | 8 | add_executable(footprint_test footprint_test.cpp MemcacheServer.cpp Session.cpp Item.cpp) 9 | target_link_libraries(footprint_test blink_inspect) 10 | 11 | if(TCMALLOC_LIBRARY AND TCMALLOC_INCLUDE_DIR) 12 | set_target_properties(footprint_test PROPERTIES COMPILE_FLAGS "-DHAVE_TCMALLOC") 13 | if(BOOSTPO_LIBRARY) 14 | set_target_properties(memcached_server PROPERTIES COMPILE_FLAHS "-DHAVE_TCMALLOC") 15 | endif() 16 | endif() 17 | -------------------------------------------------------------------------------- /example/memcached/server/Item.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | using namespace blink; 12 | 13 | Item::Item(StringPiece key_arg, 14 | uint32_t flags_arg, 15 | int exptime_arg, 16 | int value_len, 17 | uint64_t cas_arg) 18 | : key_len_(key_arg.size()), 19 | flags_(flags_arg), 20 | rel_exptime_(exptime_arg), 21 | value_len_(value_len), 22 | received_bytes_(0), 23 | cas_(cas_arg), 24 | hash_(boost::hash_range(key_arg.begin(), key_arg.end())), 25 | data_(static_cast(::malloc(totalLen()))) 26 | { 27 | assert(value_len_ >= 2); 28 | assert(received_bytes_ < totalLen()); 29 | append(key_arg.data(), key_len_); 30 | } 31 | 32 | void Item::append(const char* data, size_t len) 33 | { 34 | assert(len <= neededBytes()); 35 | memcpy(data_ + received_bytes_, data, len); 36 | received_bytes_ += static_cast(len); 37 | assert(received_bytes_ <= totalLen()); 38 | } 39 | 40 | void Item::output(Buffer* out, bool need_cas) const 41 | { 42 | out->append("VALUE "); 43 | out->append(data_, key_len_); 44 | LogStream buf; 45 | buf << ' ' << flags_ << ' ' << value_len_ - 2; 46 | if (need_cas) 47 | { 48 | buf << ' ' << cas_; 49 | } 50 | buf << "\r\n"; 51 | out->append(buf.buffer().data(), buf.buffer().usedSize()); 52 | out->append(value(), value_len_); 53 | } 54 | 55 | void Item::resetKey(StringPiece k) 56 | { 57 | assert(k.size() <= 250); 58 | key_len_ = k.size(); 59 | received_bytes_ = 0; 60 | append(k.data(), k.size()); 61 | hash_ = boost::hash_range(k.begin(), k.end()); 62 | } 63 | -------------------------------------------------------------------------------- /example/memcached/server/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace po = boost::program_options; 12 | using namespace blink; 13 | 14 | bool parseCommandLine(int argc, char* argv[], MemcacheServer::Options* options) 15 | { 16 | options->tcp_port = 11211; 17 | options->gperf_port = 11212; 18 | options->threads = 4; 19 | 20 | po::options_description desc("Allowed options"); 21 | desc.add_options() 22 | ("help,h", "Help") 23 | ("port,p", po::value(&options->tcp_port), "TCP port") 24 | ("udpport,U", po::value(&options->udp_port), "UDP port") 25 | ("gperf,g", po::value(&options->gperf_port), "port for gperftools") 26 | ("threads,t", po::value(&options->threads), "Number of worker threads") 27 | ; 28 | 29 | po::variables_map vm; 30 | po::store(po::parse_command_line(argc, argv, desc), vm); 31 | po::notify(vm); 32 | if (vm.count("help")) 33 | { 34 | std::cout << "blink-memcached 1.0\n" << desc; 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | EventLoop loop; 43 | EventLoopThread inspect_thread; 44 | MemcacheServer::Options options; 45 | if (parseCommandLine(argc, argv, &options)) 46 | { 47 | // FIXME: how to destruct it safely? 48 | new Inspector(inspect_thread.startLoop(), InetAddress(options.gperf_port), "memcache-debug"); 49 | MemcacheServer server(&loop, options); 50 | server.setThreadNumber(options.threads); 51 | server.start(); 52 | loop.loop(); 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /example/multiplexer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/multiplexer) 2 | 3 | add_executable(Demux Demux.cpp) 4 | target_link_libraries(Demux blink) 5 | 6 | add_executable(MultiplexServer MultiplexServer.cpp) 7 | target_link_libraries(MultiplexServer blink) 8 | 9 | add_executable(MultiplexServer_simple MultiplexServer_simple.cpp) 10 | target_link_libraries(MultiplexServer_simple blink) 11 | -------------------------------------------------------------------------------- /example/netty/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(discard) 2 | add_subdirectory(echo) 3 | add_subdirectory(uptime) 4 | -------------------------------------------------------------------------------- /example/netty/discard/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/netty/dicard) 2 | 3 | add_executable(client client.cpp) 4 | target_link_libraries(client blink) 5 | 6 | add_executable(server server.cpp) 7 | target_link_libraries(server blink) 8 | -------------------------------------------------------------------------------- /example/netty/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/netty/echo) 2 | 3 | add_executable(netty_echo_client client.cpp) 4 | target_link_libraries(netty_echo_client blink) 5 | 6 | add_executable(netty_echo_server server.cpp) 7 | target_link_libraries(netty_echo_server blink) 8 | 9 | add_executable(netty_echo_server2 server2.cpp) 10 | target_link_libraries(netty_echo_server2 blink) 11 | -------------------------------------------------------------------------------- /example/netty/uptime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/netty/uptime) 2 | 3 | add_executable(netty_uptime_client client.cpp) 4 | target_link_libraries(netty_uptime_client blink) 5 | -------------------------------------------------------------------------------- /example/netty/uptime/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | using namespace blink; 13 | 14 | class UptimeClient : Nocopyable 15 | { 16 | public: 17 | UptimeClient(EventLoop* loop, const InetAddress& server_addr) 18 | : client_(loop, server_addr, "UptimeClient") 19 | { 20 | client_.setConnectionCallback(boost::bind(&UptimeClient::onConnection, this, _1)); 21 | client_.setMessageCallback(boost::bind(&UptimeClient::onMessage, this, _1, _2, _3)); 22 | } 23 | 24 | void connect() 25 | { 26 | client_.connect(); 27 | } 28 | 29 | private: 30 | void onConnection(const TcpConnectionPtr& connection) 31 | { 32 | LOG_TRACE << connection->localAddress().toIpPort() << " -> " 33 | << connection->peerAddress().toIpPort() << " is " 34 | << (connection->connected() ? "UP" : "DOWN"); 35 | } 36 | 37 | void onMessage(const TcpConnectionPtr& connection, 38 | Buffer* buf, 39 | Timestamp receive_time) 40 | { 41 | } 42 | 43 | TcpClient client_; 44 | }; 45 | 46 | int main(int argc, char const *argv[]) 47 | { 48 | if (argc < 3) 49 | { 50 | fprintf(stderr, "usage: %s \n", argv[0]); 51 | return 1; 52 | } 53 | LOG_INFO << "pid = " << getpid() << ", tid" << current_thread::tid(); 54 | EventLoop loop; 55 | InetAddress server_addr(argv[1], static_cast(atoi(argv[2]))); 56 | UptimeClient client(&loop, server_addr); 57 | client.connect(); 58 | loop.loop(); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /example/pingpong/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/pingpong) 2 | 3 | add_executable(pingpong_server server.cpp) 4 | target_link_libraries(pingpong_server blink) 5 | 6 | add_executable(pingpong_client client.cpp) 7 | target_link_libraries(pingpong_client blink) 8 | 9 | add_executable(BenchMark BenchMark.cpp) 10 | target_link_libraries(BenchMark blink) 11 | -------------------------------------------------------------------------------- /example/pingpong/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | using namespace blink; 14 | 15 | void onConnection(const TcpConnectionPtr& connection) 16 | { 17 | if (connection->connected()) 18 | { 19 | connection->setTcpNoDelay(true); 20 | } 21 | } 22 | 23 | void onMessage(const TcpConnectionPtr& connection, 24 | Buffer* buf, 25 | Timestamp receive_time) 26 | { 27 | connection->send(buf); 28 | } 29 | 30 | int main(int argc, char const *argv[]) 31 | { 32 | if (argc < 2) 33 | { 34 | fprintf(stderr, "Usage: %s \n", argv[0]); 35 | return 1; 36 | } 37 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 38 | Log::setLogLevel(Log::WARN); 39 | InetAddress listen_addr(static_cast(atoi(argv[1]))); 40 | EventLoop loop; 41 | TcpServer server(&loop, listen_addr, "PingPong Server"); 42 | server.setConnectionCallback(onConnection); 43 | server.setMessageCallback(onMessage); 44 | if (argc == 3) 45 | { 46 | server.setThreadNumber(atoi(argv[2])); 47 | } 48 | server.start(); 49 | loop.loop(); 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /example/procmon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/procmon) 2 | 3 | add_executable(plot_test plot_test.cpp plot.cpp) 4 | target_link_libraries(plot_test blink gd) 5 | 6 | add_executable(procmon procmon.cpp plot.cpp) 7 | target_link_libraries(procmon blink_http gd) 8 | 9 | add_executable(dummyload dummyload.cpp) 10 | target_link_libraries(dummyload blink) 11 | -------------------------------------------------------------------------------- /example/procmon/plot.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_PROCMON_PLOT_H__ 2 | #define __EXAMPLE_PROCMON_PLOT_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include // ssize_t 8 | 9 | #include 10 | 11 | typedef struct gdImageStruct* gdImagePtr; 12 | 13 | class Plot : blink::Nocopyable 14 | { 15 | public: 16 | Plot(int width, int height, int total_seconds, int sampling_period); 17 | ~Plot(); 18 | 19 | blink::string plotCpu(const std::vector& data); 20 | 21 | private: 22 | blink::string toPng(); 23 | int getX(ssize_t i, ssize_t total) const; 24 | int getY(double value) const; 25 | void label(double max_value) const; 26 | 27 | // gdFont is a typedef of unnamed struct, cannot be foward declered 28 | // wordaround suggested int http://stackoverflow.com/questions/7256436/forward-declarations-of-unnamed-struct 29 | struct MyGdFont; 30 | typedef struct MyGdFont* MyGdFontPtr; 31 | 32 | const int width_; 33 | const int height_; 34 | const int total_seconds_; 35 | const int sampling_period_; 36 | const gdImagePtr image_; 37 | const MyGdFontPtr font_; 38 | const int font_width_; 39 | const int font_height_; 40 | const int background_; 41 | const int black_; 42 | const int gray_; 43 | const int blue_; 44 | const int kRightMargin_; 45 | 46 | static const int kLeftMargin_ = 5; 47 | static const int kMarginY_ = 5; 48 | 49 | const double ratio_x_; 50 | }; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /example/procmon/plot_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace blink; 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | std::vector cpu_usage; 14 | for (int i = 0; i < 300; ++i) 15 | { 16 | cpu_usage.push_back(1.0 + sin(pow(i / 30.0, 2))); 17 | } 18 | Plot plot(640, 100, 600, 2); 19 | Timestamp start = Timestamp::now(); 20 | const int N = 10000; 21 | for (int i = 0; i < N; ++i) 22 | { 23 | string png = plot.plotCpu(cpu_usage); 24 | } 25 | double elapsed = timeDifference(Timestamp::now(), start); 26 | printf("%d plots in %f seconds, %f PNG per second, %f ms per PNG\n", 27 | N, elapsed, N / elapsed, elapsed * 1000 / N); 28 | string png = plot.plotCpu(cpu_usage); 29 | FILE* fp = fopen("test.png", "wb"); 30 | fwrite(png.data(), 1, png.size(), fp); 31 | fclose(fp); 32 | printf("Image saved to test.png\n"); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /example/protobuf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_BINARY_DIR}) 2 | include_directories(${CMAKE_BINARY_DIR}/src) 3 | 4 | add_subdirectory(resolver) 5 | add_subdirectory(rpc) 6 | add_subdirectory(rpcbench) 7 | add_subdirectory(rpcbalancer) 8 | 9 | if(PROTOBUF_FOUND AND ZLIB_FOUND) 10 | add_subdirectory(codec) 11 | else() 12 | add_subdirectory(codec EXCLUDE_FROM_ALL) 13 | endif() 14 | -------------------------------------------------------------------------------- /example/protobuf/codec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/protobuf/codec) 2 | 3 | add_custom_command(OUTPUT query.pb.h query.pb.cc 4 | COMMAND protoc 5 | ARGS -I=${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/query.proto 6 | DEPENDS query.proto 7 | VERBATIM) 8 | 9 | set_source_files_properties(query.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 10 | 11 | add_executable(codec_test codec_test.cpp codec.cpp query.pb.cc) 12 | set_target_properties(codec_test PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 13 | target_link_libraries(codec_test blink protobuf z) 14 | 15 | add_executable(codec_dispatcher_test dispatcher_test.cpp query.pb.cc) 16 | set_target_properties(codec_dispatcher_test PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 17 | target_link_libraries(codec_dispatcher_test blink protobuf) 18 | 19 | add_executable(codec_dispatcher_lite_test dispatcher_lite_test.cpp query.pb.cc) 20 | set_target_properties(codec_dispatcher_lite_test PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 21 | target_link_libraries(codec_dispatcher_lite_test blink protobuf) 22 | 23 | add_executable(codec_client client.cpp codec.cpp query.pb.cc) 24 | set_target_properties(codec_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 25 | target_link_libraries(codec_client blink protobuf z) 26 | 27 | add_executable(codec_server server.cpp codec.cpp query.pb.cc) 28 | set_target_properties(codec_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 29 | target_link_libraries(codec_server blink protobuf z) 30 | -------------------------------------------------------------------------------- /example/protobuf/codec/dispatcher_lite.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_PROTOBUF_CODEC_DISPATCHER_LITE_H__ 2 | #define __EXAMPLE_PROTOBUF_CODEC_DISPATCHER_LITE_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | typedef boost::shared_ptr MessagePtr; 15 | 16 | class ProtobufDispatcherLite : blink::Nocopyable 17 | { 18 | public: 19 | typedef boost::function ProtobufMessageCallback; 22 | 23 | explicit ProtobufDispatcherLite(const ProtobufMessageCallback& message_callback) 24 | : default_message_callbcak_(message_callback) 25 | { 26 | } 27 | 28 | void onProtobufMessage(const blink::TcpConnectionPtr& connection, 29 | const MessagePtr& message, 30 | blink::Timestamp receive_time) const 31 | { 32 | CallbackMap::const_iterator it = callbacks_.find(message->GetDescriptor()); 33 | if (it != callbacks_.end()) 34 | { 35 | it->second(connection, message, receive_time); 36 | } 37 | else 38 | { 39 | default_message_callbcak_(connection, message, receive_time); 40 | } 41 | } 42 | 43 | void registerMessageCallback(const google::protobuf::Descriptor* descriptor, 44 | const ProtobufMessageCallback& message_callback) 45 | { 46 | callbacks_[descriptor] = message_callback; 47 | } 48 | 49 | private: 50 | typedef std::map CallbackMap; 51 | 52 | CallbackMap callbacks_; 53 | ProtobufMessageCallback default_message_callbcak_; 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /example/protobuf/codec/dispatcher_lite_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace blink; 7 | 8 | typedef boost::shared_ptr QueryPtr; 9 | typedef boost::shared_ptr AnswerPtr; 10 | 11 | void onQuery(const TcpConnectionPtr& connection, 12 | const MessagePtr& message, 13 | Timestamp) 14 | { 15 | std::cout << "onQuery: " << message->GetTypeName() << std::endl; 16 | boost::shared_ptr query = down_pointer_cast(message); 17 | assert(query != NULL); 18 | } 19 | 20 | void onAnswer(const TcpConnectionPtr& connection, 21 | const MessagePtr& message, 22 | Timestamp) 23 | { 24 | std::cout << "onAnwser: " <GetTypeName() << std::endl; 25 | boost::shared_ptr answer = down_pointer_cast(message); 26 | assert(answer != NULL); 27 | } 28 | 29 | void onUnknownMessageType(const TcpConnectionPtr& connection, 30 | const MessagePtr& message, 31 | Timestamp) 32 | { 33 | std::cout << "onknownMessageType: " << message->GetTypeName() << std::endl; 34 | } 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | GOOGLE_PROTOBUF_VERIFY_VERSION; 39 | ProtobufDispatcherLite dispatcher(onUnknownMessageType); 40 | dispatcher.registerMessageCallback(Query::descriptor(), onQuery); 41 | dispatcher.registerMessageCallback(Answer::descriptor(), onAnswer); 42 | 43 | TcpConnectionPtr connection; 44 | Timestamp t; 45 | 46 | boost::shared_ptr query(new Query); 47 | boost::shared_ptr answer(new Answer); 48 | boost::shared_ptr empty(new Empty); 49 | dispatcher.onProtobufMessage(connection, query, t); 50 | dispatcher.onProtobufMessage(connection, answer, t); 51 | dispatcher.onProtobufMessage(connection, empty, t); 52 | 53 | google::protobuf::ShutdownProtobufLibrary(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /example/protobuf/codec/dispatcher_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace blink; 7 | 8 | typedef boost::shared_ptr QueryPtr; 9 | typedef boost::shared_ptr AnswerPtr; 10 | 11 | void test_down_pointer_cast() 12 | { 13 | boost::shared_ptr message(new Query); 14 | boost::shared_ptr query(down_pointer_cast(message)); 15 | assert(message && query); 16 | if (!query) 17 | { 18 | abort(); 19 | } 20 | } 21 | 22 | void onQuery(const TcpConnectionPtr& connection, 23 | const QueryPtr& message, 24 | Timestamp) 25 | { 26 | std::cout << "onQuery: " << message->GetTypeName() << std::endl; 27 | } 28 | 29 | void onAnswer(const TcpConnectionPtr& connection, 30 | const AnswerPtr& message, 31 | Timestamp) 32 | { 33 | std::cout << "onAnwser: " <GetTypeName() << std::endl; 34 | } 35 | 36 | void onUnknownMessageType(const TcpConnectionPtr& connection, 37 | const MessagePtr& message, 38 | Timestamp) 39 | { 40 | std::cout << "onknownMessageType: " << message->GetTypeName() << std::endl; 41 | } 42 | 43 | int main(int argc, char* argv[]) 44 | { 45 | GOOGLE_PROTOBUF_VERIFY_VERSION; 46 | test_down_pointer_cast(); 47 | ProtobufDispatcher dispatcher(onUnknownMessageType); 48 | dispatcher.registerMessageCallback(onQuery); 49 | dispatcher.registerMessageCallback(onAnswer); 50 | 51 | TcpConnectionPtr connection; 52 | Timestamp t; 53 | 54 | boost::shared_ptr query(new Query); 55 | boost::shared_ptr answer(new Answer); 56 | boost::shared_ptr empty(new Empty); 57 | dispatcher.onProtobufMessage(connection, query, t); 58 | dispatcher.onProtobufMessage(connection, answer, t); 59 | dispatcher.onProtobufMessage(connection, empty, t); 60 | 61 | google::protobuf::ShutdownProtobufLibrary(); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /example/protobuf/codec/query.proto: -------------------------------------------------------------------------------- 1 | package blink; 2 | 3 | option cc_generic_services = true; 4 | option py_generic_services = true; 5 | option java_generic_services = true; 6 | 7 | message Query 8 | { 9 | required int64 id = 1; 10 | required string questioner = 2; 11 | repeated string question = 3; 12 | } 13 | 14 | message Answer 15 | { 16 | required int64 id = 1; 17 | required string questioner = 2; 18 | required string answer = 3; 19 | repeated string solution = 4; 20 | } 21 | 22 | message Empty 23 | { 24 | optional int32 id = 1; 25 | } 26 | -------------------------------------------------------------------------------- /example/protobuf/resolver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/protobuf/resolver) 2 | 3 | add_custom_command(OUTPUT resolver.pb.h resolver.pb.cc 4 | COMMAND protoc 5 | ARGS -I=${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/resolver.proto 6 | DEPENDS resolver.proto 7 | VERBATIM) 8 | 9 | set_source_files_properties(resolver.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 10 | 11 | add_executable(protobuf_resolver_client client.cpp resolver.pb.cc) 12 | set_target_properties(protobuf_resolver_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 13 | target_link_libraries(protobuf_resolver_client blink_protorpc protobuf) 14 | 15 | add_executable(protobuf_resolver_server server.cpp resolver.pb.cc) 16 | set_target_properties(protobuf_resolver_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 17 | target_link_libraries(protobuf_resolver_server blink_protorpc protobuf) 18 | -------------------------------------------------------------------------------- /example/protobuf/resolver/resolver.proto: -------------------------------------------------------------------------------- 1 | package resolver; 2 | 3 | option cc_generic_services = true; 4 | option java_generic_services = true; 5 | option py_generic_services = true; 6 | 7 | message ResolveRequest 8 | { 9 | required string adress = 1; 10 | } 11 | 12 | message ResolveResponse 13 | { 14 | optional bool resolved = 1 [default = false]; 15 | repeated fixed32 ip = 2; 16 | repeated int32 port = 3; 17 | } 18 | 19 | service ResolverService 20 | { 21 | rpc solve (ResolveRequest) returns (ResolveResponse); 22 | } 23 | -------------------------------------------------------------------------------- /example/protobuf/resolver/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | namespace resolver 13 | { 14 | 15 | class ResolverServiceImpl : public resolver::ResolverService 16 | { 17 | public: 18 | void solve(::google::protobuf::RpcController* controller, 19 | const resolver::ResolveRequest* request, 20 | resolver::ResolveResponse* response, 21 | ::google::protobuf::Closure* done) 22 | { 23 | response->set_resolved(true); 24 | struct sockaddr_in addr; 25 | sockets::fromIpPort("10.33.1.48", 9600, &addr); 26 | response->add_ip(addr.sin_addr.s_addr); 27 | response->add_port(9600); 28 | done->Run(); 29 | } 30 | }; 31 | 32 | } // namespace resolver 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | LOG_INFO << "pid = " << getpid(); 37 | EventLoop loop; 38 | resolver::ResolverServiceImpl impl; 39 | RpcServer server(&loop, InetAddress(9600), "RpcServer"); 40 | server.registerService(&impl); 41 | server.start(); 42 | loop.loop(); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /example/protobuf/rpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/protobuf/rpc) 2 | 3 | add_custom_command(OUTPUT sudoku.pb.h sudoku.pb.cc 4 | COMMAND protoc 5 | ARGS -I=${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/sudoku.proto 6 | DEPENDS sudoku.proto 7 | VERBATIM) 8 | 9 | set_source_files_properties(sudoku.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 10 | 11 | add_executable(protobuf_rpc_client client.cpp sudoku.pb.cc) 12 | set_target_properties(protobuf_rpc_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 13 | target_link_libraries(protobuf_rpc_client blink_protorpc protobuf) 14 | 15 | add_executable(protobuf_rpc_server server.cpp sudoku.pb.cc) 16 | set_target_properties(protobuf_rpc_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 17 | target_link_libraries(protobuf_rpc_server blink_protorpc protobuf) 18 | -------------------------------------------------------------------------------- /example/protobuf/rpc/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | using namespace blink; 10 | 11 | namespace sudoku 12 | { 13 | 14 | class SudokuServiceImpl : public SudokuService 15 | { 16 | public: 17 | virtual void solve(::google::protobuf::RpcController* controller, 18 | const ::sudoku::SudokuRequest* request, 19 | ::sudoku::SudokuResponse* response, 20 | ::google::protobuf::Closure* done) 21 | { 22 | LOG_INFO << "SudokuServiceImpl::solve"; 23 | response->set_solved(true); 24 | response->set_checkerboard("1234567"); 25 | done->Run(); 26 | } 27 | }; 28 | 29 | } // namespace sudoku 30 | 31 | int main(int argc, char* argv[]) 32 | { 33 | LOG_INFO << "pid = " << getpid(); 34 | EventLoop loop; 35 | InetAddress listen_addr(9600); 36 | sudoku::SudokuServiceImpl impl; 37 | RpcServer server(&loop, listen_addr, "RpcServer"); 38 | server.registerService(&impl); 39 | server.start(); 40 | loop.loop(); 41 | google::protobuf::ShutdownProtobufLibrary(); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /example/protobuf/rpc/sudoku.proto: -------------------------------------------------------------------------------- 1 | package sudoku; 2 | 3 | option cc_generic_services = true; 4 | option java_generic_services = true; 5 | option py_generic_services = true; 6 | 7 | message SudokuRequest 8 | { 9 | required string checkerboard = 1; 10 | } 11 | 12 | message SudokuResponse 13 | { 14 | optional bool solved = 1 [default = false]; 15 | optional string checkerboard = 2; 16 | } 17 | 18 | service SudokuService 19 | { 20 | rpc solve (SudokuRequest) returns (SudokuResponse); 21 | } 22 | -------------------------------------------------------------------------------- /example/protobuf/rpcbalancer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/protobuf/rpcbalancer) 2 | 3 | add_executable(rpc_balancer balancer.cpp) 4 | set_target_properties(rpc_balancer PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 5 | target_link_libraries(rpc_balancer blink_protorpc) 6 | 7 | add_executable(rpc_balancer_raw balancer_raw.cpp) 8 | set_target_properties(rpc_balancer_raw PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 9 | target_link_libraries(rpc_balancer_raw blink_protorpc) 10 | -------------------------------------------------------------------------------- /example/protobuf/rpcbench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/protobuf/rpcbench) 2 | 3 | add_custom_command(OUTPUT echo.pb.h echo.pb.cc 4 | COMMAND protoc 5 | ARGS -I=${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/echo.proto 6 | DEPENDS echo.proto 7 | VERBATIM) 8 | 9 | set_source_files_properties(echo.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 10 | 11 | add_executable(protobuf_rpcbench_client client.cpp echo.pb.cc) 12 | set_target_properties(protobuf_rpcbench_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 13 | target_link_libraries(protobuf_rpcbench_client blink_protorpc protobuf) 14 | 15 | add_executable(protobuf_rpcbench_server server.cpp echo.pb.cc) 16 | set_target_properties(protobuf_rpcbench_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 17 | target_link_libraries(protobuf_rpcbench_server blink_protorpc protobuf) 18 | -------------------------------------------------------------------------------- /example/protobuf/rpcbench/echo.proto: -------------------------------------------------------------------------------- 1 | package echo; 2 | 3 | option cc_generic_services = true; 4 | option py_generic_services = true; 5 | option java_generic_services = true; 6 | 7 | message EchoRequest 8 | { 9 | required string payload = 1; 10 | } 11 | 12 | message EchoResponse 13 | { 14 | required string payload = 1; 15 | } 16 | 17 | service EchoService 18 | { 19 | rpc echo (EchoRequest) returns (EchoResponse); 20 | } 21 | -------------------------------------------------------------------------------- /example/protobuf/rpcbench/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace blink; 8 | 9 | namespace echo 10 | { 11 | 12 | class EchoServiceImpl : public echo::EchoService 13 | { 14 | public: 15 | void echo(::google::protobuf::RpcController* controller, 16 | const ::echo::EchoRequest* request, 17 | ::echo::EchoResponse* response, 18 | ::google::protobuf::Closure* done) 19 | { 20 | response->set_payload(request->payload()); 21 | done->Run(); 22 | } 23 | }; 24 | 25 | } // namespace echo 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | int n_threads = 1; 30 | if (argc == 2) 31 | { 32 | n_threads = atoi(argv[1]); 33 | } 34 | LOG_INFO << "pid = " << getpid() << " threads = " << n_threads; 35 | EventLoop loop; 36 | echo::EchoServiceImpl impl; 37 | RpcServer server(&loop, InetAddress(9600), "RpcServer"); 38 | server.setThreadNumer(n_threads); 39 | server.registerService(&impl); 40 | server.start(); 41 | loop.loop(); 42 | exit(0); 43 | } 44 | -------------------------------------------------------------------------------- /example/roundtrip/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/roundtrip) 2 | 3 | add_executable(Roundtrip Roundtrip.cpp) 4 | target_link_libraries(Roundtrip blink) 5 | 6 | add_executable(RoundtripUdp RoundtripUdp.cpp) 7 | target_link_libraries(RoundtripUdp blink) 8 | -------------------------------------------------------------------------------- /example/shorturl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/shorturl) 2 | 3 | add_executable(ShortUrl ShortUrl.cpp) 4 | target_link_libraries(ShortUrl blink_http) 5 | -------------------------------------------------------------------------------- /example/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(all_in_one) 2 | add_subdirectory(chargen) 3 | add_subdirectory(daytime) 4 | add_subdirectory(discard) 5 | add_subdirectory(echo) 6 | add_subdirectory(time) 7 | -------------------------------------------------------------------------------- /example/simple/all_in_one/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/simple/all_in_one) 2 | 3 | add_executable(all_in_one 4 | main.cpp 5 | ../chargen/ChargenServer.cpp 6 | ../daytime/DaytimeServer.cpp 7 | ../discard/DiscardServer.cpp 8 | ../echo/EchoServer.cpp 9 | ../time/TimeServer.cpp 10 | ) 11 | target_link_libraries(all_in_one blink) 12 | -------------------------------------------------------------------------------- /example/simple/all_in_one/main.cpp: -------------------------------------------------------------------------------- 1 | #include "example/simple/chargen/ChargenServer.h" 2 | #include "example/simple/daytime/DaytimeServer.h" 3 | #include "example/simple/discard/DiscardServer.h" 4 | #include "example/simple/echo/EchoServer.h" 5 | #include "example/simple/time/TimeServer.h" 6 | 7 | #include 8 | #include 9 | 10 | int main(int argc, char const *argv[]) 11 | { 12 | blink::EventLoop loop; 13 | 14 | ChargenServer chargen_server(&loop, blink::InetAddress(9600), "ChargenServer"); 15 | chargen_server.start(); 16 | 17 | DaytimeServer daytime_server(&loop, blink::InetAddress(9601), "DaytimeServer"); 18 | daytime_server.start(); 19 | 20 | DiscardServer discard_server(&loop, blink::InetAddress(9602), "DiscardServer"); 21 | discard_server.start(); 22 | 23 | EchoServer echo_server(&loop, blink::InetAddress(9603), "EchoServer"); 24 | echo_server.start(); 25 | 26 | TimeServer time_server(&loop, blink::InetAddress(9604), "TimeServer"); 27 | time_server.start(); 28 | 29 | loop.loop(); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /example/simple/chargen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/simple/chargen) 2 | 3 | add_executable(simple_chargen_client client.cpp ChargenClient.cpp) 4 | target_link_libraries(simple_chargen_client blink) 5 | 6 | add_executable(simple_chargen_server server.cpp ChargenServer.cpp) 7 | target_link_libraries(simple_chargen_server blink) 8 | -------------------------------------------------------------------------------- /example/simple/chargen/ChargenClient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | using namespace blink; 10 | 11 | ChargenClient::ChargenClient(EventLoop* loop, const InetAddress& server_addr, const string& name) 12 | : loop_(loop), client_(loop, server_addr, name) 13 | { 14 | client_.setConnectionCallback(boost::bind(&ChargenClient::onConnection, this, _1)); 15 | client_.setMessageCallback(boost::bind(&ChargenClient::onMessage, this, _1, _2, _3)); 16 | } 17 | 18 | void ChargenClient::connect() 19 | { 20 | client_.connect(); 21 | } 22 | 23 | void ChargenClient::onConnection(const TcpConnectionPtr& connection) 24 | { 25 | LOG_INFO << connection->localAddress().toIpPort() << " -> " 26 | << connection->peerAddress().toIpPort() << " is " 27 | << (connection->connected() ? "UP" : "DOWN"); 28 | if (!connection->connected()) 29 | { 30 | loop_->quit(); 31 | } 32 | } 33 | 34 | void ChargenClient::onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 35 | { 36 | string msg = buf->resetAllToString(); 37 | printf("received data size = %zd bytes.\n", msg.size()); 38 | } 39 | -------------------------------------------------------------------------------- /example/simple/chargen/ChargenClient.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_CHARGENCLIENT_H__ 2 | #define __EXAMPLE_CHARGENCLIENT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class ChargenClient : blink::Nocopyable 10 | { 11 | public: 12 | ChargenClient(blink::EventLoop* loop, 13 | const blink::InetAddress& server_addr, 14 | const blink::string& name); 15 | 16 | void connect(); 17 | 18 | private: 19 | void onConnection(const blink::TcpConnectionPtr& connection); 20 | void onMessage(const blink::TcpConnectionPtr& connection, 21 | blink::Buffer* buf, 22 | blink::Timestamp time); 23 | 24 | blink::EventLoop* loop_; 25 | blink::TcpClient client_; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /example/simple/chargen/ChargenServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_CHARGENSERVER_H__ 2 | #define __EXAMPLE_CHARGENSERVER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class ChargenServer : blink::Nocopyable 10 | { 11 | public: 12 | ChargenServer(blink::EventLoop* loop, 13 | const blink::InetAddress& server_addr, 14 | const blink::string& name, 15 | bool print = false); 16 | 17 | void start(); 18 | 19 | private: 20 | void onConnection(const blink::TcpConnectionPtr& connection); 21 | void onMessage(const blink::TcpConnectionPtr& connection, 22 | blink::Buffer* buf, 23 | blink::Timestamp time); 24 | void onWriteComplete(const blink::TcpConnectionPtr& connection); 25 | void printThroughput(); 26 | 27 | blink::EventLoop* loop_; 28 | blink::TcpServer server_; 29 | blink::string message_; 30 | int64_t transferred_; 31 | blink::Timestamp start_time_; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /example/simple/chargen/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | using namespace blink; 13 | 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | if (argc != 3) 18 | { 19 | fprintf(stderr, "usage: %s \n", argv[0]); 20 | return 1; 21 | } 22 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 23 | EventLoop loop; 24 | InetAddress server_addr(argv[1], static_cast(atoi(argv[2]))); 25 | ChargenClient client(&loop, server_addr, "ChargenClient"); 26 | client.connect(); 27 | loop.loop(); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /example/simple/chargen/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 15 | EventLoop loop; 16 | InetAddress server_addr(9600); 17 | ChargenServer server(&loop, server_addr, "ChargenServer", true); 18 | server.start(); 19 | loop.loop(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /example/simple/daytime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/simple/daytime) 2 | 3 | add_executable(simple_daytime_client client.cpp) 4 | target_link_libraries(simple_daytime_client blink) 5 | 6 | add_executable(simple_daytime_server server.cpp DaytimeServer.cpp) 7 | target_link_libraries(simple_daytime_server blink) 8 | -------------------------------------------------------------------------------- /example/simple/daytime/DaytimeServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | using namespace blink; 13 | 14 | const int64_t kTimeZoneValue = static_cast(8) * 3600 * 1000 * 1000; 15 | 16 | DaytimeServer::DaytimeServer(EventLoop* loop, 17 | const InetAddress& server_addr, 18 | const string& name) 19 | : loop_(loop), server_(loop, server_addr, name) 20 | { 21 | server_.setConnectionCallback(boost::bind(&DaytimeServer::onConnection, this, _1)); 22 | server_.setMessageCallback(boost::bind(&DaytimeServer::onMessage, this, _1, _2, _3)); 23 | } 24 | 25 | void DaytimeServer::start() 26 | { 27 | server_.start(); 28 | } 29 | 30 | void DaytimeServer::onConnection(const TcpConnectionPtr& connection) 31 | { 32 | LOG_INFO << "DaytimeServer - " << connection->peerAddress().toIpPort() << " -> " 33 | << connection->localAddress().toIpPort() << " is " 34 | << (connection->connected() ? "UP" : "DOWN"); 35 | if (connection->connected()) 36 | { 37 | Timestamp now(Timestamp::now().microSecondsSinceEpoch() + kTimeZoneValue); 38 | connection->send(now.toFormattedString()); 39 | connection->shutdown(); 40 | } 41 | } 42 | 43 | void DaytimeServer::onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 44 | { 45 | string message = buf->resetAllToString(); 46 | LOG_INFO << connection->name() << " discards " << message.size() << " bytes received at " 47 | << Timestamp(time.microSecondsSinceEpoch() + kTimeZoneValue).toFormattedString(); 48 | } 49 | -------------------------------------------------------------------------------- /example/simple/daytime/DaytimeServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_DAYTIMESERVER_H__ 2 | #define __EXAMPLE_DAYTIMESERVER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class DaytimeServer : blink::Nocopyable 10 | { 11 | public: 12 | DaytimeServer(blink::EventLoop* loop, 13 | const blink::InetAddress& server_addr, 14 | const blink::string& name); 15 | 16 | void start(); 17 | 18 | private: 19 | void onConnection(const blink::TcpConnectionPtr& connection); 20 | void onMessage(const blink::TcpConnectionPtr& connection, 21 | blink::Buffer* buf, 22 | blink::Timestamp time); 23 | 24 | blink::EventLoop* loop_; 25 | blink::TcpServer server_; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /example/simple/daytime/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | using namespace blink; 15 | 16 | class Client 17 | { 18 | public: 19 | Client(EventLoop* loop, const InetAddress& server_addr, const string& name) 20 | : loop_(loop), client_(loop, server_addr, name) 21 | { 22 | client_.setConnectionCallback(boost::bind(&Client::onConnection, this, _1)); 23 | client_.setMessageCallback(boost::bind(&Client::onMessage, this, _1, _2, _3)); 24 | } 25 | 26 | void connect() 27 | { 28 | client_.connect(); 29 | } 30 | 31 | private: 32 | void onConnection(const TcpConnectionPtr& connection) 33 | { 34 | LOG_TRACE << connection->localAddress().toIpPort() << " -> " 35 | << connection->peerAddress().toIpPort() << " is " 36 | << (connection->connected() ? "UP" : "DOWN"); 37 | if (!connection->connected()) 38 | { 39 | loop_->quit(); 40 | } 41 | } 42 | 43 | void onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 44 | { 45 | string message = buf->resetAllToString(); 46 | LOG_INFO << "Server time: " << message; 47 | connection->shutdown(); 48 | } 49 | 50 | EventLoop* loop_; 51 | TcpClient client_; 52 | }; 53 | 54 | int main(int argc, char const *argv[]) 55 | { 56 | if (argc != 3) 57 | { 58 | fprintf(stderr, "usage: %s \n", argv[0]); 59 | return 1; 60 | } 61 | LOG_INFO << "pid = " << ::getpid() << ", tid" << current_thread::tid(); 62 | EventLoop loop; 63 | InetAddress server_addr(argv[1], static_cast(atoi(argv[2]))); 64 | Client client(&loop, server_addr, "Client"); 65 | client.connect(); 66 | loop.loop(); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /example/simple/daytime/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 15 | EventLoop loop; 16 | InetAddress server_addr(9600); 17 | DaytimeServer server(&loop, server_addr, "DaytimeServer"); 18 | server.start(); 19 | loop.loop(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /example/simple/discard/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/simple/discard) 2 | 3 | add_executable(simple_discard_client client.cpp) 4 | target_link_libraries(simple_discard_client blink) 5 | 6 | add_executable(simple_discard_server server.cpp DiscardServer.cpp) 7 | target_link_libraries(simple_discard_server blink) 8 | -------------------------------------------------------------------------------- /example/simple/discard/DiscardServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | using namespace blink; 14 | using namespace blink::sockets; 15 | 16 | const int64_t kTimeZoneValue = static_cast(8) * 3600 * 1000 * 1000; 17 | 18 | DiscardServer::DiscardServer(EventLoop* loop, 19 | const InetAddress& server_addr, 20 | const string& name) 21 | : loop_(loop), server_(loop, server_addr, name) 22 | { 23 | server_.setConnectionCallback(boost::bind(&DiscardServer::onConnection, this, _1)); 24 | server_.setMessageCallback(boost::bind(&DiscardServer::onMessage, this, _1, _2, _3)); 25 | } 26 | 27 | void DiscardServer::start() 28 | { 29 | server_.start(); 30 | } 31 | 32 | void DiscardServer::onConnection(const TcpConnectionPtr& connection) 33 | { 34 | LOG_INFO << "DiscardServer - " << connection->peerAddress().toIpPort() << " -> " 35 | << connection->localAddress().toIpPort() << " is " 36 | << (connection->connected() ? "UP" : "DOWN"); 37 | } 38 | 39 | void DiscardServer::onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 40 | { 41 | string message = buf->resetAllToString(); 42 | LOG_INFO << connection->name() << " discards " << message.size() << " bytes received at " 43 | << Timestamp(time.microSecondsSinceEpoch() + kTimeZoneValue).toFormattedString(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /example/simple/discard/DiscardServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_DISCARDSERVER_H__ 2 | #define __EXAMPLE_DISCARDSERVER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class DiscardServer : blink::Nocopyable 10 | { 11 | public: 12 | DiscardServer(blink::EventLoop* loop, 13 | const blink::InetAddress& server_addr, 14 | const blink::string& name); 15 | 16 | void start(); 17 | 18 | private: 19 | void onConnection(const blink::TcpConnectionPtr& connection); 20 | void onMessage(const blink::TcpConnectionPtr& connection, 21 | blink::Buffer* buf, 22 | blink::Timestamp time); 23 | 24 | blink::EventLoop* loop_; 25 | blink::TcpServer server_; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /example/simple/discard/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 15 | EventLoop loop; 16 | InetAddress server_addr(9600); 17 | DiscardServer server(&loop, server_addr, "DiscardServer"); 18 | server.start(); 19 | loop.loop(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /example/simple/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/simple/echo) 2 | 3 | add_executable(simple_echo_client client.cpp EchoClient.cpp) 4 | target_link_libraries(simple_echo_client blink) 5 | 6 | add_executable(simple_echo_server server.cpp EchoServer.cpp) 7 | target_link_libraries(simple_echo_server blink) 8 | -------------------------------------------------------------------------------- /example/simple/echo/EchoClient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | using namespace blink; 13 | 14 | EchoClient::EchoClient(EventLoop* loop, const InetAddress& server_addr, const string& name) 15 | : loop_(loop), client_(loop, server_addr, name) 16 | { 17 | client_.setConnectionCallback(boost::bind(&EchoClient::onConnection, this, _1)); 18 | client_.setMessageCallback(boost::bind(&EchoClient::onMessage, this, _1, _2, _3)); 19 | } 20 | 21 | void EchoClient::connect() 22 | { 23 | client_.connect(); 24 | } 25 | 26 | void EchoClient::onConnection(const TcpConnectionPtr& connection) 27 | { 28 | LOG_TRACE << connection->localAddress().toIpPort() << " -> " 29 | << connection->peerAddress().toIpPort() << " is " 30 | << (connection->connected() ? "UP" : "DOWN"); 31 | if (connection->connected()) 32 | { 33 | connection->send("world\n"); 34 | } 35 | } 36 | 37 | void EchoClient::onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 38 | { 39 | string message = buf->resetAllToString(); 40 | LOG_TRACE << connection->name() << " receive " << message.size() 41 | << " bytes at " << time.toFormattedString(); 42 | if (message == "q\n" || message == "quit\n") 43 | { 44 | connection->send("bye"); 45 | connection->shutdown(); 46 | } 47 | else if (message == "shutdown\n") 48 | { 49 | loop_->quit(); 50 | } 51 | else 52 | { 53 | printf("%s\n", message.c_str()); 54 | connection->send(message); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/simple/echo/EchoClient.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_ECHOCLIENT_H__ 2 | #define __EXAMPLE_ECHOCLIENT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class EchoClient : blink::Nocopyable 10 | { 11 | public: 12 | EchoClient(blink::EventLoop* loop, 13 | const blink::InetAddress& server_addr, 14 | const blink::string& name); 15 | 16 | void connect(); 17 | 18 | private: 19 | void onConnection(const blink::TcpConnectionPtr& connection); 20 | 21 | void onMessage(const blink::TcpConnectionPtr& connection, 22 | blink::Buffer* buf, 23 | blink::Timestamp time); 24 | 25 | blink::EventLoop* loop_; 26 | blink::TcpClient client_; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /example/simple/echo/EchoServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | using namespace blink; 10 | 11 | int g_threadNumber = 0; 12 | 13 | EchoServer::EchoServer(EventLoop* loop, const InetAddress& listen_addr, const string& name) 14 | : loop_(loop), server_(loop, listen_addr, name) 15 | { 16 | server_.setConnectionCallback(boost::bind(&EchoServer::onConnection, this, _1)); 17 | server_.setMessageCallback(boost::bind(&EchoServer::onMessage, this, _1, _2, _3)); 18 | server_.setThreadNumber(g_threadNumber); 19 | } 20 | 21 | void EchoServer::start() 22 | { 23 | server_.start(); 24 | } 25 | 26 | void EchoServer::onConnection(const TcpConnectionPtr& connection) 27 | { 28 | LOG_TRACE << connection->peerAddress().toIpPort() << " -> " 29 | << connection->peerAddress().toIpPort() << " is " 30 | << (connection->connected() ? "UP" : "DOWN"); 31 | LOG_INFO << connection->getTcpInfoString(); 32 | connection->send("hello\n"); 33 | } 34 | 35 | void EchoServer::onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 36 | { 37 | string message = buf->resetAllToString(); 38 | LOG_TRACE << connection->name() << " receive " << message.size() 39 | << " bytes at " << time.toFormattedString(); 40 | if (message == "exit\n") 41 | { 42 | connection->send("bye\n"); 43 | connection->shutdown(); 44 | } 45 | if (message == "q\n" || message == "quit\n") 46 | { 47 | loop_->quit(); 48 | } 49 | else 50 | { 51 | printf("%s\n", message.c_str()); 52 | connection->send(message); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/simple/echo/EchoServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_ECHOSERVER_H__ 2 | #define __EXAMPLE_ECHOSERVER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class EchoServer : blink::Nocopyable 10 | { 11 | public: 12 | EchoServer(blink::EventLoop* loop, 13 | const blink::InetAddress& listen_addr, 14 | const blink::string& name); 15 | 16 | void start(); 17 | 18 | private: 19 | void onConnection(const blink::TcpConnectionPtr& connection); 20 | 21 | void onMessage(const blink::TcpConnectionPtr& connection, 22 | blink::Buffer* buf, 23 | blink::Timestamp time); 24 | 25 | blink::EventLoop* loop_; 26 | blink::TcpServer server_; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /example/simple/echo/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | using namespace blink; 13 | 14 | int main(int argc, char const *argv[]) 15 | { 16 | if (argc != 3) 17 | { 18 | fprintf(stderr, "usage: %s \n", argv[0]); 19 | return 1; 20 | } 21 | LOG_INFO << "pid = " << ::getpid() << ", tid" << current_thread::tid(); 22 | EventLoop loop; 23 | InetAddress server_addr(argv[1], static_cast(atoi(argv[2]))); 24 | EchoClient client(&loop, server_addr, "EchoClient"); 25 | client.connect(); 26 | loop.loop(); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /example/simple/echo/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 15 | LOG_INFO << "sizeof TcpConnection = " << sizeof(TcpConnection); 16 | EventLoop loop; 17 | InetAddress listen_addr(9600); 18 | EchoServer server(&loop, listen_addr, "EchoServer"); 19 | server.start(); 20 | loop.loop(); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /example/simple/time/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/simple/time) 2 | 3 | add_executable(simple_time_client client.cpp) 4 | target_link_libraries(simple_time_client blink) 5 | 6 | add_executable(simple_time_server server.cpp TimeServer.cpp) 7 | target_link_libraries(simple_time_server blink) 8 | -------------------------------------------------------------------------------- /example/simple/time/TimeServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | using namespace blink; 14 | using namespace blink::sockets; 15 | 16 | const int64_t kTimeZoneValue = static_cast(8) * 3600 * 1000 * 1000; 17 | 18 | TimeServer::TimeServer(EventLoop* loop, 19 | const InetAddress& server_addr, 20 | const string& name) 21 | : loop_(loop), server_(loop, server_addr, name) 22 | { 23 | server_.setConnectionCallback(boost::bind(&TimeServer::onConnection, this, _1)); 24 | server_.setMessageCallback(boost::bind(&TimeServer::onMessage, this, _1, _2, _3)); 25 | } 26 | 27 | void TimeServer::start() 28 | { 29 | server_.start(); 30 | } 31 | 32 | void TimeServer::onConnection(const TcpConnectionPtr& connection) 33 | { 34 | LOG_INFO << "TimeServer - " << connection->peerAddress().toIpPort() << " -> " 35 | << connection->localAddress().toIpPort() << " is " 36 | << (connection->connected() ? "UP" : "DOWN"); 37 | if (connection->connected()) 38 | { 39 | Timestamp time_now(Timestamp::now().microSecondsSinceEpoch() + kTimeZoneValue); 40 | int64_t now = hostToNetwork64(time_now.microSecondsSinceEpoch()); 41 | connection->send(&now, sizeof(now)); 42 | connection->shutdown(); 43 | } 44 | } 45 | 46 | void TimeServer::onMessage(const TcpConnectionPtr& connection, Buffer* buf, Timestamp time) 47 | { 48 | string message = buf->resetAllToString(); 49 | LOG_INFO << connection->name() << " discards " << message.size() << " bytes received at " 50 | << Timestamp(time.microSecondsSinceEpoch() + kTimeZoneValue).toFormattedString(); 51 | } 52 | -------------------------------------------------------------------------------- /example/simple/time/TimeServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_TIMESERVER_H__ 2 | #define __EXAMPLE_TIMESERVER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class TimeServer : blink::Nocopyable 10 | { 11 | public: 12 | TimeServer(blink::EventLoop* loop, 13 | const blink::InetAddress& server_addr, 14 | const blink::string& name); 15 | 16 | void start(); 17 | 18 | private: 19 | void onConnection(const blink::TcpConnectionPtr& connection); 20 | void onMessage(const blink::TcpConnectionPtr& connection, 21 | blink::Buffer* buf, 22 | blink::Timestamp time); 23 | 24 | blink::EventLoop* loop_; 25 | blink::TcpServer server_; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /example/simple/time/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace blink; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | LOG_INFO << "pid = " << getpid() << ", tid = " << current_thread::tid(); 15 | EventLoop loop; 16 | InetAddress server_addr(9600); 17 | TimeServer server(&loop, server_addr, "TimeServer"); 18 | server.start(); 19 | loop.loop(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /example/socks4a/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/socks4a) 2 | 3 | add_executable(tcprelay tcprelay.cpp) 4 | target_link_libraries(tcprelay blink) 5 | 6 | add_executable(socks4a socks4a.cpp) 7 | target_link_libraries(socks4a blink) 8 | 9 | add_executable(balancer balancer.cpp) 10 | target_link_libraries(balancer blink) 11 | -------------------------------------------------------------------------------- /example/twisted/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(finger) 2 | -------------------------------------------------------------------------------- /example/twisted/finger/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/twisted/finger) 2 | 3 | add_executable(finger1 finger1.cpp) 4 | target_link_libraries(finger1 blink) 5 | 6 | add_executable(finger2 finger2.cpp) 7 | target_link_libraries(finger2 blink) 8 | 9 | add_executable(finger3 finger3.cpp) 10 | target_link_libraries(finger3 blink) 11 | 12 | add_executable(finger4 finger4.cpp) 13 | target_link_libraries(finger4 blink) 14 | 15 | add_executable(finger5 finger5.cpp) 16 | target_link_libraries(finger5 blink) 17 | 18 | add_executable(finger6 finger6.cpp) 19 | target_link_libraries(finger6 blink) 20 | 21 | add_executable(finger7 finger7.cpp) 22 | target_link_libraries(finger7 blink) 23 | -------------------------------------------------------------------------------- /example/twisted/finger/finger1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char const *argv[]) 4 | { 5 | blink::EventLoop loop; 6 | loop.loop(); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /example/twisted/finger/finger2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char const *argv[]) 5 | { 6 | blink::EventLoop loop; 7 | blink::TcpServer server(&loop, blink::InetAddress(9600), "FingerServer"); 8 | server.start(); 9 | loop.loop(); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /example/twisted/finger/finger3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace blink; 5 | 6 | void onConnection(const TcpConnectionPtr& connection) 7 | { 8 | if (connection->connected()) 9 | { 10 | connection->shutdown(); 11 | } 12 | } 13 | 14 | int main(int argc, char const *argv[]) 15 | { 16 | EventLoop loop; 17 | TcpServer server(&loop, InetAddress(9600), "FingerServer"); 18 | server.setConnectionCallback(onConnection); 19 | server.start(); 20 | loop.loop(); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /example/twisted/finger/finger4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace blink; 5 | 6 | void onMessage(const TcpConnectionPtr& connection, 7 | Buffer* buf, 8 | Timestamp receive_time) 9 | { 10 | if (buf->findCRLF()) 11 | { 12 | connection->shutdown(); 13 | } 14 | } 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | EventLoop loop; 19 | TcpServer server(&loop, InetAddress(9600), "FingerServer"); 20 | server.setMessageCallback(onMessage); 21 | server.start(); 22 | loop.loop(); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /example/twisted/finger/finger5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace blink; 5 | 6 | void onMessage(const TcpConnectionPtr& connection, 7 | Buffer* buf, 8 | Timestamp receive_time) 9 | { 10 | if (buf->findCRLF()) 11 | { 12 | connection->send("No such server\r\n"); 13 | connection->shutdown(); 14 | } 15 | } 16 | 17 | int main(int argc, char const *argv[]) 18 | { 19 | EventLoop loop; 20 | TcpServer server(&loop, InetAddress(9600), "FingerServer"); 21 | server.setMessageCallback(onMessage); 22 | server.start(); 23 | loop.loop(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /example/twisted/finger/finger6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace blink; 7 | 8 | typedef std::map UserMap; 9 | UserMap users; 10 | 11 | string getUser(const string& user) 12 | { 13 | string result("No such user"); 14 | UserMap::iterator it = users.find(user); 15 | if (it != users.end()) 16 | { 17 | result = it->second; 18 | } 19 | return result; 20 | } 21 | 22 | void onMessage(const TcpConnectionPtr& connection, 23 | Buffer* buf, 24 | Timestamp receive_time) 25 | { 26 | const char* crlf = buf->findCRLF(); 27 | if (crlf) 28 | { 29 | string user(buf->peek(), crlf); 30 | connection->send(getUser(user) + "\r\n"); 31 | buf->resetUntil(crlf + 2); 32 | connection->shutdown(); 33 | } 34 | } 35 | 36 | int main(int argc, char const *argv[]) 37 | { 38 | EventLoop loop; 39 | TcpServer server(&loop, InetAddress(9600), "FingerServer"); 40 | server.setMessageCallback(onMessage); 41 | server.start(); 42 | loop.loop(); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /example/twisted/finger/finger7.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace blink; 7 | 8 | typedef std::map UserMap; 9 | UserMap users; 10 | 11 | string getUser(const string& user) 12 | { 13 | string result("No such user"); 14 | UserMap::iterator it = users.find(user); 15 | if (it != users.end()) 16 | { 17 | result = it->second; 18 | } 19 | return result; 20 | } 21 | 22 | void onMessage(const TcpConnectionPtr& connection, 23 | Buffer* buf, 24 | Timestamp receive_time) 25 | { 26 | const char* crlf = buf->findCRLF(); 27 | if (crlf) 28 | { 29 | string user(buf->peek(), crlf); 30 | connection->send(getUser(user) + "\r\n"); 31 | buf->resetUntil(crlf + 2); 32 | connection->shutdown(); 33 | } 34 | } 35 | 36 | int main(int argc, char const *argv[]) 37 | { 38 | users["john"] = "hey boy!"; 39 | EventLoop loop; 40 | TcpServer server(&loop, InetAddress(9600), "FingerServer"); 41 | server.setMessageCallback(onMessage); 42 | server.start(); 43 | loop.loop(); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /example/wordcount/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/wordcount) 2 | 3 | add_executable(wordcount_sender hash.cpp) 4 | target_link_libraries(wordcount_sender blink) 5 | 6 | add_executable(wordcount_receiver receiver.cpp) 7 | target_link_libraries(wordcount_receiver blink) 8 | -------------------------------------------------------------------------------- /example/wordcount/gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import random 4 | 5 | words = 1000000 6 | word_len = 5 7 | alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" 8 | 9 | output = open("random_words", "w"); 10 | for x in xrange(words): 11 | array = [random.choice(alphabet) for i in range(word_len)] 12 | word = ''.join(array) 13 | output.write(word) 14 | output.write('\n') 15 | -------------------------------------------------------------------------------- /example/wordcount/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_BLINK_HASH_H__ 2 | #define __EXAMPLE_BLINK_HASH_H__ 3 | 4 | #include 5 | 6 | namespace boost 7 | { 8 | 9 | std::size_t hash_value(const blink::string& x); 10 | 11 | } // namespace boost 12 | 13 | #include 14 | 15 | namespace boost 16 | { 17 | 18 | inline std::size_t hash_value(const blink::string& x) 19 | { 20 | return hash_range(x.begin(), x.end()); 21 | } 22 | 23 | } // namespace boost 24 | 25 | typedef boost::unordered_map WordCountMap; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /example/wordcount/slowsink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os, socket, sys, time 4 | 5 | host = '' 6 | port = 9600 7 | 8 | if len(sys.argv) > 1: 9 | mps = float(sys.argv[1]) 10 | else: 11 | mps = 1.0 12 | bps = mps * 1000000 13 | buffer_size = int(bps / 10) # sleep 100ms at full speed 14 | 15 | print "Mbytes/s = ", mps 16 | 17 | if len(sys.argv) > 3: 18 | host = sys.argv[2] 19 | port = int(sys.argv[3]) 20 | print "connecting to %s:%d" % (host, port) 21 | else: 22 | print "listening on port", port 23 | 24 | if host: 25 | client_socket = socket.create_connection((host, port)) 26 | print "connected to", client_socket.getpeername(); 27 | else: 28 | listen_address = ("", port) 29 | server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 30 | server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 31 | server_socket.bind(listen_address) 32 | server_socket.listen(5) 33 | 34 | (client_socket, client_address) = server_socket.accept() 35 | print "got connection from", client_address 36 | 37 | start = time.time() 38 | total_size = 0 39 | dot = bps 40 | 41 | while True: 42 | data = client_socket.recv(buffer_size) 43 | if data: 44 | size = len(data) 45 | total_size += size 46 | if total_size > dot: 47 | dot += bps 48 | sys.stdout.write('.') 49 | sys.stdout.flush() 50 | time.sleep(size / bps) 51 | else: 52 | print "\ndisconnect" 53 | client_socket.close() 54 | break 55 | 56 | end = time.time() 57 | elapsed = end - start 58 | print "elapsed seconds %.3f" % elapsed 59 | print "total bytes ", total_size 60 | print "throughout bytes/s %.2f" % (total_size / elapsed) 61 | print "throughout Mbytes/s %.3f" % (total_size / elapsed / 1000000) 62 | -------------------------------------------------------------------------------- /example/zeromq/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/zeromq) 2 | 3 | add_executable(zeromq_client remote_lat.cpp) 4 | target_link_libraries(zeromq_client blink) 5 | 6 | add_executable(zeromq_server local_lat.cpp) 7 | target_link_libraries(zeromq_server blink) 8 | -------------------------------------------------------------------------------- /example/zeromq/codec.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXAMPLE_ZEROMQ_CODEC_H__ 2 | #define __EXAMPLE_ZEROMQ_CODEC_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | class Codec : blink::Nocopyable 13 | { 14 | public: 15 | typedef boost::function StringMessageCallback; 18 | 19 | explicit Codec(const StringMessageCallback& cb) 20 | : message_callback_(cb) 21 | { 22 | } 23 | 24 | void onMessage(const blink::TcpConnectionPtr& connection, 25 | blink::Buffer* buf, 26 | blink::Timestamp receive_time) 27 | { 28 | while (buf->readableSize() >= kHeaderlen) 29 | { 30 | const int32_t len = buf->peekInt32(); 31 | if (len > 65536 || len < 0) 32 | { 33 | LOG_ERROR << "Invalid length " << len; 34 | connection->shutdown(); 35 | break; 36 | } 37 | else if (buf->readableSize() >= len + kHeaderlen) 38 | { 39 | buf->reset(kHeaderlen); 40 | blink::string message(buf->peek(), len); 41 | message_callback_(connection, message, receive_time); 42 | buf->reset(len); 43 | } 44 | else 45 | { 46 | break; 47 | } 48 | } 49 | } 50 | 51 | void send(blink::TcpConnection* connection, blink::string message) 52 | { 53 | blink::Buffer buf; 54 | buf.append(&*message.begin(), message.size()); 55 | buf.prependInt32(static_cast(message.size())); 56 | connection->send(&buf); 57 | } 58 | 59 | private: 60 | StringMessageCallback message_callback_; 61 | static const size_t kHeaderlen = sizeof(int32_t); 62 | }; 63 | 64 | const size_t Codec::kHeaderlen; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /example/zeromq/local_lat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | using namespace blink; 12 | 13 | bool g_tcpNoDelay = false; 14 | 15 | void onConnection(const TcpConnectionPtr& connection) 16 | { 17 | if (connection->connected()) 18 | { 19 | connection->setTcpNoDelay(g_tcpNoDelay); 20 | } 21 | } 22 | 23 | void onStringMessage(Codec* codec, 24 | const TcpConnectionPtr& connection, 25 | const string& message, 26 | Timestamp receive_time) 27 | { 28 | codec->send(boost::get_pointer(connection), message); 29 | } 30 | 31 | int main(int argc, char* argv[]) 32 | { 33 | if (argc < 2) 34 | { 35 | fprintf(stderr, "Usage: %s [tcp_no_delay] [threads_number]\n", argv[0]); 36 | return 1; 37 | } 38 | uint16_t port = static_cast(atoi(argv[1])); 39 | g_tcpNoDelay = argc > 2 ? atoi(argv[2]) : 0; 40 | int thread_count = argc > 3 ? atoi(argv[3]) : 0; 41 | LOG_INFO << "pid = " << getpid() << ", listem port = " < 1) 50 | { 51 | server.setThreadNumber(thread_count); 52 | } 53 | server.start(); 54 | loop.loop(); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(blink) 2 | -------------------------------------------------------------------------------- /src/blink/Acceptor.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_ACCEPTOR_H__ 2 | #define __BLINK_ACCEPTOR_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | class EventLoop; 14 | class InetAddress; 15 | 16 | class Acceptor : Nocopyable 17 | { 18 | public: 19 | typedef boost::function NewConnectionCallback; 20 | 21 | Acceptor(EventLoop* loop, const InetAddress& listen_addr, bool reuse_port); 22 | ~Acceptor(); 23 | 24 | void listen(); 25 | 26 | void setNewConnectionCallback(const NewConnectionCallback& cb) 27 | { 28 | new_connection_callback_ = cb; 29 | } 30 | 31 | bool listenning() const 32 | { 33 | return listenning_; 34 | } 35 | 36 | private: 37 | void handleRead(); 38 | 39 | EventLoop* loop_; 40 | Socket accept_socket_; 41 | Channel accept_channel_; 42 | NewConnectionCallback new_connection_callback_; 43 | bool listenning_; 44 | int idle_fd_; 45 | }; 46 | 47 | } // namespace blink 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/blink/AsyncLog.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_ASYNCLOG_H__ 2 | #define __BLINK_ASYNCLOG_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace blink 17 | { 18 | 19 | class TimeZone; 20 | 21 | class AsyncLog : Nocopyable 22 | { 23 | typedef detail::FixedBuffer Buffer; 24 | typedef boost::ptr_vector BufferVector; 25 | typedef boost::ptr_vector::auto_type BufferPtr; 26 | 27 | public: 28 | AsyncLog(const string& basename, size_t roll_size, int flush_interval = 3); 29 | 30 | ~AsyncLog() 31 | { 32 | if (running_) 33 | { 34 | stop(); 35 | } 36 | } 37 | 38 | void append(const char* logline, size_t len); 39 | 40 | void start() 41 | { 42 | running_ = true; 43 | thread_.start(); 44 | latch_.wait(); 45 | } 46 | 47 | void stop() 48 | { 49 | running_ = false; 50 | cond_.wakeup(); 51 | thread_.join(); 52 | } 53 | 54 | static void setTimeZone(const TimeZone& time_zone); 55 | 56 | private: 57 | AsyncLog(const AsyncLog&); 58 | AsyncLog& operator=(const AsyncLog&); 59 | 60 | void ThreadFunc(); 61 | void formatTime(char* time_buf, size_t len); 62 | 63 | string basename_; 64 | size_t roll_size_; 65 | const int flush_interval_; 66 | bool running_; 67 | Thread thread_; 68 | CountDownLatch latch_; 69 | MutexLock mutex_; 70 | Condition cond_; 71 | BufferPtr current_buffer_; 72 | BufferPtr next_buffer_; 73 | BufferVector buffers_; 74 | }; 75 | 76 | } // namespace blink 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/blink/Atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_ATOMIC_H__ 2 | #define __BLINK_ATOMIC_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | namespace detail 12 | { 13 | 14 | template 15 | class AtomicInteger : Nocopyable 16 | { 17 | public: 18 | AtomicInteger() 19 | : value_(0) 20 | { 21 | } 22 | 23 | T get() 24 | { 25 | return __sync_val_compare_and_swap(&value_, 0, 0); 26 | } 27 | 28 | T getAndAdd(T x) 29 | { 30 | return __sync_fetch_and_add(&value_, x); 31 | } 32 | 33 | T getAndSet(T x) 34 | { 35 | return __sync_lock_test_and_set(&value_, x); 36 | } 37 | 38 | T addAndGet(T x) 39 | { 40 | return getAndAdd(x) + x; 41 | } 42 | 43 | T incrementAndGet() 44 | { 45 | return addAndGet(1); 46 | } 47 | 48 | T decrementAndGet() 49 | { 50 | return addAndGet(-1); 51 | } 52 | 53 | void add(T x) 54 | { 55 | getAndAdd(x); 56 | } 57 | 58 | void increment() 59 | { 60 | incrementAndGet(); 61 | } 62 | 63 | void decrement() 64 | { 65 | decrementAndGet(); 66 | } 67 | 68 | private: 69 | volatile T value_; 70 | }; 71 | 72 | } // namespace detail 73 | 74 | typedef detail::AtomicInteger AtomicInt64; 75 | typedef detail::AtomicInteger AtomicInt32; 76 | typedef detail::AtomicInteger AtomicInt16; 77 | typedef detail::AtomicInteger AtomicInt8; 78 | 79 | typedef detail::AtomicInteger AtomicUint64; 80 | typedef detail::AtomicInteger AtomicUint32; 81 | typedef detail::AtomicInteger AtomicUint16; 82 | typedef detail::AtomicInteger AtomicUint8; 83 | 84 | } // namespace blink 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/blink/BlockingQueue.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_BLOCKINGQUEUE_H__ 2 | #define __BLINK_BLOCKINGQUEUE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace blink 12 | { 13 | 14 | template 15 | class BlockingQueue : Nocopyable 16 | { 17 | public: 18 | BlockingQueue() 19 | : mutex_(), not_empty_(mutex_), queue_() 20 | { 21 | } 22 | 23 | void put(const T& task) 24 | { 25 | MutexLockGuard guard(mutex_); 26 | queue_.push_back(task); 27 | not_empty_.wakeup(); 28 | } 29 | 30 | T take() 31 | { 32 | MutexLockGuard guard(mutex_); 33 | while(queue_.empty()) 34 | { 35 | not_empty_.wait(); 36 | } 37 | assert(!queue_.empty()); 38 | T task = queue_.front(); 39 | queue_.pop_front(); 40 | return task; 41 | } 42 | 43 | size_t size() const 44 | { 45 | MutexLockGuard guard(mutex_); 46 | return queue_.size(); 47 | } 48 | 49 | private: 50 | mutable MutexLock mutex_; 51 | Condition not_empty_; 52 | std::deque queue_; 53 | }; 54 | 55 | } // namespace blink 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/blink/BoundedBlockingQueue.h: -------------------------------------------------------------------------------- 1 | #ifndef __BOUNDEDBLOCKINGQUEUE_H__ 2 | #define __BOUNDEDBLOCKINGQUEUE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace blink 13 | { 14 | 15 | template 16 | class BounededBlockingQueue : Nocopyable 17 | { 18 | public: 19 | explicit BounededBlockingQueue(size_t maxsize) 20 | : mutex_(), not_empty_(mutex_), not_full_(mutex_), queue_(maxsize) 21 | { 22 | } 23 | 24 | void put(const T& task) 25 | { 26 | MutexLockGuard guard(mutex_); 27 | while (queue_.full()) 28 | { 29 | not_full_.wait(); 30 | } 31 | assert(!queue_.full()); 32 | queue_.push_back(task); 33 | not_empty_.wakeup(); 34 | } 35 | 36 | T take() 37 | { 38 | MutexLockGuard guard(mutex_); 39 | while (queue_.empty()) 40 | { 41 | not_empty_.wait(); 42 | } 43 | assert(!queue_.empty()); 44 | T task = queue_.front(); 45 | queue_.pop_front(); 46 | not_full_.wakeup(); 47 | return task; 48 | } 49 | 50 | bool empty() const 51 | { 52 | MutexLockGuard guard(mutex_); 53 | return queue_.empty(); 54 | } 55 | 56 | bool full() const 57 | { 58 | MutexLockGuard guard(mutex_); 59 | return queue_.full(); 60 | } 61 | 62 | size_t size() const 63 | { 64 | MutexLockGuard guard(mutex_); 65 | return queue_.size(); 66 | } 67 | 68 | size_t capacity() const 69 | { 70 | MutexLockGuard guard(mutex_); 71 | return queue_.capacity(); 72 | } 73 | 74 | private: 75 | mutable MutexLock mutex_; 76 | Condition not_empty_; 77 | Condition not_full_; 78 | boost::circular_buffer queue_; 79 | }; 80 | 81 | } // namespace blink 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/blink/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | const int Buffer::kPrependSize; 12 | const int Buffer::kBufferSize; 13 | const char Buffer::kCRLF[] = "\r\n"; 14 | 15 | // struct iovec 16 | // { 17 | // void* iov_base; /* Starting address */ 18 | // size_t iov_len; /* Length in bytes */ 19 | // }; 20 | 21 | ssize_t Buffer::readData(int fd, int* err) 22 | { 23 | char stack_buf[1024 * 64]; 24 | struct iovec iov[2]; 25 | const size_t writeable_size = writeableSize(); 26 | iov[0].iov_base = beginWrite(); 27 | iov[0].iov_len = writeable_size; 28 | iov[1].iov_base = stack_buf; 29 | iov[1].iov_len = sizeof(stack_buf); 30 | const int iov_count = writeable_size < sizeof(stack_buf) ? 2 : 1; 31 | const ssize_t n = sockets::readv(fd, iov, iov_count); 32 | if (n < 0) 33 | { 34 | *err = errno; 35 | } 36 | else if (implicit_cast(n) <= writeable_size) 37 | { 38 | write_index_ += n; 39 | } 40 | else 41 | { 42 | write_index_ = buffer_.size(); 43 | append(stack_buf, n - writeable_size); 44 | } 45 | return n; 46 | } 47 | 48 | } // namespace blink 49 | -------------------------------------------------------------------------------- /src/blink/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE(CheckFunctionExists) 2 | 3 | check_function_exists(accept4 HAVE_ACCEPT4) 4 | if(NOT HAVE_ACCEPT4) 5 | set_source_file_target(Socket.cpp PROPERTIES COMPILE_FLAGS "-DNO_ACCEPT4") 6 | endif() 7 | 8 | set(SRCS 9 | Acceptor.cpp 10 | AsyncLog.cpp 11 | Buffer.cpp 12 | Channel.cpp 13 | Condition.cpp 14 | Connector.cpp 15 | CountDownLatch.cpp 16 | CurrentThread.cpp 17 | Date.cpp 18 | EventLoop.cpp 19 | EventLoopThread.cpp 20 | EventLoopThreadPool.cpp 21 | Exception.cpp 22 | FileTool.cpp 23 | InetAddress.cpp 24 | Log.cpp 25 | LogFile.cpp 26 | LogStream.cpp 27 | MutexLock.cpp 28 | Poller.cpp 29 | ProcessBase.cpp 30 | ProcessInfo.cpp 31 | Rio.cpp 32 | Socket.cpp 33 | SocketBase.cpp 34 | TcpClient.cpp 35 | TcpConnection.cpp 36 | TcpServer.cpp 37 | Thread.cpp 38 | ThreadBase.cpp 39 | ThreadPool.cpp 40 | Timer.cpp 41 | TimerQueue.cpp 42 | Timestamp.cpp 43 | TimeZone.cpp 44 | ) 45 | 46 | add_library(blink ${SRCS}) 47 | target_link_libraries(blink pthread rt ${Boost_LIBRARIES}) 48 | 49 | add_subdirectory(http) 50 | add_subdirectory(inspect) 51 | 52 | if(PROTOBUF_FOUND AND ZLIB_FOUND) 53 | add_subdirectory(protobuf) 54 | add_subdirectory(protorpc) 55 | else() 56 | add_subdirectory(protobuf EXCLUDE_FROM_ALL) 57 | add_subdirectory(protorpc EXCLUDE_FROM_ALL) 58 | endif() 59 | 60 | install(TARGETS blink DESTINATION lib) 61 | 62 | file(GLOB HEADERS "*.h") 63 | install(FILES ${HEADERS} DESTINATION include) 64 | -------------------------------------------------------------------------------- /src/blink/Callbacks.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_CALLBACKS_H__ 2 | #define __BLINK_CALLBACKS_H__ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | // Adapted from google-protobuf stubs/common.h 13 | template 14 | inline boost::shared_ptr down_pointer_cast(const boost::shared_ptr& f) 15 | { 16 | if (false) 17 | { 18 | implicit_cast(0); 19 | } 20 | 21 | #ifndef NDEBUG 22 | assert(f == NULL || dynamic_cast(boost::get_pointer(f)) != NULL); 23 | #endif 24 | 25 | return boost::static_pointer_cast(f); 26 | } 27 | 28 | class Buffer; 29 | class TcpConnection; 30 | 31 | typedef boost::shared_ptr TcpConnectionPtr; 32 | typedef boost::function TimerCallback; 33 | typedef boost::function ConnectionCallback; 34 | typedef boost::function CloseCallback; 35 | typedef boost::function WriteCompleteCallback; 36 | typedef boost::function HighWaterMarkCallback; 37 | 38 | // The data has been read to (buf, len) 39 | typedef boost::function MessageCallback; 40 | 41 | // Implement in TcpConnection.cpp 42 | void defaultConnectionCallback(const TcpConnectionPtr& connection); 43 | void defaultMessageCallback(const TcpConnectionPtr& connection, Buffer* buffer, Timestamp receive_time); 44 | 45 | } // namespace blink 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/blink/Condition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | Condition::Condition(MutexLock& mutex) 12 | : mutex_(mutex) 13 | { 14 | MCHECK(threads::pthread_cond_init(&cond_, NULL)); 15 | } 16 | 17 | Condition::~Condition() 18 | { 19 | MCHECK(threads::pthread_cond_destroy(&cond_)); 20 | } 21 | 22 | void Condition::wait() 23 | { 24 | MutexLock::ConditionGuard guard(mutex_); 25 | MCHECK(threads::pthread_cond_wait(&cond_, mutex_.getMutex())); 26 | } 27 | 28 | bool Condition::timedWait(int seconds) 29 | { 30 | struct timespec absolute_time; 31 | clock_gettime(CLOCK_REALTIME, &absolute_time); 32 | absolute_time.tv_sec += seconds; 33 | MutexLock::ConditionGuard guard(mutex_); 34 | return ETIMEDOUT == threads::pthread_cond_timedwait(&cond_, mutex_.getMutex(), &absolute_time); 35 | } 36 | 37 | void Condition::wakeup() 38 | { 39 | MCHECK(threads::pthread_cond_signal(&cond_)); 40 | } 41 | 42 | void Condition::wakeupAll() 43 | { 44 | MCHECK(threads::pthread_cond_broadcast(&cond_)); 45 | } 46 | 47 | } // namespace blink 48 | -------------------------------------------------------------------------------- /src/blink/Condition.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_CONDITION_H__ 2 | #define __BLINK_CONDITION_H__ 3 | 4 | #include 5 | 6 | namespace blink 7 | { 8 | 9 | class Condition : Nocopyable 10 | { 11 | public: 12 | explicit Condition(MutexLock& mutex); 13 | ~Condition(); 14 | 15 | void wait(); 16 | bool timedWait(int seconds); // if timeout return true, false otherwise 17 | void wakeup(); 18 | void wakeupAll(); 19 | 20 | private: 21 | MutexLock& mutex_; 22 | pthread_cond_t cond_; 23 | }; 24 | 25 | } // namespace blink 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/blink/Copyable.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_COPYABLE__ 2 | #define __BLINK_COPYABLE__ 3 | 4 | namespace blink 5 | { 6 | 7 | // Empty base class emphasis the objects of derived class are copyable 8 | class Copyable 9 | { 10 | }; 11 | 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/blink/CountDownLatch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace blink 4 | { 5 | 6 | CountDownLatch::CountDownLatch(int count) 7 | : mutex_(), cond_(mutex_), count_(count) 8 | { 9 | } 10 | 11 | void CountDownLatch::wait() 12 | { 13 | MutexLockGuard guard(mutex_); 14 | while (count_ > 0) 15 | { 16 | cond_.wait(); 17 | } 18 | } 19 | 20 | void CountDownLatch::countDown() 21 | { 22 | MutexLockGuard guard(mutex_); 23 | --count_; 24 | if (count_ == 0) 25 | { 26 | cond_.wakeupAll(); 27 | } 28 | } 29 | 30 | int CountDownLatch::getCount() const 31 | { 32 | MutexLockGuard guard(mutex_); 33 | return count_; 34 | } 35 | 36 | } // namespace blink 37 | -------------------------------------------------------------------------------- /src/blink/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_COUNTDOWNLATCH_H__ 2 | #define __BLINK_COUNTDOWNLATCH_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | class CountDownLatch : Nocopyable 12 | { 13 | public: 14 | explicit CountDownLatch(int count); 15 | 16 | void wait(); 17 | void countDown(); 18 | int getCount() const; 19 | 20 | private: 21 | mutable MutexLock mutex_; 22 | Condition cond_; 23 | int count_; 24 | }; 25 | 26 | } // namespace blink 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/blink/CurrentThread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace blink 15 | { 16 | 17 | namespace current_thread 18 | { 19 | 20 | __thread int t_cache_tid = 0; 21 | __thread char t_tid_string[32]; 22 | __thread int t_tid_string_length = 6; 23 | __thread const char* t_thread_name = "unknown"; 24 | 25 | const bool is_same_type = boost::is_same::value; 26 | BOOST_STATIC_ASSERT(is_same_type); 27 | 28 | void cacheTid() 29 | { 30 | if (t_cache_tid == 0) 31 | { 32 | t_cache_tid = threads::gettid(); 33 | t_tid_string_length = snprintf(t_tid_string, sizeof(t_tid_string), "%5d ", t_cache_tid); 34 | } 35 | } 36 | 37 | bool isMainThread() 38 | { 39 | return tid() == processes::getpid(); 40 | } 41 | 42 | // struct timespec 43 | // { 44 | // time_t tv_sec; /* seconds */ 45 | // long tv_nsec; /* nanoseconds */ 46 | // }; 47 | 48 | void sleepMicroseconds(int64_t microseconds) 49 | { 50 | struct timespec spec; 51 | spec.tv_sec = static_cast(microseconds / (1000 * 1000)); 52 | spec.tv_nsec = static_cast(microseconds % (1000 * 1000) * 1000); 53 | ::nanosleep(&spec, NULL); 54 | } 55 | 56 | } // namespace current_thread 57 | 58 | } // namespace blink 59 | 60 | -------------------------------------------------------------------------------- /src/blink/CurrentThread.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_CURRENTTHREAD_H__ 2 | #define __BLINK_CURRENTTHREAD_H__ 3 | 4 | #include 5 | 6 | namespace blink 7 | { 8 | 9 | namespace current_thread 10 | { 11 | 12 | extern __thread int t_cache_tid; 13 | extern __thread char t_tid_string[32]; 14 | extern __thread int t_tid_string_length; 15 | extern __thread const char* t_thread_name; 16 | 17 | void cacheTid(); 18 | 19 | inline int tid() 20 | { 21 | if (__builtin_expect(t_cache_tid == 0, 0)) 22 | { 23 | cacheTid(); 24 | } 25 | return t_cache_tid; 26 | } 27 | 28 | inline const char* tidString() 29 | { 30 | return t_tid_string; 31 | } 32 | 33 | inline int tidStringLength() 34 | { 35 | return t_tid_string_length; 36 | } 37 | 38 | inline const char* threadName() 39 | { 40 | return t_thread_name; 41 | } 42 | 43 | bool isMainThread(); 44 | 45 | void sleepMicroseconds(int64_t microseconds); // implement by nanosleep. 46 | 47 | } // namespace current_thread 48 | 49 | } // namespace blink 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/blink/Date.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | namespace detail 12 | { 13 | 14 | BOOST_STATIC_ASSERT(sizeof(int) >= sizeof(int32_t)); 15 | 16 | int getJulianDayNumber(int year, int month, int day) 17 | { 18 | int a = (14 - month) / 12; 19 | int y = year + 4800 - a; 20 | int m = month + 12 * a - 3; 21 | return day + (153 * m + 2) / 5 + y * 365 + y / 4 - y / 100 + y / 400 - 32045; 22 | } 23 | 24 | Date::YearMonthDay getYearMonthDay(int julian_day_number) 25 | { 26 | int a = julian_day_number + 32044; 27 | int b = (4 * a + 3) / 146097; 28 | int c = a - ((b * 146097) / 4); 29 | int d = (4 * c + 3) / 1461; 30 | int e = c - ((1461 * d) / 4); 31 | int m = (5 * e + 2) / 153; 32 | Date::YearMonthDay result; 33 | result.year = b * 100 + d - 4800 + (m / 10); 34 | result.month = m + 3 - 12 * (m / 10); 35 | result.day = e - ((153 * m + 2) / 5) + 1; 36 | return result; 37 | } 38 | 39 | } // namespace detail 40 | 41 | const int Date::kDaysPerWeek; 42 | const int Date::kJuliandayOf1970_01_01 = detail::getJulianDayNumber(1970, 1, 1); 43 | 44 | Date::Date(const struct tm& tm_time) 45 | : julian_day_number_(detail::getJulianDayNumber(tm_time.tm_year + 1900, 46 | tm_time.tm_mon + 1, 47 | tm_time.tm_mday)) 48 | { 49 | } 50 | 51 | Date::Date(int years, int months, int days) 52 | : julian_day_number_(detail::getJulianDayNumber(years, months, days)) 53 | { 54 | } 55 | 56 | string Date::toString() const 57 | { 58 | char buf[32]; 59 | YearMonthDay ymd(yearMonthDay()); 60 | snprintf(buf, sizeof(buf), "%04d-%02d-%02d", ymd.year, ymd.month, ymd.day); 61 | return buf; 62 | } 63 | 64 | Date::YearMonthDay Date::yearMonthDay() const 65 | { 66 | return detail::getYearMonthDay(julian_day_number_); 67 | } 68 | 69 | } // namespace blink 70 | -------------------------------------------------------------------------------- /src/blink/Endian.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_ENDIAN_H__ 2 | #define __BLINK_ENDIAN_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | namespace sockets 12 | { 13 | 14 | // The htobe64 etc. are macros, 15 | // and inline asm code makes type blur, so disable warnings for a while. 16 | 17 | #if defined(__clang__) || __GNUC_MINOR__ >= 6 18 | #pragma GCC diagnostic push 19 | #endif 20 | #pragma GCC diagnostic ignored "-Wconversion" 21 | #pragma GCC diagnostic ignored "-Wold-style-cast" 22 | 23 | inline uint64_t hostToNetwork64(uint64_t host64) 24 | { 25 | return htobe64(host64); 26 | } 27 | 28 | inline uint32_t hostToNetwork32(uint32_t host32) 29 | { 30 | return htobe32(host32); 31 | } 32 | 33 | inline uint16_t hostToNetwork16(uint16_t host16) 34 | { 35 | return htobe16(host16); 36 | } 37 | 38 | inline uint64_t networkToHost64(uint64_t net64) 39 | { 40 | return be64toh(net64); 41 | } 42 | 43 | inline uint32_t networkToHost32(uint32_t net32) 44 | { 45 | return be32toh(net32); 46 | } 47 | 48 | inline uint16_t networkToHost16(uint16_t net16) 49 | { 50 | return be16toh(net16); 51 | } 52 | 53 | #if defined(__clang__) || __GNUC_MINOR__ >= 6 54 | #pragma GCC diagnostic pop 55 | #else 56 | #pragma GCC diagnostic warning "-Wconversion" 57 | #pragma GCC diagnostic warning "-Wold-style-cast" 58 | #endif 59 | 60 | } // namespace sockets 61 | 62 | } // namespace blink 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/blink/EventLoopThread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | EventLoopThread::EventLoopThread(const ThreadInitCallback& cb, const string& name) 12 | : loop_(NULL), 13 | exiting_(false), 14 | thread_(boost::bind(&EventLoopThread::ThreadFunc, this), name), 15 | mutex_(), 16 | cond_(mutex_), 17 | callback_(cb) 18 | { 19 | } 20 | 21 | EventLoopThread::~EventLoopThread() 22 | { 23 | exiting_ = true; 24 | if (loop_ != NULL) // not 100% race-free, eg. threadFunc could be running callback_. 25 | { 26 | loop_->quit(); 27 | thread_.join(); // still a tiny chance to call destructor object, if threadFunc exit just now. 28 | } // but when EventLoopthread destructs, usually programming is exiting anyway. 29 | } 30 | 31 | EventLoop* EventLoopThread::startLoop() 32 | { 33 | assert(!thread_.started()); 34 | thread_.start(); 35 | { 36 | MutexLockGuard guard(mutex_); 37 | while (loop_ == NULL) 38 | { 39 | cond_.wait(); 40 | } 41 | } 42 | return loop_; 43 | } 44 | 45 | void EventLoopThread::ThreadFunc() 46 | { 47 | EventLoop loop; 48 | if (callback_) 49 | { 50 | callback_(&loop); 51 | } 52 | { 53 | MutexLockGuard guard(mutex_); 54 | loop_ = &loop; 55 | cond_.wakeup(); 56 | } 57 | loop.loop(); 58 | //assert(exiting_); 59 | loop_ = NULL; 60 | } 61 | 62 | } // namespace blink 63 | -------------------------------------------------------------------------------- /src/blink/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_EVENTLOOPTHREAD_H__ 2 | #define __BLINK_EVENTLOOPTHREAD_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace blink 12 | { 13 | 14 | class EventLoop; 15 | 16 | class EventLoopThread : Nocopyable 17 | { 18 | public: 19 | typedef boost::function ThreadInitCallback; 20 | 21 | EventLoopThread(const ThreadInitCallback& cb = ThreadInitCallback(), 22 | const string& name = string()); 23 | ~EventLoopThread(); 24 | 25 | EventLoop* startLoop(); 26 | 27 | private: 28 | void ThreadFunc(); 29 | 30 | EventLoop* loop_; 31 | bool exiting_; 32 | Thread thread_; 33 | MutexLock mutex_; 34 | Condition cond_; 35 | ThreadInitCallback callback_; 36 | 37 | }; 38 | 39 | } // namespace blink 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/blink/EventLoopThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_EVENTLOOPTHREADPOOL_H__ 2 | #define __BLINK_EVENTLOOPTHREADPOOL_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace blink 13 | { 14 | 15 | class EventLoop; 16 | class EventLoopThread; 17 | 18 | class EventLoopThreadPool : Nocopyable 19 | { 20 | public: 21 | typedef boost::function ThreadInitCallback; 22 | 23 | EventLoopThreadPool(EventLoop* base_loop, const string& name_arg); 24 | ~EventLoopThreadPool(); 25 | 26 | void start(const ThreadInitCallback& cb = ThreadInitCallback()); 27 | 28 | // valid after caling start(). 29 | // round-robin. 30 | EventLoop* getNextLoop(); 31 | 32 | // valid after caling start(). 33 | // It will always return the same value, with the same hash_code. 34 | EventLoop* getLoopForHash(size_t hash_code); 35 | 36 | // Get all EventLoop* in loops_. 37 | // If loops_ is empty, return the base_loop_ anyway. 38 | std::vector getAllLoops(); 39 | 40 | const string& name() const 41 | { 42 | return name_; 43 | } 44 | 45 | bool started() const 46 | { 47 | return started_; 48 | } 49 | 50 | void setThreadNumber(int number_threads) 51 | { 52 | number_threads_ = number_threads; 53 | } 54 | 55 | private: 56 | EventLoop* base_loop_; 57 | string name_; 58 | bool started_; 59 | int number_threads_; 60 | int next_; 61 | boost::ptr_vector threads_; 62 | std::vector loops_; 63 | }; 64 | 65 | } // namespace blink 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/blink/Exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace blink 8 | { 9 | 10 | Exception::Exception(const string& message) 11 | : message_(message) 12 | { 13 | fillStackTrace(); 14 | } 15 | 16 | Exception::Exception(const char* message) 17 | : message_(message) 18 | { 19 | fillStackTrace(); 20 | } 21 | 22 | Exception::~Exception() throw() 23 | { 24 | } 25 | 26 | const char* Exception::what() const throw() 27 | { 28 | return message_.c_str(); 29 | } 30 | 31 | const char* Exception::stackTrace() const throw() 32 | { 33 | return stack_.c_str(); 34 | } 35 | 36 | void Exception::fillStackTrace() 37 | { 38 | const int len = 200; 39 | void* buf[len]; 40 | int n = ::backtrace(buf, len); 41 | char** string_array = ::backtrace_symbols(buf, n); 42 | if (string_array) 43 | { 44 | for (int i = 0; i < n; ++i) 45 | { 46 | stack_.append(string_array[i]); 47 | stack_.push_back('\n'); 48 | } 49 | free(string_array); 50 | } 51 | } 52 | 53 | } // namespace blink 54 | -------------------------------------------------------------------------------- /src/blink/Exception.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_EXCEPTION_H__ 2 | #define __BLINK_EXCEPTION_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | class Exception : public std::exception 12 | { 13 | public: 14 | explicit Exception(const string& message); 15 | explicit Exception(const char* message); 16 | virtual ~Exception() throw(); 17 | 18 | virtual const char* what() const throw(); 19 | const char* stackTrace() const throw(); 20 | 21 | private: 22 | void fillStackTrace(); 23 | 24 | string message_; 25 | string stack_; 26 | }; 27 | 28 | } // namespace blink 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/blink/FileTool.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_FILETOOL_H__ 2 | #define __BLINK_FILETOOL_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | class ReadSmallFile : Nocopyable 14 | { 15 | public: 16 | static const int kBufferSize = 1024 * 64; 17 | 18 | explicit ReadSmallFile(StringArg filename); 19 | ~ReadSmallFile(); 20 | 21 | int readToBuffer(int* size); 22 | 23 | template 24 | int readToString(int maxsize, 25 | String* destination, 26 | int64_t* filesize, 27 | int64_t* creat_time, 28 | int64_t* modify_time); 29 | 30 | const char* buffer() const 31 | { 32 | return buf_; 33 | } 34 | 35 | private: 36 | int fd_; 37 | int errno_; 38 | char buf_[kBufferSize]; 39 | }; 40 | 41 | template 42 | int readFile(StringArg filename, 43 | int maxsize, 44 | String* destination, 45 | int64_t* filesize = NULL, 46 | int64_t* creat_time = NULL, 47 | int64_t* modify_time = NULL) 48 | { 49 | ReadSmallFile file(filename); 50 | return file.readToString(maxsize, destination, filesize, creat_time, modify_time); 51 | } 52 | 53 | class AppendFile 54 | { 55 | public: 56 | const static int kBufferSize = 1024 * 64; 57 | 58 | explicit AppendFile(StringArg filename); 59 | ~AppendFile(); 60 | 61 | void appendFile(const char* destination, size_t len); 62 | void flush(); 63 | 64 | size_t writtenBytes() const 65 | { 66 | return bytes_; 67 | } 68 | 69 | private: 70 | FILE* fp_; 71 | size_t bytes_; 72 | char buf_[kBufferSize]; 73 | }; 74 | 75 | } // namespace blink 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/blink/InetAddress.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_INETADDRESS_H__ 2 | #define __BLINK_INETADDRESS_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace blink 12 | { 13 | 14 | // struct sockaddr 15 | // { 16 | //   unsigned short sa_family; /* address family, AF_xxx */ 17 | //   char sa_data[14]; /* 14 bytes of protocol address */ 18 | // }; 19 | // 20 | // struct sockaddr_in 21 | // { 22 | // short int sin_family; /* Address family */ 23 | // unsigned short int sin_port; /* Port number */ 24 | // struct in_addr sin_addr; /* Internet address */ 25 | // unsigned char sin_zero[8]; /* Same size as struct sockaddr */ 26 | // }; 27 | // 28 | // struct in_addr 29 | // { 30 | // unsigned int s_addr; /* 32 bits */ 31 | // }; 32 | 33 | class InetAddress : Copyable 34 | { 35 | public: 36 | explicit InetAddress(const struct sockaddr_in& addr) 37 | : addr_(addr) 38 | { 39 | } 40 | 41 | explicit InetAddress(uint16_t port = 0, bool loop_back_only = false); 42 | InetAddress(StringArg ip, uint16_t port); 43 | 44 | string toIp() const; 45 | string toIpPort() const; 46 | uint16_t toPort() const; 47 | 48 | const struct sockaddr_in getSockAddrInet() const 49 | { 50 | return addr_; 51 | } 52 | 53 | void setSockAddrInet(const struct sockaddr_in& addr) 54 | { 55 | addr_ = addr; 56 | } 57 | 58 | uint32_t ipNetEndian() const 59 | { 60 | return addr_.sin_addr.s_addr; 61 | } 62 | 63 | uint16_t portNetEndian() const 64 | { 65 | return addr_.sin_port; 66 | } 67 | 68 | static bool resolve(StringArg hostname, InetAddress* result); 69 | 70 | private: 71 | struct sockaddr_in addr_; 72 | }; 73 | 74 | } // namespace 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/blink/LogFile.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_LOGFILE_H__ 2 | #define __BLINK_LOGFILE_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | class MutexLock; 13 | class AppendFile; 14 | class TimeZone; 15 | 16 | class LogFile : Nocopyable 17 | { 18 | public: 19 | LogFile(const string& basename, 20 | size_t roll_size, 21 | bool thread_safe = true, 22 | int flush_interval = 3, 23 | int check_every_n = 1024); 24 | 25 | ~LogFile(); 26 | 27 | void append(const char* logline, size_t len); 28 | void flush(); 29 | bool rollFile(); 30 | 31 | static void setTimeZone(const TimeZone& time_zone); 32 | 33 | private: 34 | void appendUnlocked(const char* logline, size_t len); 35 | static string getLogFileName(const string& basename, time_t* now); 36 | 37 | const string basename_; 38 | const size_t roll_size_; 39 | const int flush_interval_; 40 | const int check_every_n_; 41 | int count_; 42 | boost::scoped_ptr mutex_; 43 | time_t start_of_period_; 44 | time_t last_roll_; 45 | time_t last_flush_; 46 | boost::scoped_ptr file_; 47 | 48 | const static int kRollPerSeconds = 60 * 60 * 24; 49 | }; 50 | 51 | } // namespace blink 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/blink/MutexLock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace blink 6 | { 7 | 8 | MutexLock::MutexLock() 9 | : holder_(0) 10 | { 11 | MCHECK(threads::pthread_mutex_init(&mutex_, NULL)); 12 | } 13 | 14 | MutexLock::~MutexLock() 15 | { 16 | MCHECK(threads::pthread_mutex_destroy(&mutex_)); 17 | } 18 | 19 | void MutexLock::lock() 20 | { 21 | MCHECK(threads::pthread_mutex_lock(&mutex_)); 22 | setHolder(); 23 | } 24 | 25 | void MutexLock::trylock() 26 | { 27 | if (threads::pthread_mutex_trylock(&mutex_) == 0) 28 | { 29 | setHolder(); 30 | } 31 | } 32 | 33 | void MutexLock::unlock() 34 | { 35 | resetHolder(); 36 | MCHECK(threads::pthread_mutex_unlock(&mutex_)); 37 | } 38 | 39 | bool MutexLock::isLockedByCurrentThread() const 40 | { 41 | return holder_ == current_thread::tid(); 42 | } 43 | 44 | void MutexLock::assertLockted() const 45 | { 46 | assert(isLockedByCurrentThread()); 47 | } 48 | 49 | void MutexLock::setHolder() 50 | { 51 | holder_ = current_thread::tid(); 52 | } 53 | 54 | MutexLockGuard::MutexLockGuard(MutexLock& mutex) 55 | : mutex_(mutex) 56 | { 57 | mutex_.lock(); 58 | } 59 | 60 | MutexLockGuard::~MutexLockGuard() 61 | { 62 | mutex_.unlock(); 63 | } 64 | 65 | } // namespace blink 66 | -------------------------------------------------------------------------------- /src/blink/Nocopyable.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_NOCOPYABLE_H__ 2 | #define __BLINK_NOCOPYABLE_H__ 3 | 4 | namespace blink 5 | { 6 | 7 | // Empty base class emphasis the objects of derived class are nocopyable 8 | class Nocopyable 9 | { 10 | protected: 11 | Nocopyable() 12 | { 13 | } 14 | 15 | ~Nocopyable() 16 | { 17 | } 18 | 19 | private: 20 | Nocopyable(const Nocopyable&); 21 | Nocopyable& operator=(const Nocopyable&); 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/blink/ProcessBase.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_PROCESSBASE_H__ 2 | #define __BLINK_PROCESSBASE_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace blink 8 | { 9 | 10 | namespace processes 11 | { 12 | 13 | pid_t getpid(); 14 | pid_t getppid(); 15 | uid_t getuid(); 16 | uid_t geteuid(); 17 | gid_t getgid(); 18 | gid_t getegid(); 19 | 20 | pid_t fork(); 21 | pid_t waitpid(pid_t pid, int* status, int options); 22 | pid_t wait(int* status); 23 | int execve(const char* filename, char* const argv[], char* const envp[]); 24 | 25 | pid_t getpgrp(); 26 | int setpgid(pid_t pid, pid_t pgid); 27 | 28 | int kill(pid_t pid, int sig); 29 | unsigned int alarm(unsigned int secs); 30 | 31 | //typedef void (*sighandler_t)(int); 32 | 33 | sighandler_t signal(int signum, sighandler_t handler); 34 | sighandler_t signalRestart(int signum, sighandler_t handler); 35 | 36 | // struct sigaction 37 | // { 38 | // void (*sa_handler)(int); /* func pointer */ 39 | // void (*sa_sigaction)(int, siginfo_t *, void *); /* func pointer */ 40 | // sigset_t sa_mask; 41 | // int sa_flags; 42 | // void (*sa_restorer)(void); 43 | // }; 44 | 45 | // typedef struct 46 | // { 47 | // unsigned long sig[_NSIG_WORDS]; 48 | // 49 | // } sigset_t; 50 | 51 | int sigaction(int signum, struct sigaction* act, struct sigaction* oldact); 52 | int sigprocmask(int how, const sigset_t* set, sigset_t* oldset); 53 | int sigemptyset(sigset_t* set); 54 | int sigfillset(sigset_t* set); 55 | int sigaddset(sigset_t* set, int signumi); 56 | int sigdelset(sigset_t* set, int signum); 57 | int sigismember(const sigset_t* set, int signum); 58 | 59 | } // namespace processes 60 | 61 | } // namespace blink 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/blink/ProcessInfo.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_PROCESSINFO_H__ 2 | #define __BLINK_PROCESSINFO_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | namespace process_info 14 | { 15 | 16 | pid_t pid(); 17 | string pidString(); 18 | string username(); 19 | Timestamp startTime(); 20 | int clockTicksPerSecond(); 21 | int pageSize(); 22 | bool isDebugBuild(); 23 | string hostName(); 24 | string procName(); 25 | StringPiece procName(const string& stat); 26 | 27 | // read from /proc/self/status 28 | string procStatus(); 29 | 30 | // read from /proc/self/status 31 | string procStat(); 32 | 33 | // read from /proc/self/task/tid/stat 34 | string threadStat(); 35 | 36 | // read from /proc/self/exe 37 | string exePath(); 38 | int openedFiles(); 39 | int maxOpenFiles(); 40 | 41 | struct CpuTime 42 | { 43 | double user_seconds; 44 | double system_seconds; 45 | 46 | CpuTime() 47 | : user_seconds(0), system_seconds(0) 48 | { 49 | } 50 | }; 51 | 52 | CpuTime cpuTime(); 53 | int threadsNumber(); 54 | std::vector threads(); 55 | 56 | } // namespace process_info 57 | 58 | } // namespace blink 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/blink/Rio.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_RIO_H__ 2 | #define __BLINK_RIO_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | class Rio : Nocopyable 14 | { 15 | public: 16 | enum Whence 17 | { 18 | kBegin = SEEK_SET, 19 | kCurrent = SEEK_CUR, 20 | kEnd = SEEK_END, 21 | }; 22 | 23 | Rio(int fd, size_t buffer_size = 8192) 24 | : fd_(fd), 25 | count_(0), 26 | buffer_size_(buffer_size), 27 | buf_(buffer_size), 28 | bufptr_(&*buf_.begin()) 29 | { 30 | } 31 | 32 | void setFd(int fd) 33 | { 34 | fd_ = fd; 35 | } 36 | 37 | void setBufferSize(size_t n); 38 | ssize_t readBytes(void* usrbuf, size_t n); 39 | ssize_t writeBytes(void* usrbuf, size_t n); 40 | ssize_t readLineBuffer(void* usrbuf, size_t maxlen); 41 | ssize_t readBytesBuffer(void* usrbuf, size_t n); 42 | off_t seekBytes(off_t offset, Whence whence); 43 | 44 | private: 45 | ssize_t rioRead(char* usrbuf, size_t n); 46 | 47 | int fd_; 48 | int count_; 49 | size_t buffer_size_; 50 | std::vector buf_; 51 | char* bufptr_; 52 | }; 53 | 54 | } //namespace blink 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/blink/Singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_SINGLETON_H__ 2 | #define __BLINK_SINGLETON_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace blink 13 | { 14 | 15 | namespace detail 16 | { 17 | 18 | template 19 | struct has_no_destroy // can not check inherited member function. 20 | { // http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions 21 | template 22 | static char check_no_destroy(typeof(&_Tp::no_destroy)); 23 | 24 | template 25 | static int check_no_destroy(...); 26 | 27 | static const bool value = (sizeof(check_no_destroy(0)) == 1); 28 | }; 29 | 30 | template 31 | const bool has_no_destroy::value; 32 | 33 | } // namespace detail 34 | 35 | template 36 | class Singleton : Nocopyable 37 | { 38 | public: 39 | static T& getInstance() 40 | { 41 | threads::pthread_once(&once_control_, init); 42 | assert(value_ != NULL); 43 | return *value_; 44 | } 45 | 46 | private: 47 | static void init() 48 | { 49 | if (!detail::has_no_destroy::value) 50 | { 51 | value_ = new T(); 52 | ::atexit(destroy); 53 | } 54 | } 55 | 56 | static void destroy() 57 | { 58 | typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; 59 | T_must_be_complete_type dummy; 60 | (void)dummy; 61 | delete value_; 62 | value_ = NULL; 63 | } 64 | 65 | Singleton(); 66 | ~Singleton(); 67 | 68 | static pthread_once_t once_control_; 69 | static T* value_; 70 | }; 71 | 72 | template 73 | pthread_once_t Singleton::once_control_ = PTHREAD_ONCE_INIT; 74 | 75 | template 76 | T* Singleton::value_ = NULL; 77 | 78 | } // namespace blink 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/blink/Socket.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_SOCKET_H__ 2 | #define __BLINK_SOCKET_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | struct tcp_info; 9 | struct sockaddr_in; 10 | 11 | namespace blink 12 | { 13 | 14 | class InetAddress; 15 | 16 | class Socket : Nocopyable 17 | { 18 | public: 19 | explicit Socket(int sockfd) 20 | : sockfd_(sockfd) 21 | { 22 | } 23 | 24 | ~Socket(); 25 | 26 | bool getTcpInfo(struct tcp_info* tcp) const; 27 | bool getTcpInfoString(char* buf, size_t len) const; 28 | void bindAddress(const InetAddress& local_addr); 29 | void listen(); 30 | 31 | // set to non-blocking and close-on-exec 32 | int accept(InetAddress* addr); 33 | 34 | void shutdownWrite(); 35 | 36 | // enable/disable TCP_NODELAY(Nagle's algorithm) 37 | void setTcpNoDelay(bool on); 38 | 39 | // enable/disable SO_REUSEADDR 40 | void setReuseAddr(bool on); 41 | 42 | // enable/disable SO_REUSEPORT 43 | void setReusePort(bool on); 44 | 45 | // enable/disable SO_KEEPALIVE 46 | void setKeepAlive(bool on); 47 | 48 | int fd() const 49 | { 50 | return sockfd_; 51 | } 52 | 53 | private: 54 | const int sockfd_; 55 | }; 56 | 57 | } // namespace blink 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/blink/Thread.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_THREAD_H__ 2 | #define __BLINK_THREAD_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace blink 14 | { 15 | 16 | class Thread : Nocopyable 17 | { 18 | public: 19 | typedef boost::function ThreadFunc; 20 | 21 | explicit Thread(const ThreadFunc& func, const string& thread_name = string()); 22 | ~Thread(); 23 | 24 | void start(); 25 | int join(); 26 | 27 | bool started() const 28 | { 29 | return started_; 30 | } 31 | 32 | pid_t tid() const 33 | { 34 | return *tid_; 35 | } 36 | 37 | const string name() const 38 | { 39 | return name_; 40 | } 41 | 42 | static int numCreated() 43 | { 44 | return num_created_.get(); 45 | } 46 | 47 | private: 48 | void setDefaultName(); 49 | 50 | bool started_; 51 | bool joined_; 52 | pthread_t pthread_id_; 53 | boost::shared_ptr tid_; 54 | ThreadFunc func_; 55 | string name_; 56 | 57 | static AtomicInt32 num_created_; 58 | }; 59 | 60 | } // namespace blink 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/blink/ThreadLocal.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_THREADLOCAL_H__ 2 | #define __BLINK_THREADLOCAL_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace blink 8 | { 9 | 10 | template 11 | class ThreadLocal : Nocopyable 12 | { 13 | public: 14 | ThreadLocal() 15 | { 16 | threads::pthread_key_create(&key_, &ThreadLocal::destructor); 17 | } 18 | 19 | ~ThreadLocal() 20 | { 21 | threads::pthread_key_delete(key_); 22 | } 23 | 24 | T& value() 25 | { 26 | T* val = static_cast(threads::pthread_getspecific(key_)); 27 | if (!val) 28 | { 29 | val = new T(); 30 | threads::pthread_setspecific(key_, val); 31 | } 32 | return *val; 33 | } 34 | 35 | private: 36 | static void destructor(void* arg) 37 | { 38 | T* data = static_cast(arg); 39 | typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; 40 | T_must_be_complete_type dummy; 41 | (void)dummy; 42 | delete data; 43 | } 44 | 45 | pthread_key_t key_; 46 | }; 47 | 48 | } // namespace blink 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/blink/ThreadLocalSingleton.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_THREADLOCALSINGLETON_H__ 2 | #define __BLINK_THREADLOCALSINGLETON_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | template 13 | class ThreadLocalSingleton : Nocopyable 14 | { 15 | public: 16 | static T& getInstance() 17 | { 18 | if (!t_value_) 19 | { 20 | t_value_ = new T(); 21 | deleter_.set(t_value_); 22 | } 23 | return *t_value_; 24 | } 25 | 26 | static T* pointer() 27 | { 28 | return t_value_; 29 | } 30 | 31 | private: 32 | ThreadLocalSingleton(); 33 | ~ThreadLocalSingleton(); 34 | 35 | static void destructor(void* arg) 36 | { 37 | assert(arg == t_value_); 38 | typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; 39 | T_must_be_complete_type dummy; 40 | (void)dummy; 41 | delete t_value_; 42 | t_value_ = NULL; 43 | } 44 | 45 | class Deleter 46 | { 47 | public: 48 | Deleter() 49 | { 50 | threads::pthread_key_create(&key_, &ThreadLocalSingleton::destructor); 51 | } 52 | 53 | ~Deleter() 54 | { 55 | threads::pthread_key_delete(key_); 56 | } 57 | 58 | void set(T* val) 59 | { 60 | assert(threads::pthread_getspecific(key_) == NULL); 61 | threads::pthread_setspecific(key_, val); 62 | } 63 | 64 | pthread_key_t key_; 65 | }; 66 | 67 | static __thread T* t_value_; 68 | static Deleter deleter_; 69 | }; 70 | 71 | template 72 | __thread T* ThreadLocalSingleton::t_value_ = NULL; 73 | 74 | template 75 | typename ThreadLocalSingleton::Deleter ThreadLocalSingleton::deleter_; 76 | 77 | } // namespace blink 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/blink/ThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_THREADPOOL_H__ 2 | #define __BLINK_THREADPOOL_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace blink 15 | { 16 | 17 | class Thread; 18 | 19 | class ThreadPool : Nocopyable 20 | { 21 | public: 22 | typedef boost::function Task; 23 | 24 | explicit ThreadPool(const string& name_arg = string("ThreadPool")); 25 | ~ThreadPool(); 26 | 27 | void start(int num_threads); 28 | void run(const Task& task); 29 | void stop(); 30 | size_t queueSize() const; 31 | 32 | const string& name() const 33 | { 34 | return name_; 35 | } 36 | 37 | void setMaxQueueSize(size_t maxsize) 38 | { 39 | max_queue_size_ = maxsize; 40 | } 41 | 42 | void setThreadInitCallback(const Task& func) 43 | { 44 | thread_init_callback_ = func; 45 | } 46 | 47 | private: 48 | bool isFull() const; 49 | void runInThread(); 50 | Task take(); 51 | 52 | mutable MutexLock mutex_; 53 | Condition not_empty_; 54 | Condition not_full_; 55 | string name_; 56 | Task thread_init_callback_; 57 | boost::ptr_vector threads_; 58 | std::deque queue_; 59 | size_t max_queue_size_; 60 | bool running_; 61 | }; 62 | 63 | } // namespace blink 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /src/blink/TimeZone.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_TIMEZONE_H__ 2 | #define __BLINK_TIMEZONE_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | class TimeZone : Copyable 14 | { 15 | public: 16 | TimeZone() 17 | { 18 | } 19 | 20 | explicit TimeZone(const char* zonefile); 21 | TimeZone(int east_of_utc, const char* timezone_name); 22 | 23 | struct tm toLocalTime(time_t seconds_since_epoch) const; 24 | time_t fromLocalTime(const struct tm& tm_time) const; 25 | 26 | static struct tm toUtcTime(time_t seconds_since_epoch, bool yday = false); 27 | static time_t fromUtcTime(const struct tm& tm_time); 28 | static time_t fromUtcTime(int year, int month, int day, int hour, int minute, int second); // year [1900-2500] 29 | 30 | bool valid() const 31 | { 32 | return static_cast(data_); 33 | } 34 | 35 | class Data; 36 | 37 | private: 38 | boost::shared_ptr data_; 39 | }; 40 | 41 | } // namesapce blink 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/blink/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace blink 4 | { 5 | 6 | AtomicInt64 Timer::number_created_; 7 | 8 | void Timer::run() 9 | { 10 | callback_(); 11 | } 12 | 13 | void Timer::restart(Timestamp now) 14 | { 15 | if (repeat_) 16 | { 17 | expiration_ = addTime(now, interval_); 18 | } 19 | else 20 | { 21 | expiration_ = Timestamp::invalid(); 22 | } 23 | } 24 | 25 | } // namespace blink 26 | -------------------------------------------------------------------------------- /src/blink/Timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_TIMER_H__ 2 | #define __BLINK_TIMER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | class Timer : Nocopyable 13 | { 14 | public: 15 | Timer(const TimerCallback callback, Timestamp when, double interval) 16 | : callback_(callback), 17 | expiration_(when), 18 | interval_(interval), 19 | repeat_(interval > 0.0), 20 | sequence_(number_created_.incrementAndGet()) 21 | { 22 | } 23 | 24 | void run(); 25 | void restart(Timestamp now); 26 | 27 | Timestamp expiration() const 28 | { 29 | return expiration_; 30 | } 31 | 32 | bool repeat() const 33 | { 34 | return repeat_; 35 | } 36 | 37 | int64_t sequence() const 38 | { 39 | return sequence_; 40 | } 41 | 42 | static int64_t numberCreated() 43 | { 44 | return number_created_.get(); 45 | } 46 | 47 | private: 48 | const TimerCallback callback_; 49 | Timestamp expiration_; 50 | const double interval_; 51 | const bool repeat_; 52 | const int64_t sequence_; 53 | 54 | static AtomicInt64 number_created_; 55 | }; 56 | 57 | } // namespace blink 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/blink/TimerId.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_TIMERID_H__ 2 | #define __BLINK_TIMERID_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace blink 9 | { 10 | 11 | class Timer; 12 | 13 | class TimerId : Copyable 14 | { 15 | public: 16 | TimerId() 17 | : timer_(NULL), sequence_(0) 18 | { 19 | } 20 | 21 | TimerId(Timer* timer, int64_t sequence) 22 | : timer_(timer), sequence_(sequence) 23 | { 24 | } 25 | 26 | friend class TimerQueue; 27 | 28 | private: 29 | Timer* timer_; 30 | int64_t sequence_; 31 | }; 32 | 33 | } // namespace blink 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/blink/TimerQueue.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_TIMERQUEUE_H__ 2 | #define __BLINK_TIMERQUEUE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace blink 14 | { 15 | 16 | class EventLoop; 17 | class Timer; 18 | class TimerId; 19 | 20 | class TimerQueue : Nocopyable 21 | { 22 | public: 23 | TimerQueue(EventLoop* loop); 24 | ~TimerQueue(); 25 | 26 | TimerId addTimer(const TimerCallback& callback, Timestamp when, double interval); 27 | void cancel(TimerId timer_id); 28 | 29 | private: 30 | // may use unique_ptr instead of raw pointer in C++11. 31 | typedef std::pair Entry; 32 | typedef std::set TimerList; 33 | typedef std::pair ActiveTimer; 34 | typedef std::set ActiveTimerSet; 35 | 36 | void addTimerInLoop(Timer* timer); 37 | void cancelInLoop(TimerId timer_id); 38 | 39 | // called when timerfd alarms. 40 | void handleRead(); 41 | 42 | // move out all expired timers. 43 | std::vector getExpired(Timestamp now); 44 | void reset(const std::vector& expired, Timestamp now); 45 | bool insert(Timer* timer); 46 | 47 | EventLoop* loop_; 48 | const int timerfd_; 49 | Channel timerfd_channel_; 50 | TimerList timers_; // sorted by expiration time. 51 | ActiveTimerSet active_timers_; // sorted by Timer's address. 52 | bool calling_expired_timers_; // atomic. 53 | ActiveTimerSet canceling_timers_; // for cancel(). 54 | }; 55 | 56 | } // namespace blink 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/blink/WeakCallback.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_WEAKCALLBACK_H__ 2 | #define __BLINK_WEAKCALLBACK_H__ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | template 14 | class WeakCallback : Copyable 15 | { 16 | public: 17 | WeakCallback(const boost::weak_ptr& arg, const boost::function& function) 18 | : arg_(arg), function_(function) 19 | { 20 | } 21 | 22 | void operator()() 23 | { 24 | boost::shared_ptr ptr(arg_.lock()); 25 | if (ptr) 26 | { 27 | function_(ptr.get()); 28 | } 29 | } 30 | 31 | private: 32 | boost::weak_ptr arg_; 33 | boost::function function_; 34 | }; 35 | 36 | template 37 | WeakCallback makeWeakCallback(const boost::shared_ptr& arg, void (T::*function)()) 38 | { 39 | return WeakCallback(arg, function); 40 | } 41 | 42 | template 43 | WeakCallback makeWeakCallback(const boost::shared_ptr& arg, void (T::*function)() const) 44 | { 45 | return WeakCallback(arg, function); 46 | } 47 | 48 | template 49 | WeakCallback makeWeakCallback(const boost::shared_ptr& arg, void (*function)(T*)) 50 | { 51 | return WeakCallback(arg, function); 52 | } 53 | 54 | } // namespace blink 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/blink/http/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(http_SRCS 2 | HttpContext.cpp 3 | HttpRequest.cpp 4 | HttpResponse.cpp 5 | HttpServer.cpp 6 | ) 7 | 8 | add_library(blink_http ${http_SRCS}) 9 | target_link_libraries(blink_http blink) 10 | 11 | install(TARGETS blink_http DESTINATION lib) 12 | 13 | file(GLOB HEADERS "*.h") 14 | install(FILES ${HEADERS} DESTINATION include/http) 15 | -------------------------------------------------------------------------------- /src/blink/http/HttpContext.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_HTTP_HTTPCONTEXT_H__ 2 | #define __BLINK_HTTP_HTTPCONTEXT_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace blink 8 | { 9 | 10 | class Buffer; 11 | 12 | class HttpContext : Copyable 13 | { 14 | public: 15 | enum HttpRequestParseState 16 | { 17 | kExpectRequestLine, 18 | kExpectHeaders, 19 | kExpectBody, 20 | kGotAll, 21 | }; 22 | 23 | HttpContext() 24 | : state_(kExpectRequestLine) 25 | { 26 | } 27 | 28 | bool parseRequest(Buffer* buf, Timestamp receive_time); 29 | 30 | bool expectRequestLine() const 31 | { 32 | return state_ == kExpectRequestLine; 33 | } 34 | 35 | bool expectHeaders() const 36 | { 37 | return state_ == kExpectHeaders; 38 | } 39 | 40 | bool expectBody() const 41 | { 42 | return state_ == kExpectBody; 43 | } 44 | 45 | bool gotAll() const 46 | { 47 | return state_ == kGotAll; 48 | } 49 | 50 | void receiveRequestLine() 51 | { 52 | state_ = kExpectHeaders; 53 | } 54 | 55 | void receiveHeaders() 56 | { 57 | state_ = kGotAll; // FIXME 58 | } 59 | 60 | void reset() 61 | { 62 | state_ = kExpectRequestLine; 63 | HttpRequest dummy; 64 | request_.swap(dummy); 65 | } 66 | 67 | const HttpRequest& request() const 68 | { 69 | return request_; 70 | } 71 | 72 | HttpRequest& request() 73 | { 74 | return request_; 75 | } 76 | 77 | private: 78 | bool processRequestLine(const char* begin, const char* end); 79 | 80 | HttpRequestParseState state_; 81 | HttpRequest request_; 82 | }; 83 | 84 | } // namespace blink 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/blink/http/HttpResponse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace blink 7 | { 8 | 9 | void HttpResponse::appendToBuffer(Buffer* output) const 10 | { 11 | char buf[32]; 12 | snprintf(buf, sizeof(buf), "HTTP/1.1 %d ", status_code_); 13 | output->append(buf); 14 | output->append(status_message_); 15 | output->append("\r\n"); 16 | 17 | if (close_connection_) 18 | { 19 | output->append("Connection: close\r\n"); 20 | } 21 | else 22 | { 23 | snprintf(buf, sizeof(buf), "Content-Length: %zd\r\n", body_.size()); 24 | output->append(buf); 25 | output->append("Connection: Keep-Alive\r\n"); 26 | } 27 | 28 | for (std::map::const_iterator it = headers_.begin(); 29 | it != headers_.end(); ++it) 30 | { 31 | output->append(it->first); 32 | output->append(": "); 33 | output->append(it->second); 34 | output->append("\r\n"); 35 | } 36 | 37 | output->append("\r\n"); 38 | output->append(body_); 39 | } 40 | 41 | } // namespace blink 42 | -------------------------------------------------------------------------------- /src/blink/http/HttpResponse.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_HTTP_HTTPRESPONSE_H__ 2 | #define __BLINK_HTTP_HTTPRESPONSE_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | class Buffer; 13 | 14 | class HttpResponse : Copyable 15 | { 16 | public: 17 | enum HttpStatusCode 18 | { 19 | kUnknown, 20 | kOk = 200, 21 | kMovePermanently = 301, 22 | kBadReqeust = 400, 23 | kNotFound = 404, 24 | }; 25 | 26 | explicit HttpResponse(bool close) 27 | :status_code_(kUnknown), close_connection_(close) 28 | { 29 | } 30 | 31 | void appendToBuffer(Buffer* output) const; 32 | 33 | void setStatusCode(HttpStatusCode code) 34 | { 35 | status_code_ = code; 36 | } 37 | 38 | void setStatusMessage(const string& message) 39 | { 40 | status_message_ = message; 41 | } 42 | 43 | void setCloseConnection(bool on) 44 | { 45 | close_connection_ = on; 46 | } 47 | 48 | bool closeConnection() const 49 | { 50 | return close_connection_; 51 | } 52 | 53 | void setContextType(const string& context_type) 54 | { 55 | addHeader("Content-Type", context_type); 56 | } 57 | 58 | void addHeader(const string& key, const string& value) 59 | { 60 | headers_[key] = value; 61 | } 62 | 63 | void setBody(const string& body) 64 | { 65 | body_ = body; 66 | } 67 | 68 | private: 69 | std::map headers_; 70 | HttpStatusCode status_code_; // FIXME: add http version 71 | string status_message_; 72 | bool close_connection_; 73 | string body_; 74 | }; 75 | 76 | } // namespace blink 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/blink/http/HttpServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_HTTP_HTTPSERVER_H__ 2 | #define __BLINK_HTTP_HTTPSERVER_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace blink 8 | { 9 | 10 | class HttpRequest; 11 | class HttpResponse; 12 | 13 | // A simple embeddable HTTP server. 14 | // It is not a fully HTTP 1.1 comliant server, but provides minimum features 15 | // that can communicate with HTTP client and web browser. 16 | class HttpServer : Nocopyable 17 | { 18 | public: 19 | typedef boost::function HttpCallback; 20 | 21 | HttpServer(EventLoop* loop, 22 | const InetAddress& listen_addr, 23 | const string& name, 24 | TcpServer::Option option = TcpServer::kNoReusePort); 25 | 26 | // force out-line destructor, for scoped_ptr member. 27 | ~HttpServer(); 28 | 29 | void start(); 30 | 31 | EventLoop* getLoop() const 32 | { 33 | return server_.getLoop(); 34 | } 35 | 36 | // Not thread safe, callback should be registered before calling start(). 37 | void setHttpCallback(const HttpCallback& cb) 38 | { 39 | http_callback_ = cb; 40 | } 41 | 42 | void setThreadNumber(int number_threads) 43 | { 44 | server_.setThreadNumber(number_threads); 45 | } 46 | 47 | private: 48 | void onConnection(const TcpConnectionPtr& connection); 49 | void onMessage(const TcpConnectionPtr& connection, 50 | Buffer* buf, 51 | Timestamp receive_time); 52 | void onRequest(const TcpConnectionPtr& connection, const HttpRequest& request); 53 | 54 | TcpServer server_; 55 | HttpCallback http_callback_; 56 | }; 57 | 58 | } // namespace blink 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/blink/inspect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(inspect_SRCS 2 | Inspector.cpp 3 | PerformanceInspector.cpp 4 | ProcessInspector.cpp 5 | SystemInspector.cpp 6 | ) 7 | 8 | add_library(blink_inspect ${inspect_SRCS}) 9 | target_link_libraries(blink_inspect blink_http) 10 | 11 | if(TCMALLOC_LIBRARY AND TCMALLOC_INCLUDE_DIR) 12 | set_target_properties(blink_inspect PROPERTIES COMPILE_FLAGS "-DHAVE_TCMALLOC") 13 | target_link_libraries(blink_inspect tcmalloc_and_profiler) 14 | endif() 15 | 16 | install(TARGETS blink_inspect DESTINATION lib) 17 | 18 | file(GLOB HEADERS "*.h") 19 | install(FILES ${HEADERS} DESTINATION include/inspect) 20 | -------------------------------------------------------------------------------- /src/blink/inspect/Inspector.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_INSPECT_INSPECTOR_H__ 2 | #define __BLINK_INSPECT_INSPECTOR_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace blink 15 | { 16 | 17 | class ProcessInspector; 18 | class PerformanceInspector; 19 | class SystemInspector; 20 | 21 | // An internal inspector of the running process, usually a singleton. 22 | // Better to run a separated thread, as some method may block for seconds. 23 | class Inspector : Nocopyable 24 | { 25 | public: 26 | typedef std::vector ArgList; 27 | typedef boost::function Callback; 28 | 29 | Inspector(EventLoop* loop, const InetAddress& http_addr, const string& name); 30 | ~Inspector(); 31 | 32 | void add(const string& module, 33 | const string& command, 34 | const Callback& cb, 35 | const string& help); 36 | void remove(const string& module, const string& command); 37 | 38 | private: 39 | void start(); 40 | void onRequest(const HttpRequest& request, HttpResponse* response); 41 | 42 | typedef std::map CommandList; 43 | typedef std::map HelpList; 44 | 45 | HttpServer server_; 46 | boost::scoped_ptr process_inspector_; 47 | boost::scoped_ptr performance_inspector_; 48 | boost::scoped_ptr system_inspector_; 49 | MutexLock mutex_; 50 | std::map modules_; 51 | std::map helps_; 52 | }; 53 | 54 | } // namespace blink 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/blink/inspect/PerformanceInspector.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_INSPECT_PERFORMANCEINSPECTOR_H__ 2 | #define __BLINK_INSPECT_PERFORMANCEINSPECTOR_H__ 3 | 4 | #include 5 | 6 | namespace blink 7 | { 8 | 9 | class PerformanceInspector : Nocopyable 10 | { 11 | public: 12 | void registerCommands(Inspector* inspector); 13 | 14 | static string heap(HttpRequest::Method, const Inspector::ArgList&); 15 | static string growth(HttpRequest::Method, const Inspector::ArgList&); 16 | static string profile(HttpRequest::Method, const Inspector::ArgList&); 17 | static string cmdline(HttpRequest::Method, const Inspector::ArgList&); 18 | static string memstats(HttpRequest::Method, const Inspector::ArgList&); 19 | static string memhistogram(HttpRequest::Method, const Inspector::ArgList&); 20 | static string releaseFreeMemory(HttpRequest::Method, const Inspector::ArgList&); 21 | static string symbol(HttpRequest::Method, const Inspector::ArgList&); 22 | }; 23 | 24 | } // namespace blink 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/blink/inspect/ProcessInspector.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_INSPECT_PROCESSINSPECTOR_H__ 2 | #define __BLINK_INSPECT_PROCESSINSPECTOR_H__ 3 | 4 | #include 5 | 6 | namespace blink 7 | { 8 | 9 | class ProcessInspector : Nocopyable 10 | { 11 | public: 12 | void registerCommands(Inspector* inspector); 13 | 14 | static string overview(HttpRequest::Method, const Inspector::ArgList&); 15 | static string pid(HttpRequest::Method, const Inspector::ArgList&); 16 | static string proStatus(HttpRequest::Method, const Inspector::ArgList&); 17 | static string openedFiles(HttpRequest::Method, const Inspector::ArgList&); 18 | static string threads(HttpRequest::Method, const Inspector::ArgList&); 19 | 20 | static string username_; 21 | }; 22 | 23 | string uptime(Timestamp now, Timestamp start, bool show_microseconds); 24 | int stringPrintf(string* out, const char* fmt, ...) __attribute__((format(printf, 2, 3))); 25 | long getLong(const string& proc_status, const char* key); 26 | 27 | } // namespace blink 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/blink/inspect/SystemInspector.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_INSPECT_SYSTEMINSPECTOR_H__ 2 | #define __BLINK_INSPECT_SYSTEMINSPECTOR_H__ 3 | 4 | #include 5 | 6 | namespace blink 7 | { 8 | 9 | class SystemInspector : Nocopyable 10 | { 11 | public: 12 | void registerCommands(Inspector* inspector); 13 | 14 | static string overview(HttpRequest::Method, const Inspector::ArgList&); 15 | static string loadavg(HttpRequest::Method, const Inspector::ArgList&); 16 | static string version(HttpRequest::Method, const Inspector::ArgList&); 17 | static string cpuinfo(HttpRequest::Method, const Inspector::ArgList&); 18 | static string meminfo(HttpRequest::Method, const Inspector::ArgList&); 19 | static string stat(HttpRequest::Method, const Inspector::ArgList); 20 | }; 21 | 22 | } // namespace blink 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/blink/protobuf/BufferStream.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_PROTOBUF_BUFFERSTREAN_H__ 2 | #define __BLINK_PROTOBUF_BUFFERSTREAN_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | // FIXME: 13 | // class BufferInputStream 14 | // { 15 | // }; 16 | 17 | class BufferOutputStream : public google::protobuf::io::ZeroCopyOutputStream 18 | { 19 | public: 20 | BufferOutputStream(Buffer* buf) 21 | : buffer_(CHECK_NOTNULL(buf)) 22 | original_size_(buf->readableSize()) 23 | { 24 | } 25 | 26 | virtual ~BufferOutputStream() // override 27 | { 28 | } 29 | 30 | virtual bool Next(void** data, int* size) // override 31 | { 32 | buffer_->ensureWriteableSize(4096); 33 | *data = buffer_->beginWrite(); 34 | *size = static_cast(buffer_->writeableSize()); 35 | buffer_->haveWritten(*size); 36 | return true; 37 | } 38 | 39 | virtual void BackUp(int count) //override 40 | { 41 | buffer_->unwrite(count); 42 | } 43 | 44 | virtual int64_t ByteCount() const // override 45 | { 46 | return buffer_->readableSize() - original_size_; 47 | } 48 | 49 | private: 50 | Buffer* buffer_; 51 | size_t original_size_; 52 | }; 53 | 54 | } // namespace blink 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/blink/protobuf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(blink_protobuf ProtobufCodecLite.cpp) 2 | target_link_libraries(blink_protobuf blink protobuf z) 3 | 4 | install(TARGETS blink_protobuf DESTINATION lib) 5 | 6 | file(GLOB HEADERS "*.h") 7 | install(FILES ${HEADERS} DESTINATION include/protobuf) 8 | -------------------------------------------------------------------------------- /src/blink/protorpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command(OUTPUT rpc.pb.h rpc.pb.cc 2 | COMMAND protoc 3 | ARGS -I=${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/rpc.proto 4 | DEPENDS rpc.proto 5 | VERBATIM ) 6 | 7 | include_directories(${PROJECT_BINARY_DIR}/src) 8 | set_source_files_properties(rpc.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion") 9 | 10 | add_library(blink_protorpc_wire rpc.pb.cc RpcCodec.cpp) 11 | set_target_properties(blink_protorpc_wire PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 12 | 13 | add_library(blink_protorpc RpcServer.cpp RpcChannel.cpp) 14 | set_target_properties(blink_protorpc PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 15 | target_link_libraries(blink_protorpc blink_protorpc_wire blink_protobuf blink protobuf z) 16 | 17 | if(TCMALLOC_LIBRARY AND TCMALLOC_INCLUDE_DIR) 18 | target_link_libraries(blink_protorpc tcmalloc_and_profiler) 19 | endif() 20 | 21 | install(TARGETS blink_protorpc_wire DESTINATION lib) 22 | install(TARGETS blink_protorpc DESTINATION lib) 23 | 24 | file(GLOB HEADERS "*.h") 25 | install(FILES ${HEADERS} DESTINATION include/protorpc) 26 | 27 | -------------------------------------------------------------------------------- /src/blink/protorpc/RpcCodec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace blink 10 | { 11 | 12 | namespace 13 | { 14 | 15 | int protobufVersionCheck() 16 | { 17 | GOOGLE_PROTOBUF_VERIFY_VERSION; 18 | return 0; 19 | } 20 | 21 | int dummy = protobufVersionCheck(); 22 | 23 | } // anonymous namespace 24 | 25 | const char rpctag[] = "RPC0"; 26 | 27 | } // namespace blink 28 | -------------------------------------------------------------------------------- /src/blink/protorpc/RpcCodec.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_PROTORPC_RPCCODEC_H__ 2 | #define __BLINK_PROTORPC_RPCCODEC_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace blink 13 | { 14 | 15 | class Buffer; 16 | class RpcMessage; 17 | typedef boost::shared_ptr RpcMessagePtr; 18 | 19 | extern const char rpctag[]; // = "RPC0"; 20 | 21 | // wire format 22 | // 23 | // Field Length Content 24 | // 25 | // size 4-byte N+8 26 | // "RPC0" 4-byte 27 | // payload N-byte 28 | // checksum 4-byte adler32 of "RPC0"+payload 29 | 30 | typedef ProtobufCodecLiteT RpcCodec; 31 | 32 | } // namespace blink 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/blink/protorpc/RpcServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace blink 11 | { 12 | 13 | RpcServer::RpcServer(EventLoop* loop, 14 | const InetAddress& listen_addr, 15 | const string& name_arg) 16 | : server_(loop, listen_addr, name_arg) 17 | { 18 | server_.setConnectionCallback(boost::bind(&RpcServer::onConnection, this, _1)); 19 | //server_.setMessageCallback(boost::bind(&RpcServer::onMessage, this, _1, _2, _3)); 20 | } 21 | 22 | void RpcServer::registerService(::google::protobuf::Service* service) 23 | { 24 | const google::protobuf::ServiceDescriptor* desc = service->GetDescriptor(); 25 | services_[desc->name()] = service; 26 | } 27 | 28 | void RpcServer::start() 29 | { 30 | server_.start(); 31 | } 32 | 33 | void RpcServer::onConnection(const TcpConnectionPtr& connection) 34 | { 35 | LOG_INFO << "RpcServer - " << connection->peerAddress().toIpPort() << " -> " 36 | << connection->localAddress().toIpPort() << " is " 37 | << (connection->connected() ? "UP" : "DOWN"); 38 | if (connection->connected()) 39 | { 40 | RpcChannelPtr channel(new RpcChannel(connection)); 41 | channel->setServices(&services_); 42 | connection->setMessageCallback(boost::bind(&RpcChannel::onMessage, channel.get(), _1, _2, _3)); 43 | connection->setContext(channel); 44 | } 45 | else 46 | { 47 | connection->setContext(RpcChannelPtr()); 48 | // FIXME: 49 | } 50 | } 51 | 52 | // void RpcServer::onMessage(const TcpConnectionPtr& connection, 53 | // Buffer* buf, 54 | // Timestamp receive_time) 55 | // { 56 | // RpcChannelPtr& channel = boost::any_cast(connection->getContext()); 57 | // channel->onMessage(connection, buf, receive_time); 58 | // } 59 | 60 | } // namespace blink 61 | -------------------------------------------------------------------------------- /src/blink/protorpc/RpcServer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLINK_PROTORPC_RPCSERVER_H__ 2 | #define __BLINK_PROTORPC_RPCSERVER_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace google 8 | { 9 | 10 | namespace protobuf 11 | { 12 | 13 | class Service; 14 | 15 | } // namespace protobuf 16 | 17 | } // namespace google 18 | 19 | namespace blink 20 | { 21 | 22 | class RpcServer : Nocopyable 23 | { 24 | public: 25 | RpcServer(EventLoop* loop, 26 | const InetAddress& listen_addr, 27 | const string& name_arg); 28 | 29 | void setThreadNumer(int n) 30 | { 31 | server_.setThreadNumber(n); 32 | } 33 | 34 | const string& name() const 35 | { 36 | return server_.name(); 37 | } 38 | 39 | void registerService(::google::protobuf::Service* service); 40 | void start(); 41 | 42 | private: 43 | void onConnection(const TcpConnectionPtr& connection); 44 | 45 | // void onMessage(const TcpConnectionPtr& connection, 46 | // Buffer* buf, 47 | // Timestamp receive_time); 48 | 49 | TcpServer server_; 50 | std::map services_; 51 | }; 52 | 53 | } // namespace blink 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/blink/protorpc/rpc.proto: -------------------------------------------------------------------------------- 1 | package blink; 2 | 3 | //option java_package = "com.blink.protorpc"; 4 | //option java_outer_class = "RpcProto"; 5 | 6 | enum MessageType 7 | { 8 | REQUEST = 1; 9 | RESPONSE = 2; 10 | ERROR = 3; // not used 11 | } 12 | 13 | enum ErrorCode 14 | { 15 | NO_ERROR = 0; 16 | WRONG_PROTO = 1; 17 | NO_SERVICE = 2; 18 | NO_METHOD = 3; 19 | INVALID_REQUEST = 4; 20 | INVALID_RESPONSE = 5; 21 | TIMEOUT = 6; 22 | } 23 | 24 | message RpcMessage 25 | { 26 | required MessageType type = 1; 27 | required fixed64 id = 2; 28 | 29 | optional string service = 3; 30 | optional string method = 4; 31 | optional bytes request = 5; 32 | optional bytes response = 6; 33 | optional ErrorCode error = 7; 34 | } 35 | -------------------------------------------------------------------------------- /src/blink/protorpc/rpcservice.proto: -------------------------------------------------------------------------------- 1 | package blink; 2 | 3 | option cc_generic_services = true; 4 | option java_generic_services = true; 5 | option py_generic_services = true; 6 | 7 | //option java_package = "com.blink.protorpc"; 8 | //option java_outer_classname = "RpcServiceProto"; 9 | 10 | //import "google/protobuf/descriptor.proto"; 11 | import "rpc.proto"; 12 | 13 | message ListRpcRequest 14 | { 15 | optional string service_name = 1; 16 | optional bool list_method = 2; 17 | } 18 | 19 | message ListRpcResponse 20 | { 21 | required ErrorCode error = 1; 22 | repeated string service_name = 2; 23 | repeated string method_name = 3; 24 | } 25 | 26 | message GetServiceRequest 27 | { 28 | required string service_name = 1; 29 | } 30 | 31 | message GetServiceResponse 32 | { 33 | required ErrorCode error = 1; 34 | repeated string proto_file = 2; 35 | repeated string proto_file_name = 3; 36 | } 37 | 38 | // the meta service 39 | service RpcService 40 | { 41 | rpc listRpc (ListRpcRequest) returns (ListRpcResponse); 42 | rpc getService (GetServiceRequest) returns (GetServiceResponse); 43 | } 44 | -------------------------------------------------------------------------------- /test/AcceptorTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | using namespace blink; 12 | 13 | void print(int connectfd, const InetAddress& addr, EventLoop* loop) 14 | { 15 | printf("connectfd = %d, addr = %s\n", connectfd, addr.toIp().c_str()); 16 | ::close(connectfd); 17 | loop->quit(); 18 | } 19 | 20 | int main(int argc, char const *argv[]) 21 | { 22 | EventLoop loop; 23 | InetAddress local_addr(9600); 24 | printf("local_addr = %s, port = %hu\n", local_addr.toIpPort().c_str(), local_addr.toPort()); 25 | Acceptor acceptor(&loop, local_addr, false); 26 | acceptor.setNewConnectionCallback(boost::bind(print, _1, _2, &loop)); 27 | acceptor.listen(); 28 | loop.loop(); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /test/AtomicTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using namespace blink; 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | AtomicInt64 atomic_int64; 11 | assert(atomic_int64.get() == 0); 12 | assert(atomic_int64.getAndAdd(10) == 0); 13 | assert(atomic_int64.getAndSet(20) == 10); 14 | assert(atomic_int64.addAndGet(20) == 40); 15 | assert(atomic_int64.incrementAndGet() == 41); 16 | assert(atomic_int64.decrementAndGet() == 40); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /test/CountDownLatchTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | using namespace blink; 12 | 13 | void print(const string& msg, int n, const boost::shared_ptr& latch) 14 | { 15 | char buf[64]; 16 | snprintf(buf, sizeof(buf), "I'm the task %d: %s", n, msg.c_str()); 17 | LOG_INFO << buf; 18 | latch->countDown(); 19 | } 20 | 21 | int main(int argc, char const *argv[]) 22 | { 23 | ThreadPool pool(string("CountDownLatchTest.ThreadPool")); 24 | pool.setMaxQueueSize(5); 25 | pool.start(5); 26 | boost::shared_ptr latch(new CountDownLatch(90)); 27 | for (int i = 1; i <= 100; ++i) 28 | { 29 | char buf[32]; 30 | snprintf(buf, sizeof(buf), "(task %d)", i); 31 | pool.run(boost::bind(print, string(buf), i, latch)); 32 | } 33 | latch->wait(); 34 | LOG_INFO << "latch::getCount: " << latch->getCount(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /test/DateTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace blink; 9 | 10 | int main(int argc, char const *argv[]) 11 | { 12 | struct timeval tm; 13 | gettimeofday(&tm, NULL); 14 | 15 | time_t second = tm.tv_sec; 16 | struct tm tm_time; 17 | gmtime_r(&second, &tm_time); 18 | 19 | Date date2(tm_time); 20 | string s = date2.toString(); 21 | printf("%s\n", s.c_str()); 22 | 23 | Date date3(2014, 12, 21); 24 | s = date3.toString(); 25 | printf("%s\n", s.c_str()); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/EventLoopTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | using namespace blink; 13 | 14 | boost::scoped_ptr g_loop; 15 | 16 | void cb() 17 | { 18 | printf("cb() pid = %d tid = %d\n", getpid(), current_thread::tid()); 19 | EventLoop another_loop; 20 | } 21 | 22 | void func() 23 | { 24 | printf("func() pid = %d tid = %d\n", getpid(), current_thread::tid()); 25 | assert(EventLoop::getEventLoopOfCurrentThread() == NULL); 26 | EventLoop loop; 27 | assert(EventLoop::getEventLoopOfCurrentThread() == &loop); 28 | loop.runAfter(1.0, cb); 29 | loop.loop(); 30 | } 31 | 32 | int main(int argc, char const *argv[]) 33 | { 34 | printf("main() pid = %d tid = %d\n", getpid(), current_thread::tid()); 35 | assert(EventLoop::getEventLoopOfCurrentThread() == NULL); 36 | EventLoop loop; 37 | assert(EventLoop::getEventLoopOfCurrentThread() == &loop); 38 | Thread thread(func); 39 | thread.start(); 40 | loop.loop(); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /test/EventLoopThreadTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | using namespace blink; 14 | 15 | void print(EventLoop* p = NULL) 16 | { 17 | printf("print: pid = %d, tid = %d. loop = %p\n", getpid(), current_thread::tid(), p); 18 | } 19 | 20 | void quit(EventLoop* p) 21 | { 22 | print(p); 23 | p->quit(); 24 | } 25 | 26 | int main(int argc, char const *argv[]) 27 | { 28 | print(); 29 | { 30 | EventLoopThread loop_thread1; 31 | } 32 | { // destructor call quit() 33 | EventLoopThread loop_thread2; 34 | EventLoop* loop = loop_thread2.startLoop(); 35 | loop->runInLoop(boost::bind(print, loop)); 36 | current_thread::sleepMicroseconds(500 * 1000); 37 | } 38 | { // call quit() before destruct. 39 | EventLoopThread loop_thread3; 40 | EventLoop* loop = loop_thread3.startLoop(); 41 | loop->runInLoop(boost::bind(quit, loop)); 42 | current_thread::sleepMicroseconds(500 * 1000); 43 | } 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test/ExceptionTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | void test() 6 | { 7 | throw blink::Exception("test for Exception"); 8 | } 9 | 10 | int main(int argc, char const *argv[]) 11 | { 12 | try 13 | { 14 | test(); 15 | } 16 | catch (const blink::Exception& e) 17 | { 18 | printf("reason: %s\n", e.what()); 19 | printf("stacktrace:\n%s\n", e.stackTrace()); 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /test/FileToolTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define __STDC_FORMAT_MACROS 8 | #include 9 | 10 | using namespace blink; 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | const char* s = "hey, make it happy!"; 15 | string str; 16 | ReadSmallFile read_file(string("1.txt")); 17 | int n; 18 | read_file.readToBuffer(&n); 19 | int64_t filesize; 20 | int64_t creat_time; 21 | int64_t modify_time; 22 | read_file.readToString(1024*64, &str, &filesize, &creat_time, &modify_time); 23 | printf("str = %s\n", str.c_str()); 24 | printf("buf = %s\n", read_file.buffer()); 25 | printf("filesize = %" PRIu64 "\n", filesize); 26 | printf("creat_time = %" PRIu64 "\n", creat_time); 27 | printf("modify_time = %" PRIu64 "\n", modify_time); 28 | printf("readbytes = %d\n", n); 29 | 30 | AppendFile append_file(string("1.txt")); 31 | append_file.appendFile(s, strlen(s)); 32 | append_file.flush(); 33 | printf("writebytes = %zd\n", append_file.writtenBytes()); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/GzipFileTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace blink; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | const char* filename = "GzipFileTest.gz"; 11 | unlink(filename); 12 | const char data[] = "123456789012345678901234567890123456789012345678901234567890"; 13 | 14 | { 15 | printf("testing openForAppend\n"); 16 | GzipFile writer = GzipFile::openForAppend(filename); 17 | if (writer.valid()) 18 | { 19 | LOG_INFO << "tell " << writer.tell(); 20 | LOG_INFO << "wrote " << writer.write(data); 21 | LOG_INFO << "tell " << writer.tell(); 22 | } 23 | } 24 | 25 | { 26 | printf("testing openForRead\n"); 27 | GzipFile reader(GzipFile::openForRead(filename)); 28 | if (reader.valid()) 29 | { 30 | char buf[256]; 31 | LOG_INFO << "tell " <= 0) 35 | { 36 | buf[nread] = '\0'; 37 | printf("data: %s\n", buf); 38 | } 39 | LOG_INFO << "tell " << reader.tell(); 40 | if (strncmp(buf, data, strlen(data)) != 0) 41 | { 42 | printf("failed!\n"); 43 | abort(); 44 | } 45 | else 46 | { 47 | printf("passed!\n"); 48 | } 49 | } 50 | } 51 | 52 | { 53 | printf("testing openForWriteExclusive\n"); 54 | GzipFile writer = GzipFile::openForWriteExclusive(filename); 55 | if (writer.valid() || errno != EEXIST) 56 | { 57 | printf("failed!\n"); 58 | } 59 | else 60 | { 61 | printf("passed!\n"); 62 | } 63 | } 64 | unlink(filename); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /test/InetAddressTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | void dnsParse(const blink::string& hostname) 10 | { 11 | struct sockaddr_in sock_addr; 12 | memset(&sock_addr, 0, sizeof(sock_addr)); 13 | blink::InetAddress addr(sock_addr); 14 | if (blink::InetAddress::resolve(hostname, &addr)) 15 | { 16 | printf("%s parse succeed, IpAddr: %s\n", hostname.c_str(), addr.toIp().c_str()); 17 | } 18 | else 19 | { 20 | printf("%s parse failed\n", hostname.c_str()); 21 | } 22 | } 23 | 24 | void testIpPort() 25 | { 26 | for (int i = 0; i < 255; ++i) 27 | { 28 | std::ostringstream os; 29 | os << "192.168." << i << ".255"; 30 | blink::InetAddress addr(os.str().c_str(), static_cast(10 * i)); 31 | printf("Ip: %s\n", addr.toIp().c_str()); 32 | } 33 | for (int i = 0; i < 255; ++i) 34 | { 35 | blink::InetAddress addr("192.168.1.1", static_cast(10 * i)); 36 | printf("Port: %hu\n", addr.toPort()); 37 | } 38 | for (int i = 0; i < 255; ++i) 39 | { 40 | std::ostringstream os; 41 | os << "192.168.1." << i; 42 | blink::InetAddress addr(os.str().c_str(), static_cast(10 * i)); 43 | printf("Ip: Port %s\n", addr.toIpPort().c_str()); 44 | } 45 | } 46 | 47 | void testResolve() 48 | { 49 | dnsParse("www.baidu.com"); 50 | dnsParse("www.google.com"); 51 | dnsParse("facebook.com"); 52 | dnsParse("stackoverflow.com"); 53 | dnsParse("www.163.com"); 54 | dnsParse("www.zhihu.com"); 55 | dnsParse("twiter.com"); 56 | dnsParse("twitch.com"); 57 | dnsParse("youtube.com"); 58 | dnsParse("cnblog.com"); 59 | dnsParse("www.csdn.com"); 60 | dnsParse("www.1201dsad2sda12sad901.com.dsa"); 61 | dnsParse("dsadqw12e.cn.net.oki"); 62 | dnsParse("23123asdasd12313asdasd"); 63 | } 64 | 65 | int main(int argc, char const *argv[]) 66 | { 67 | testIpPort(); 68 | testResolve(); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /test/InspectorTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace blink; 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | LOG_INFO << "pid = " << process_info::pid() << ", tid = " << current_thread::tid(); 11 | EventLoop loop; 12 | Inspector inspector(&loop, InetAddress(9600), "Inspector"); 13 | loop.loop(); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /test/LogFileTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | using namespace blink; 12 | 13 | boost::scoped_ptr logfile; 14 | 15 | void outputFunc(const char* message, size_t len) 16 | { 17 | logfile->append(message, len); 18 | } 19 | 20 | void flushFunc() 21 | { 22 | logfile->flush(); 23 | } 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | char buf[256]; 28 | snprintf(buf, sizeof (buf), "%s", argv[0]); 29 | LogFile::setTimeZone(TimeZone(3600 * 8, "CST")); 30 | logfile.reset(new LogFile(::basename(buf), 1024*200)); 31 | Log::setOutput(outputFunc); 32 | Log::setFlush(flushFunc); 33 | 34 | string s = "1234567890 QWERTYUUIOPASDFGHJKLZXCVBN sadasdqwewqsadadasd"; 35 | for (int i = 0; i < 1024 * 10; ++i) 36 | { 37 | LOG_INFO << s; 38 | usleep(1000); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /test/LogStreamTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace blink; 6 | 7 | int main(int argc, char const *argv[]) 8 | { 9 | LogStream logstream; 10 | char* p = NULL; 11 | logstream << p; 12 | string s = logstream.buffer().toString(); 13 | printf("%s\n", s.c_str()); 14 | logstream.reset(); 15 | 16 | logstream << 201412201415; 17 | s = logstream.buffer().toString(); 18 | printf("%s\n", s.c_str()); 19 | logstream.reset(); 20 | 21 | logstream << Format("2014: %lld", 20141220520); 22 | s = logstream.buffer().toString(); 23 | printf("%s\n", s.c_str()); 24 | 25 | Format fmt("2014-12-20: %lld", 201412205220); 26 | s = fmt.data(); 27 | printf("%s\n", s.c_str()); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /test/LogTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace blink; 8 | 9 | int main(int argc, char const *argv[]) 10 | { 11 | //Log::setLogLevel(Log::TRACE); 12 | LOG_TRACE << "hey!"; 13 | LOG_DEBUG << "GO! GO! GO!"; 14 | LOG_INFO << "hello, world"; 15 | LOG_WARN << "HOW ARE YOU"; 16 | LOG_ERROR << "ERROR!"; 17 | 18 | char* p = NULL; 19 | CHECK_NOTNULL(p); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /test/ProcessInfoTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace blink; 6 | using namespace blink::process_info; 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | printf("pidString : %s\n", pidString().c_str()); 11 | printf("usrname : %s\n", username().c_str()); 12 | printf("startTime : %s\n", startTime().toString().c_str()); 13 | printf("startTime(format) : %s\n", startTime().toFormattedString().c_str()); 14 | printf("clockTicksPerSecond : %d\n", clockTicksPerSecond()); 15 | printf("pageSize : %d\n", pageSize()); 16 | printf("isDebugBuild : %s\n", (isDebugBuild() ? "true" : "false")); 17 | printf("hostName : %s\n", hostName().c_str()); 18 | printf("procName : %s\n", procName().c_str()); 19 | printf("procStatus : %s\n", procStatus().c_str()); 20 | printf("procStat : %s\n", procStat().c_str()); 21 | printf("threadStat : %s\n", threadStat().c_str()); 22 | printf("exePath: %s\n", exePath().c_str()); 23 | printf("openedFiles : %d\n", openedFiles()); 24 | printf("maxOpenFiles : %d\n", maxOpenFiles()); 25 | printf("cpuTime: user_seconds = %.12g system_seconds = %.12g\n", 26 | cpuTime().user_seconds, cpuTime().system_seconds); 27 | printf("threadsNumber : %d\n", threadsNumber()); 28 | printf("threads: "); 29 | std::vector vec = threads(); 30 | for (size_t i = 0; i < vec.size(); ++i) 31 | { 32 | printf("%d\n", vec[i]); 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/TcpClientTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | void ConnectionCallback(const blink::TcpConnectionPtr& connection) 11 | { 12 | printf("Have connected to %s\n", connection->peerAddress().toIpPort().c_str()); 13 | } 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | blink::EventLoop loop; 18 | blink::InetAddress server_addr("10.33.1.180", 9600); 19 | blink::TcpClient client(&loop, server_addr, "TcpClient"); 20 | client.setConnectionCallback(ConnectionCallback); 21 | client.connect(); 22 | loop.loop(); 23 | printf("main end\n"); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test/TcpServerTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | using namespace blink; 12 | 13 | void threadInitCallbac(EventLoop* loop) 14 | { 15 | printf("thead tid = %d init in %p\n", current_thread::tid(), loop); 16 | } 17 | 18 | void threadConnectionCallnack(const TcpConnectionPtr& connection) 19 | { 20 | //connection->forceClose(); 21 | } 22 | 23 | int main(int argc, char const *argv[]) 24 | { 25 | EventLoop loop; 26 | InetAddress local_addr(9600); 27 | TcpServer server(&loop, local_addr, "TcpServer"); 28 | server.setThreadNumber(5); 29 | server.setThreadInitCallback(threadInitCallbac); 30 | server.setConnectionCallback(threadConnectionCallnack); 31 | server.start(); 32 | loop.loop(); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /test/ThreadLocalSingletonTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace blink; 11 | 12 | class Test 13 | { 14 | public: 15 | Test() 16 | { 17 | printf("tid = %d, constructing addr: %p\n", current_thread::tid(), this); 18 | } 19 | 20 | ~Test() 21 | { 22 | printf("tid = %d, destructing addr: %p, Test name: %s\n", current_thread::tid(), this, name_.c_str()); 23 | } 24 | 25 | void setName(const string& namemsg) 26 | { 27 | name_ = namemsg; 28 | } 29 | 30 | const string& name() const 31 | { 32 | return name_; 33 | } 34 | 35 | private: 36 | string name_; 37 | }; 38 | 39 | void print() 40 | { 41 | printf("tid = %d, singleton obj name: %s\n", 42 | current_thread::tid(), ThreadLocalSingleton::getInstance().name().c_str()); 43 | } 44 | 45 | void func(string change) 46 | { 47 | print(); 48 | ThreadLocalSingleton::getInstance().setName(change); 49 | timespec sp = {1, 0}; 50 | nanosleep(&sp, NULL); 51 | print(); 52 | } 53 | 54 | int main(int argc, char const *argv[]) 55 | { 56 | ThreadLocalSingleton::getInstance().setName("main set start"); 57 | print(); 58 | Thread t1(boost::bind(func, "t1 changed")); 59 | Thread t2(boost::bind(func, "t2 changed")); 60 | t1.start(); 61 | t2.start(); 62 | t1.join(); 63 | t2.join(); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /test/ThreadLocalTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | using namespace blink; 8 | 9 | class ThreadLocalTest 10 | { 11 | public: 12 | ThreadLocalTest() 13 | { 14 | printf("Thread tid: %d, Thread name: %s , construct addr: %p\n", 15 | current_thread::tid(), current_thread::threadName(), this); 16 | } 17 | 18 | ~ThreadLocalTest() 19 | { 20 | printf("Thread tid: %d, Thread name: %s , destruct addr: %p, test name: %s\n", 21 | current_thread::tid(), current_thread::threadName(), this, name_.c_str()); 22 | } 23 | 24 | void setName(const string namemsg) 25 | { 26 | name_ = namemsg; 27 | } 28 | 29 | const string& name() const 30 | { 31 | return name_; 32 | } 33 | 34 | private: 35 | string name_; 36 | }; 37 | 38 | ThreadLocal test1; 39 | ThreadLocal test2; 40 | 41 | void print() 42 | { 43 | printf("Thread tid: %d, test1 addr: %p, test1 name: %s\n", 44 | current_thread::tid(), &test1, test1.value().name().c_str()); 45 | printf("Thread tid: %d, test2 addr: %p, test2 name: %s\n", 46 | current_thread::tid(), &test2, test2.value().name().c_str()); 47 | } 48 | 49 | void func() 50 | { 51 | print(); 52 | test1.value().setName("change test1 by subthread."); 53 | test2.value().setName("change test2 by subthread."); 54 | print(); 55 | } 56 | 57 | int main(int argc, char const *argv[]) 58 | { 59 | print(); 60 | test1.value().setName("main change test1"); 61 | test2.value().setName("main change test2"); 62 | Thread t1(func, "sub thread"); 63 | t1.start(); 64 | print(); 65 | t1.join(); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /test/ThreadPoolTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using namespace blink; 11 | 12 | void print() 13 | { 14 | LOG_INFO << "tid=" << current_thread::tid(); 15 | } 16 | 17 | void printString(const string& s) 18 | { 19 | LOG_INFO << "tid=" << current_thread::tid() << " " << s.c_str(); 20 | } 21 | 22 | void test(size_t size) 23 | { 24 | ThreadPool threadpool(string("TestThreadPool")); 25 | threadpool.setMaxQueueSize(size); 26 | threadpool.start(5); 27 | threadpool.run(print); 28 | threadpool.run(print); 29 | 30 | for (int i = 1; i <= 100; ++i) 31 | { 32 | char buf[32]; 33 | snprintf(buf, sizeof(buf), "cycle task test: %d", i); 34 | threadpool.run(boost::bind(printString, string(buf))); 35 | } 36 | LOG_INFO << "done"; 37 | usleep(1); 38 | struct timespec sp = {1, 0}; 39 | nanosleep(&sp, NULL); 40 | LOG_INFO << "wake up from sleep"; 41 | } 42 | 43 | int main(int argc, char const *argv[]) 44 | { 45 | test(5); 46 | LOG_INFO << "back from test()"; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test/TimerQueueTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | using namespace blink; 15 | 16 | int count = 0; 17 | EventLoop* g_loop; 18 | 19 | void printId() 20 | { 21 | printf("pid = %d, tid = %d\n", getpid(), current_thread::tid()); 22 | printf("now %s\n", Timestamp::now().toFormattedString().c_str()); 23 | } 24 | 25 | void print(const char* message) 26 | { 27 | printf("message %s %s\n", Timestamp::now().toFormattedString().c_str(), message); 28 | if (++count == 100) 29 | { 30 | g_loop->quit(); 31 | } 32 | } 33 | 34 | void cancel(TimerId timer) 35 | { 36 | g_loop->cancel(timer); 37 | printf("canceled at %s\n", Timestamp::now().toFormattedString().c_str()); 38 | } 39 | 40 | int main(int argc, char const *argv[]) 41 | { 42 | printId(); 43 | sleep(1); 44 | { 45 | EventLoop loop; 46 | g_loop = &loop; 47 | printf("main\n"); 48 | loop.runAfter(1, boost::bind(print, "once1")); 49 | loop.runAfter(1.5, boost::bind(print, "once1.5")); 50 | loop.runAfter(2.5, boost::bind(print, "once2.5")); 51 | loop.runAfter(3.5, boost::bind(print, "once3.5")); 52 | TimerId t45 = loop.runAfter(4, boost::bind(print, "once4.5")); 53 | loop.runAfter(4.2, boost::bind(cancel, t45)); 54 | loop.runAfter(4.8, boost::bind(cancel, t45)); 55 | 56 | loop.runEvery(2, boost::bind(print, "every2")); 57 | TimerId t3 = loop.runEvery(3, boost::bind(print, "every3")); 58 | loop.runAfter(9.001, boost::bind(cancel, t3)); 59 | printf("loop start\n"); 60 | loop.loop(); 61 | printf("main loop exits.\n"); 62 | } 63 | sleep(1); 64 | { 65 | EventLoopThread loop_thread; 66 | EventLoop* loop = loop_thread.startLoop(); 67 | loop->runAfter(2, printId); 68 | sleep(3); 69 | printf("thread loop exits.\n"); 70 | } 71 | return 0; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /test/TimestampTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace blink; 10 | 11 | int main(int argc, char const *argv[]) 12 | { 13 | Timestamp tm_stamp(Timestamp::now()); 14 | string s = tm_stamp.toString(); 15 | string s_fmt = tm_stamp.toFormattedString(true); 16 | printf("%s\n", s.c_str()); 17 | printf("%s\n", s_fmt.c_str()); 18 | struct timeval tv; 19 | gettimeofday(&tv, 0); 20 | printf("%ld\n", tv.tv_sec); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /test/WeakCallbackTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | class WeakCallbackTest 10 | { 11 | public: 12 | void foo() 13 | { 14 | printf("WeakCallbackTest non-const member function\n"); 15 | } 16 | 17 | void bar() const 18 | { 19 | printf("WeakCallbackTest const member function\n"); 20 | } 21 | }; 22 | 23 | void get(WeakCallbackTest* ptr) 24 | { 25 | printf("WeakCallbackTest non-member function, ptr addr: %p\n", ptr); 26 | } 27 | 28 | int main(int argc, char const *argv[]) 29 | { 30 | boost::shared_ptr mem_func(new WeakCallbackTest); 31 | blink::makeWeakCallback(mem_func, &WeakCallbackTest::foo)(); 32 | 33 | boost::shared_ptr mem_func_const(new WeakCallbackTest); 34 | blink::makeWeakCallback(mem_func_const, &WeakCallbackTest::bar)(); 35 | 36 | boost::shared_ptr non_mem_func(new WeakCallbackTest); 37 | blink::makeWeakCallback(non_mem_func, get)(); 38 | return 0; 39 | } 40 | --------------------------------------------------------------------------------