The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitignore
├── CMakeLists.txt
├── Doxyfile
├── Makefile
├── README.md
├── bin
    ├── conf
    │   ├── fox_thread.yml
    │   ├── log.yml
    │   ├── redis.yml
    │   ├── server.yml
    │   ├── service.yml
    │   ├── system.yml
    │   └── worker.yml
    └── orm_conf
    │   └── user.xml
├── cmake
    ├── FindMySQL.cmake
    └── utils.cmake
├── examples
    ├── echo_server.cc
    ├── echo_server_udp.cc
    └── echo_udp_client.cc
├── generate.sh
├── samples
    └── my_http_server.cc
├── sylar
    ├── address.cc
    ├── address.h
    ├── application.cc
    ├── application.h
    ├── bytearray.cc
    ├── bytearray.h
    ├── config.cc
    ├── config.h
    ├── daemon.cc
    ├── daemon.h
    ├── db
    │   ├── db.h
    │   ├── fox_thread.cc
    │   ├── fox_thread.h
    │   ├── mysql.cc
    │   ├── mysql.h
    │   ├── redis.cc
    │   ├── redis.h
    │   ├── sqlite3.cc
    │   └── sqlite3.h
    ├── ds
    │   ├── array.h
    │   ├── bitmap.cc
    │   ├── bitmap.h
    │   ├── cache_status.h
    │   ├── dict.h
    │   ├── hash_map.h
    │   ├── hash_multimap.h
    │   ├── lru_cache.h
    │   ├── roaring.c
    │   ├── roaring.h
    │   ├── roaring.hh
    │   ├── roaring_bitmap.cc
    │   ├── roaring_bitmap.h
    │   ├── timed_cache.h
    │   ├── timed_lru_cache.h
    │   ├── util.cc
    │   └── util.h
    ├── email
    │   ├── email.cc
    │   ├── email.h
    │   ├── smtp.cc
    │   └── smtp.h
    ├── endian.h
    ├── env.cc
    ├── env.h
    ├── fd_manager.cc
    ├── fd_manager.h
    ├── fiber.cc
    ├── fiber.h
    ├── hook.cc
    ├── hook.h
    ├── http
    │   ├── http.cc
    │   ├── http.h
    │   ├── http11_common.h
    │   ├── http11_parser.h
    │   ├── http11_parser.rl
    │   ├── http_connection.cc
    │   ├── http_connection.h
    │   ├── http_parser.cc
    │   ├── http_parser.h
    │   ├── http_server.cc
    │   ├── http_server.h
    │   ├── http_session.cc
    │   ├── http_session.h
    │   ├── httpclient_parser.h
    │   ├── httpclient_parser.rl
    │   ├── servlet.cc
    │   ├── servlet.h
    │   ├── servlets
    │   │   ├── config_servlet.cc
    │   │   ├── config_servlet.h
    │   │   ├── status_servlet.cc
    │   │   └── status_servlet.h
    │   ├── session_data.cc
    │   ├── session_data.h
    │   ├── ws_connection.cc
    │   ├── ws_connection.h
    │   ├── ws_server.cc
    │   ├── ws_server.h
    │   ├── ws_servlet.cc
    │   ├── ws_servlet.h
    │   ├── ws_session.cc
    │   └── ws_session.h
    ├── iomanager.cc
    ├── iomanager.h
    ├── library.cc
    ├── library.h
    ├── log.cc
    ├── log.h
    ├── macro.h
    ├── main.cc
    ├── module.cc
    ├── module.h
    ├── mutex.cc
    ├── mutex.h
    ├── noncopyable.h
    ├── ns
    │   ├── name_server_module.cc
    │   ├── name_server_module.h
    │   ├── ns_client.cc
    │   ├── ns_client.h
    │   ├── ns_protobuf.proto
    │   ├── ns_protocol.cc
    │   └── ns_protocol.h
    ├── orm
    │   ├── column.cc
    │   ├── column.h
    │   ├── index.cc
    │   ├── index.h
    │   ├── orm.cc
    │   ├── table.cc
    │   ├── table.h
    │   ├── util.cc
    │   └── util.h
    ├── protocol.cc
    ├── protocol.h
    ├── rock
    │   ├── rock_protocol.cc
    │   ├── rock_protocol.h
    │   ├── rock_server.cc
    │   ├── rock_server.h
    │   ├── rock_stream.cc
    │   └── rock_stream.h
    ├── scheduler.cc
    ├── scheduler.h
    ├── singleton.h
    ├── socket.cc
    ├── socket.h
    ├── stream.cc
    ├── stream.h
    ├── streams
    │   ├── async_socket_stream.cc
    │   ├── async_socket_stream.h
    │   ├── load_balance.cc
    │   ├── load_balance.h
    │   ├── service_discovery.cc
    │   ├── service_discovery.h
    │   ├── socket_stream.cc
    │   ├── socket_stream.h
    │   ├── zlib_stream.cc
    │   └── zlib_stream.h
    ├── sylar.h
    ├── tcp_server.cc
    ├── tcp_server.h
    ├── test.proto
    ├── thread.cc
    ├── thread.h
    ├── timer.cc
    ├── timer.h
    ├── uri.h
    ├── uri.rl
    ├── util.cc
    ├── util.h
    ├── util
    │   ├── crypto_util.cc
    │   ├── crypto_util.h
    │   ├── hash_util.cc
    │   ├── hash_util.h
    │   ├── json_util.cc
    │   └── json_util.h
    ├── worker.cc
    ├── worker.h
    ├── zk_client.cc
    └── zk_client.h
├── template
    ├── CMakeLists.txt
    ├── bin
    │   └── conf
    │   │   ├── log.yml
    │   │   ├── server.yml
    │   │   ├── system.yml
    │   │   └── worker.yml
    ├── move.sh
    └── template
    │   ├── my_module.cc
    │   └── my_module.h
└── tests
    ├── test.cc
    ├── test_address.cc
    ├── test_application.cc
    ├── test_array.cc
    ├── test_bitmap.cc
    ├── test_bytearray.cc
    ├── test_config.cc
    ├── test_crypto.cc
    ├── test_daemon.cc
    ├── test_dict.cc
    ├── test_email.cc
    ├── test_env.cc
    ├── test_fiber.cc
    ├── test_hashmap.cc
    ├── test_hashmultimap.cc
    ├── test_hook.cc
    ├── test_http.cc
    ├── test_http_connection.cc
    ├── test_http_parser.cc
    ├── test_http_server.cc
    ├── test_iomanager.cc
    ├── test_lru.cc
    ├── test_module.cc
    ├── test_mysql.cc
    ├── test_nameserver.cc
    ├── test_orm.cc
    ├── test_rock.cc
    ├── test_scheduler.cc
    ├── test_service_discovery.cc
    ├── test_socket.cc
    ├── test_sqlite3.cc
    ├── test_tcp_server.cc
    ├── test_thread.cc
    ├── test_timed_cache.cc
    ├── test_timed_lru_cache.cc
    ├── test_uri.cc
    ├── test_util.cc
    ├── test_ws_client.cc
    ├── test_ws_server.cc
    ├── test_zlib_stream.cc
    └── test_zookeeper.cc


/.gitignore:
--------------------------------------------------------------------------------
 1 | tags
 2 | *.o
 3 | *.sub
 4 | *.guess
 5 | ltmain.sh
 6 | *.la
 7 | *.a
 8 | .deps
 9 | .dirstamp
10 | .libs
11 | *.lo
12 | *.pb.h
13 | *.pb.cc
14 | *.rl.cc
15 | aclocal.m4
16 | autom4te.cache
17 | config.h.in
18 | config.log
19 | config.status
20 | configure
21 | config.h.in~
22 | install-sh
23 | libtool
24 | Makefile
25 | Makefile.in
26 | missing
27 | stamp-h1
28 | *.pc
29 | depcomp
30 | *.xcodeproj
31 | 


--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
 1 | .PHONY: xx
 2 | 
 3 | "":
 4 | 	if [ -d "build" ]; then \
 5 | 		cd build && make -j4; \
 6 | 	else \
 7 | 		mkdir build; \
 8 | 		cd build && cmake -DCMAKE_CXX_COMPILER:FILEPATH=$(shell which g++) -DCMAKE_C_COMPILER:FILEPATH=$(shell which gcc) ..; \
 9 | 	fi
10 | 
11 | %:
12 | 	if [ -d "build" ]; then \
13 | 		cd build && make $@; \
14 | 	else \
15 | 		mkdir build; \
16 | 		cd build && cmake -DCMAKE_CXX_COMPILER:FILEPATH=$(shell which g++) -DCMAKE_C_COMPILER:FILEPATH=$(shell which gcc) $@ ..; \
17 | 	fi
18 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # 视频地址
 2 | [\[C++高级教程\]从零开始开发服务器框架(sylar)](https://www.bilibili.com/video/av53602631/?from=www.sylar.top "")
 3 | # 视频教程内容:
 4 | ## 1.日志模块
 5 | 支持流式日志风格写日志和格式化风格写日志,支持日志格式自定义,日志级别,多日志分离等等功能
 6 | 流式日志使用:SYLAR_LOG_INFO(g_logger) << "this is a log";
 7 | 格式化日志使用:SYLAR_LOG_FMT_INFO(g_logger, "%s", "this is a log");
 8 | 支持时间,线程id,线程名称,日志级别,日志名称,文件名,行号等内容的自由配置
 9 | ## 2.配置模块
10 | 采用约定由于配置的思想。定义即可使用。不需要单独去解析。支持变更通知功能。使用YAML文件做为配置内容。支持级别格式的数据类型,支持STL容器(vector,list,set,map等等),支持自定义类型的支持(需要实现序列化和反序列化方法)使用方式如下:
11 | ```cpp
12 | static sylar::ConfigVar<int>::ptr g_tcp_connect_timeout =
13 | 	sylar::Config::Lookup("tcp.connect.timeout", 5000, "tcp connect timeout");
14 | ```
15 | 定义了一个tcp连接超时参数,可以直接使用 g_tcp_connect_timeout->getValue() 获取参数的值,当配置修改重新加载,该值自动更新
16 | 上述配置格式如下:
17 | ```sh
18 | tcp:
19 |     connect:
20 |             timeout: 10000
21 | ```
22 | ## 3.线程模块
23 | 线程模块,封装了pthread里面的一些常用功能,Thread,Semaphore,Mutex,RWMutex,Spinlock等对象,可以方便开发中对线程日常使用
24 | 为什么不适用c++11里面的thread
25 | 本框架是使用C++11开发,不使用thread,是因为thread其实也是基于pthread实现的。并且C++11里面没有提供读写互斥量,RWMutex,Spinlock等,在高并发场景,这些对象是经常需要用到的。所以选择了自己封装pthread
26 | ## 4.协程模块
27 | 协程:用户态的线程,相当于线程中的线程,更轻量级。后续配置socket hook,可以把复杂的异步调用,封装成同步操作。降低业务逻辑的编写复杂度。
28 | 目前该协程是基于ucontext_t来实现的,后续将支持采用boost.context里面的fcontext_t的方式实现
29 | ## 5.协程调度模块
30 | 协程调度器,管理协程的调度,内部实现为一个线程池,支持协程在多线程中切换,也可以指定协程在固定的线程中执行。是一个N-M的协程调度模型,N个线程,M个协程。重复利用每一个线程。
31 | ## 6.IO协程调度模块
32 | 继承与协程调度器,封装了epoll(Linux),并支持定时器功能(使用epoll实现定时器,精度毫秒级),支持Socket读写时间的添加,删除,取消功能。支持一次性定时器,循环定时器,条件定时器等功能
33 | ## 7.Hook模块
34 | hook系统底层和socket相关的API,socket io相关的API,以及sleep系列的API。hook的开启控制是线程粒度的。可以自由选择。通过hook模块,可以使一些不具异步功能的API,展现出异步的性能。如(mysql)
35 | ## 8.Socket模块
36 | 封装了Socket类,提供所有socket API功能,统一封装了地址类,将IPv4,IPv6,Unix地址统一起来。并且提供域名,IP解析功能。
37 | ## 9.ByteArray序列化模块
38 | ByteArray二进制序列化模块,提供对二进制数据的常用操作。读写入基础类型int8_t,int16_t,int32_t,int64_t等,支持Varint,std::string的读写支持,支持字节序转化,支持序列化到文件,以及从文件反序列化等功能
39 | ## 10.TcpServer模块
40 | 基于Socket类,封装了一个通用的TcpServer的服务器类,提供简单的API,使用便捷,可以快速绑定一个或多个地址,启动服务,监听端口,accept连接,处理socket连接等功能。具体业务功能更的服务器实现,只需要继承该类就可以快速实现
41 | ## 11.Stream模块
42 | 封装流式的统一接口。将文件,socket封装成统一的接口。使用的时候,采用统一的风格操作。基于统一的风格,可以提供更灵活的扩展。目前实现了SocketStream
43 | ## 12.HTTP模块
44 | 采用Ragel(有限状态机,性能媲美汇编),实现了HTTP/1.1的简单协议实现和uri的解析。基于SocketStream实现了HttpConnection(HTTP的客户端)和HttpSession(HTTP服务器端的链接)。基于TcpServer实现了HttpServer。提供了完整的HTTP的客户端API请求功能,HTTP基础API服务器功能
45 | ## 13.Servlet模块
46 | 仿照java的servlet,实现了一套Servlet接口,实现了ServletDispatch,FunctionServlet。NotFoundServlet。支持uri的精准匹配,模糊匹配等功能。和HTTP模块,一起提供HTTP服务器功能
47 | ## 14.其他相关
48 | 联系方式:
49 |  QQ:564628276
50 |  邮箱:564628276@qq.com
51 |  微信:sylar-yin
52 |  QQ群:8151915(sylar技术群)
53 | 个人主页:www.sylar.top
54 | github:https://github.com/sylar-yin/sylar
55 | 


--------------------------------------------------------------------------------
/bin/conf/fox_thread.yml:
--------------------------------------------------------------------------------
1 | fox_thread:
2 |     redis:
3 |         name: redis
4 |         num: 2
5 |         advance: 0
6 | 


--------------------------------------------------------------------------------
/bin/conf/log.yml:
--------------------------------------------------------------------------------
 1 | logs:
 2 |     - name: root
 3 |       level: info
 4 |       appenders:
 5 |           - type: FileLogAppender
 6 |             file: /apps/logs/sylar/root.txt
 7 |           - type: StdoutLogAppender
 8 |     - name: system
 9 |       level: info
10 |       appenders:
11 |           - type: FileLogAppender
12 |             file: /apps/logs/sylar/system.txt
13 |           - type: StdoutLogAppender
14 | 


--------------------------------------------------------------------------------
/bin/conf/redis.yml:
--------------------------------------------------------------------------------
1 | redis:
2 |     config:
3 |         local:
4 |             host: 127.0.0.1:6379
5 |             type: fox_redis
6 |             pool: 2
7 |             timeout: 100
8 |     desc: "type: redis,redis_cluster,fox_redis,fox_redis_cluster"
9 | 


--------------------------------------------------------------------------------
/bin/conf/server.yml:
--------------------------------------------------------------------------------
 1 | servers:
 2 |     - address: ["0.0.0.0:8090", "127.0.0.1:8091", "/tmp/test.sock"]
 3 |       keepalive: 1
 4 |       timeout: 1000
 5 |       name: sylar/1.1
 6 |       accept_worker: accept
 7 |       io_worker: http_io
 8 |       process_worker:  http_io
 9 |       type: http
10 |     - address: ["0.0.0.0:8062", "0.0.0.0:8061"]
11 |       timeout: 1000
12 |       name: sylar-rock/1.0
13 |       accept_worker: accept
14 |       io_worker: io
15 |       process_worker:  io
16 |       type: rock
17 | 


--------------------------------------------------------------------------------
/bin/conf/service.yml:
--------------------------------------------------------------------------------
1 | service_discovery:
2 |     zk: 127.0.0.1:21811
3 | rock_services:
4 |     sylar.top:
5 |         "all" : fair
6 | 


--------------------------------------------------------------------------------
/bin/conf/system.yml:
--------------------------------------------------------------------------------
1 | server:
2 |     work_path: /apps/work/sylar
3 |     pid_file: sylar.pid
4 | 


--------------------------------------------------------------------------------
/bin/conf/worker.yml:
--------------------------------------------------------------------------------
 1 | workers:
 2 |     io:
 3 |         thread_num: 8
 4 |     http_io:
 5 |         thread_num: 1
 6 |     accept:
 7 |         thread_num: 2
 8 |     worker:
 9 |         thread_num: 8
10 |     notify:
11 |         thread_num: 8
12 |     service_io:
13 |         thread_num: 4
14 | 


--------------------------------------------------------------------------------
/bin/orm_conf/user.xml:
--------------------------------------------------------------------------------
 1 | <table name="user" namespace="test.orm">
 2 |     <columns>
 3 |         <column name="id" type="int64" desc="唯一主键" auto_increment="true"/>
 4 |         <column name="name" type="string" desc="名称" length="30"/>
 5 |         <column name="email" type="string" default="xx@xx.com"/>
 6 |         <column name="phone" type="string"/>
 7 |         <column name="status" type="int32" default="10"/>
 8 |         <column name="create_time" type="timestamp"/>
 9 |         <column name="update_time" type="timestamp" default="current_timestamp" update="current_timestamp"/>
10 |     </columns>
11 |     <indexs>
12 |         <index name="pk" cols="id" type="pk" desc="主键"/>
13 |         <index name="name" cols="name" type="uniq" desc="关联"/>
14 |         <index name="email" cols="email" type="uniq" desc="关联"/>
15 |         <index name="status" cols="status" type="index" desc="关联"/>
16 |     </indexs>
17 | </table>
18 | 


--------------------------------------------------------------------------------
/cmake/utils.cmake:
--------------------------------------------------------------------------------
 1 | function(force_redefine_file_macro_for_sources targetname)
 2 |     get_target_property(source_files "${targetname}" SOURCES)
 3 |     foreach(sourcefile ${source_files})
 4 |         # Get source file's current list of compile definitions.
 5 |         get_property(defs SOURCE "${sourcefile}"
 6 |             PROPERTY COMPILE_DEFINITIONS)
 7 |         # Get the relative path of the source file in project directory
 8 |         get_filename_component(filepath "${sourcefile}" ABSOLUTE)
 9 |         string(REPLACE ${PROJECT_SOURCE_DIR}/ "" relpath ${filepath})
10 |         list(APPEND defs "__FILE__=\"${relpath}\"")
11 |         # Set the updated compile definitions on the source file.
12 |         set_property(
13 |             SOURCE "${sourcefile}"
14 |             PROPERTY COMPILE_DEFINITIONS ${defs}
15 |             )
16 |     endforeach()
17 | endfunction()
18 | 
19 | function(ragelmaker src_rl outputlist outputdir)
20 |     #Create a custom build step that will call ragel on the provided src_rl file.
21 |     #The output .cpp file will be appended to the variable name passed in outputlist.
22 | 
23 |     get_filename_component(src_file ${src_rl} NAME_WE)
24 | 
25 |     set(rl_out ${outputdir}/${src_file}.rl.cc)
26 | 
27 |     #adding to the list inside a function takes special care, we cannot use list(APPEND...)
28 |     #because the results are local scope only
29 |     set(${outputlist} ${${outputlist}} ${rl_out} PARENT_SCOPE)
30 | 
31 |     #Warning: The " -S -M -l -C -T0  --error-format=msvc" are added to match existing window invocation
32 |     #we might want something different for mac and linux
33 |     add_custom_command(
34 |         OUTPUT ${rl_out}
35 |         COMMAND cd ${outputdir}
36 |         COMMAND ragel ${CMAKE_CURRENT_SOURCE_DIR}/${src_rl} -o ${rl_out} -l -C -G2  --error-format=msvc
37 |         DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src_rl}
38 |         )
39 |     set_source_files_properties(${rl_out} PROPERTIES GENERATED TRUE)
40 | endfunction(ragelmaker)
41 | 
42 | function(protobufmaker src_proto outputlist outputdir)
43 |     #Create a custom build step that will call ragel on the provided src_rl file.
44 |     #The output .cpp file will be appended to the variable name passed in outputlist.
45 | 
46 |     get_filename_component(src_file ${src_proto} NAME_WE)
47 |     get_filename_component(src_path ${src_proto} PATH)
48 | 
49 |     set(protobuf_out ${outputdir}/${src_path}/${src_file}.pb.cc)
50 | 
51 |     #adding to the list inside a function takes special care, we cannot use list(APPEND...)
52 |     #because the results are local scope only
53 |     set(${outputlist} ${${outputlist}} ${protobuf_out} PARENT_SCOPE)
54 | 
55 |     add_custom_command(
56 |         OUTPUT ${protobuf_out}
57 |         COMMAND protoc --cpp_out=${outputdir} -I${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${src_proto}
58 |         DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src_proto}
59 |         )
60 |     set_source_files_properties(${protobuf_out} PROPERTIES GENERATED TRUE)
61 | endfunction(protobufmaker)
62 | 
63 | 
64 | function(sylar_add_executable targetname srcs depends libs)
65 |     add_executable(${targetname} ${srcs})
66 |     add_dependencies(${targetname} ${depends})
67 |     force_redefine_file_macro_for_sources(${targetname})
68 |     target_link_libraries(${targetname} ${libs})
69 | endfunction()
70 | 


--------------------------------------------------------------------------------
/examples/echo_server.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/tcp_server.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/iomanager.h"
 4 | #include "sylar/bytearray.h"
 5 | #include "sylar/address.h"
 6 | 
 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 8 | 
 9 | class EchoServer : public sylar::TcpServer {
10 | public:
11 |     EchoServer(int type);
12 |     void handleClient(sylar::Socket::ptr client);
13 | 
14 | private:
15 |     int m_type = 0;
16 | };
17 | 
18 | EchoServer::EchoServer(int type)
19 |     :m_type(type) {
20 | }
21 | 
22 | void EchoServer::handleClient(sylar::Socket::ptr client) {
23 |     SYLAR_LOG_INFO(g_logger) << "handleClient " << *client;   
24 |     sylar::ByteArray::ptr ba(new sylar::ByteArray);
25 |     while(true) {
26 |         ba->clear();
27 |         std::vector<iovec> iovs;
28 |         ba->getWriteBuffers(iovs, 1024);
29 | 
30 |         int rt = client->recv(&iovs[0], iovs.size());
31 |         if(rt == 0) {
32 |             SYLAR_LOG_INFO(g_logger) << "client close: " << *client;
33 |             break;
34 |         } else if(rt < 0) {
35 |             SYLAR_LOG_INFO(g_logger) << "client error rt=" << rt
36 |                 << " errno=" << errno << " errstr=" << strerror(errno);
37 |             break;
38 |         }
39 |         ba->setPosition(ba->getPosition() + rt);
40 |         ba->setPosition(0);
41 |         //SYLAR_LOG_INFO(g_logger) << "recv rt=" << rt << " data=" << std::string((char*)iovs[0].iov_base, rt);
42 |         if(m_type == 1) {//text 
43 |             std::cout << ba->toString();// << std::endl;
44 |         } else {
45 |             std::cout << ba->toHexString();// << std::endl;
46 |         }
47 |         std::cout.flush();
48 |     }
49 | }
50 | 
51 | int type = 1;
52 | 
53 | void run() {
54 |     SYLAR_LOG_INFO(g_logger) << "server type=" << type;
55 |     EchoServer::ptr es(new EchoServer(type));
56 |     auto addr = sylar::Address::LookupAny("0.0.0.0:8020");
57 |     while(!es->bind(addr)) {
58 |         sleep(2);
59 |     }
60 |     es->start();
61 | }
62 | 
63 | int main(int argc, char** argv) {
64 |     if(argc < 2) {
65 |         SYLAR_LOG_INFO(g_logger) << "used as[" << argv[0] << " -t] or [" << argv[0] << " -b]";
66 |         return 0;
67 |     }
68 | 
69 |     if(!strcmp(argv[1], "-b")) {
70 |         type = 2;
71 |     }
72 | 
73 |     sylar::IOManager iom(2);
74 |     iom.schedule(run);
75 |     return 0;
76 | }
77 | 


--------------------------------------------------------------------------------
/examples/echo_server_udp.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/socket.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/iomanager.h"
 4 | 
 5 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 6 | 
 7 | void run() {
 8 |     sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8050");
 9 |     sylar::Socket::ptr sock = sylar::Socket::CreateUDP(addr);
10 |     if(sock->bind(addr)) {
11 |         SYLAR_LOG_INFO(g_logger) << "udp bind : " << *addr;
12 |     } else {
13 |         SYLAR_LOG_ERROR(g_logger) << "udp bind : " << *addr << " fail";
14 |         return;
15 |     }
16 |     while(true) {
17 |         char buff[1024];
18 |         sylar::Address::ptr from(new sylar::IPv4Address);
19 |         int len = sock->recvFrom(buff, 1024, from);
20 |         if(len > 0) {
21 |             buff[len] = '\0';
22 |             SYLAR_LOG_INFO(g_logger) << "recv: " << buff << " from: " << *from;
23 |             len = sock->sendTo(buff, len, from);
24 |             if(len < 0) {
25 |                 SYLAR_LOG_INFO(g_logger) << "send: " << buff << " to: " << *from
26 |                     << " error=" << len;
27 |             }
28 |         }
29 |     }
30 | }
31 | 
32 | int main(int argc, char** argv) {
33 |     sylar::IOManager iom(1);
34 |     iom.schedule(run);
35 |     return 0;
36 | }
37 | 


--------------------------------------------------------------------------------
/examples/echo_udp_client.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/socket.h"
 2 | #include "sylar/iomanager.h"
 3 | #include "sylar/log.h"
 4 | #include <stdlib.h>
 5 | 
 6 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 7 | 
 8 | const char* ip = nullptr;
 9 | uint16_t port = 0;
10 | 
11 | void run() {
12 |     sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress(ip);
13 |     if(!addr) {
14 |         SYLAR_LOG_ERROR(g_logger) << "invalid ip: " << ip;
15 |         return;
16 |     }
17 |     addr->setPort(port);
18 | 
19 |     sylar::Socket::ptr sock = sylar::Socket::CreateUDP(addr);
20 | 
21 |     sylar::IOManager::GetThis()->schedule([sock](){
22 |             sylar::Address::ptr addr(new sylar::IPv4Address);
23 |             SYLAR_LOG_INFO(g_logger) << "begin recv";
24 |             while(true) {
25 |                 char buff[1024];
26 |                 int len = sock->recvFrom(buff, 1024, addr);
27 |                 if(len > 0) {
28 |                     std::cout << std::endl << "recv: " << std::string(buff, len) << " from: " << *addr << std::endl;
29 |                 }
30 |             }
31 |     });
32 |     sleep(1);
33 |     while(true) {
34 |         std::string line;
35 |         std::cout << "input>";
36 |         std::getline(std::cin, line);
37 |         if(!line.empty()) {
38 |             int len = sock->sendTo(line.c_str(), line.size(), addr);
39 |             if(len < 0) {
40 |                 int err = sock->getError();
41 |                 SYLAR_LOG_ERROR(g_logger) << "send error err=" << err
42 |                         << " errstr=" << strerror(err) << " len=" << len
43 |                         << " addr=" << *addr
44 |                         << " sock=" << *sock;
45 |             } else {
46 |                 SYLAR_LOG_INFO(g_logger) << "send " << line << " len:" << len;
47 |             }
48 |         }
49 |     }
50 | }
51 | 
52 | int main(int argc, char** argv) {
53 |     if(argc < 3) {
54 |         SYLAR_LOG_INFO(g_logger) << "use as[" << argv[0] << " ip port]";
55 |         return 0;
56 |     }
57 |     ip = argv[1];
58 |     port = atoi(argv[2]);
59 |     sylar::IOManager iom(2);
60 |     iom.schedule(run);
61 |     return 0;
62 | }
63 | 


--------------------------------------------------------------------------------
/generate.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | command_error_exit() {
 4 |     $*
 5 |     if [ $? -ne 0 ]
 6 |     then
 7 |         exit 1
 8 |     fi
 9 | }
10 | 
11 | if [ $# -lt 2 ]
12 | then
13 |     echo "use [$0 project_name namespace]"
14 |     exit 0
15 | fi
16 | 
17 | project_name=$1
18 | namespace=$2
19 | 
20 | command_error_exit mkdir $project_name
21 | command_error_exit cd $project_name
22 | command_error_exit git clone https://github.com/sylar-yin/sylar.git
23 | command_error_exit cp sylar/Makefile .
24 | command_error_exit cp -rf sylar/template/* .
25 | command_error_exit cp -rf sylar/template/* .
26 | command_error_exit mv template ${namespace}
27 | command_error_exit sed -i "s/project_name/${project_name}/g" CMakeLists.txt
28 | command_error_exit sed -i "s/template/${namespace}/g" CMakeLists.txt
29 | command_error_exit sed -i "s/project_name/${project_name}/g" move.sh
30 | command_error_exit cd ${namespace}
31 | command_error_exit sed -i "s/name_space/${namespace}/g" `ls .`
32 | command_error_exit sed -i "s/project_name/${project_name}/g" `ls .`
33 | command_error_exit cd ../bin/conf
34 | command_error_exit sed -i "s/name_space/${namespace}/g" `ls .`
35 | command_error_exit sed -i "s/project_name/${project_name}/g" `ls .`
36 | 
37 | echo "create module ${project_name} -- ${namespace} ok" 
38 | 


--------------------------------------------------------------------------------
/samples/my_http_server.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/http/http_server.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | sylar::IOManager::ptr worker;
 6 | void run() {
 7 |     g_logger->setLevel(sylar::LogLevel::INFO);
 8 |     sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020");
 9 |     if(!addr) {
10 |         SYLAR_LOG_ERROR(g_logger) << "get address error";
11 |         return;
12 |     }
13 | 
14 |     sylar::http::HttpServer::ptr http_server(new sylar::http::HttpServer(true, worker.get()));
15 |     //sylar::http::HttpServer::ptr http_server(new sylar::http::HttpServer(true));
16 |     bool ssl = false;
17 |     while(!http_server->bind(addr, ssl)) {
18 |         SYLAR_LOG_ERROR(g_logger) << "bind " << *addr << " fail";
19 |         sleep(1);
20 |     }
21 | 
22 |     if(ssl) {
23 |         //http_server->loadCertificates("/home/apps/soft/sylar/keys/server.crt", "/home/apps/soft/sylar/keys/server.key");
24 |     }
25 | 
26 |     http_server->start();
27 | }
28 | 
29 | int main(int argc, char** argv) {
30 |     sylar::IOManager iom(1);
31 |     worker.reset(new sylar::IOManager(4, false));
32 |     iom.schedule(run);
33 |     return 0;
34 | }
35 | 


--------------------------------------------------------------------------------
/sylar/application.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_APPLICATION_H__
 2 | #define __SYLAR_APPLICATION_H__
 3 | 
 4 | #include "sylar/http/http_server.h"
 5 | #include "sylar/streams/service_discovery.h"
 6 | #include "sylar/rock/rock_stream.h"
 7 | 
 8 | namespace sylar {
 9 | 
10 | class Application {
11 | public:
12 |     Application();
13 | 
14 |     static Application* GetInstance() { return s_instance;}
15 |     bool init(int argc, char** argv);
16 |     bool run();
17 | 
18 |     bool getServer(const std::string& type, std::vector<TcpServer::ptr>& svrs);
19 |     void listAllServer(std::map<std::string, std::vector<TcpServer::ptr> >& servers);
20 | 
21 |     ZKServiceDiscovery::ptr getServiceDiscovery() const { return m_serviceDiscovery;}
22 |     RockSDLoadBalance::ptr getRockSDLoadBalance() const { return m_rockSDLoadBalance;}
23 | private:
24 |     int main(int argc, char** argv);
25 |     int run_fiber();
26 | private:
27 |     int m_argc = 0;
28 |     char** m_argv = nullptr;
29 | 
30 |     //std::vector<sylar::http::HttpServer::ptr> m_httpservers;
31 |     std::map<std::string, std::vector<TcpServer::ptr> > m_servers;
32 |     IOManager::ptr m_mainIOManager;
33 |     static Application* s_instance;
34 | 
35 |     ZKServiceDiscovery::ptr m_serviceDiscovery;
36 |     RockSDLoadBalance::ptr m_rockSDLoadBalance;
37 | };
38 | 
39 | }
40 | 
41 | #endif
42 | 


--------------------------------------------------------------------------------
/sylar/config.cc:
--------------------------------------------------------------------------------
  1 | #include "sylar/config.h"
  2 | #include "sylar/env.h"
  3 | #include "sylar/util.h"
  4 | #include <sys/types.h>
  5 | #include <sys/stat.h>
  6 | #include <unistd.h>
  7 | 
  8 | namespace sylar {
  9 | 
 10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
 11 | 
 12 | ConfigVarBase::ptr Config::LookupBase(const std::string& name) {
 13 |     RWMutexType::ReadLock lock(GetMutex());
 14 |     auto it = GetDatas().find(name);
 15 |     return it == GetDatas().end() ? nullptr : it->second;
 16 | }
 17 | 
 18 | //"A.B", 10
 19 | //A:
 20 | //  B: 10
 21 | //  C: str
 22 | 
 23 | static void ListAllMember(const std::string& prefix,
 24 |                           const YAML::Node& node,
 25 |                           std::list<std::pair<std::string, const YAML::Node> >& output) {
 26 |     if(prefix.find_first_not_of("abcdefghikjlmnopqrstuvwxyz._012345678")
 27 |             != std::string::npos) {
 28 |         SYLAR_LOG_ERROR(g_logger) << "Config invalid name: " << prefix << " : " << node;
 29 |         return;
 30 |     }
 31 |     output.push_back(std::make_pair(prefix, node));
 32 |     if(node.IsMap()) {
 33 |         for(auto it = node.begin();
 34 |                 it != node.end(); ++it) {
 35 |             ListAllMember(prefix.empty() ? it->first.Scalar()
 36 |                     : prefix + "." + it->first.Scalar(), it->second, output);
 37 |         }
 38 |     }
 39 | }
 40 | 
 41 | void Config::LoadFromYaml(const YAML::Node& root) {
 42 |     std::list<std::pair<std::string, const YAML::Node> > all_nodes;
 43 |     ListAllMember("", root, all_nodes);
 44 | 
 45 |     for(auto& i : all_nodes) {
 46 |         std::string key = i.first;
 47 |         if(key.empty()) {
 48 |             continue;
 49 |         }
 50 | 
 51 |         std::transform(key.begin(), key.end(), key.begin(), ::tolower);
 52 |         ConfigVarBase::ptr var = LookupBase(key);
 53 | 
 54 |         if(var) {
 55 |             if(i.second.IsScalar()) {
 56 |                 var->fromString(i.second.Scalar());
 57 |             } else {
 58 |                 std::stringstream ss;
 59 |                 ss << i.second;
 60 |                 var->fromString(ss.str());
 61 |             }
 62 |         }
 63 |     }
 64 | }
 65 | 
 66 | static std::map<std::string, uint64_t> s_file2modifytime;
 67 | static sylar::Mutex s_mutex;
 68 | 
 69 | void Config::LoadFromConfDir(const std::string& path, bool force) {
 70 |     std::string absoulte_path = sylar::EnvMgr::GetInstance()->getAbsolutePath(path);
 71 |     std::vector<std::string> files;
 72 |     FSUtil::ListAllFile(files, absoulte_path, ".yml");
 73 | 
 74 |     for(auto& i : files) {
 75 |         {
 76 |             struct stat st;
 77 |             lstat(i.c_str(), &st);
 78 |             sylar::Mutex::Lock lock(s_mutex);
 79 |             if(!force && s_file2modifytime[i] == (uint64_t)st.st_mtime) {
 80 |                 continue;
 81 |             }
 82 |             s_file2modifytime[i] = st.st_mtime;
 83 |         }
 84 |         try {
 85 |             YAML::Node root = YAML::LoadFile(i);
 86 |             LoadFromYaml(root);
 87 |             SYLAR_LOG_INFO(g_logger) << "LoadConfFile file="
 88 |                 << i << " ok";
 89 |         } catch (...) {
 90 |             SYLAR_LOG_ERROR(g_logger) << "LoadConfFile file="
 91 |                 << i << " failed";
 92 |         }
 93 |     }
 94 | }
 95 | 
 96 | void Config::Visit(std::function<void(ConfigVarBase::ptr)> cb) {
 97 |     RWMutexType::ReadLock lock(GetMutex());
 98 |     ConfigVarMap& m = GetDatas();
 99 |     for(auto it = m.begin();
100 |             it != m.end(); ++it) {
101 |         cb(it->second);
102 |     }
103 | 
104 | }
105 | 
106 | }
107 | 


--------------------------------------------------------------------------------
/sylar/daemon.cc:
--------------------------------------------------------------------------------
 1 | #include "daemon.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/config.h"
 4 | #include <time.h>
 5 | #include <string.h>
 6 | #include <sys/types.h>
 7 | #include <sys/wait.h>
 8 | #include <unistd.h>
 9 | 
10 | namespace sylar {
11 | 
12 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
13 | static sylar::ConfigVar<uint32_t>::ptr g_daemon_restart_interval
14 |     = sylar::Config::Lookup("daemon.restart_interval", (uint32_t)5, "daemon restart interval");
15 | 
16 | std::string ProcessInfo::toString() const {
17 |     std::stringstream ss;
18 |     ss << "[ProcessInfo parent_id=" << parent_id
19 |        << " main_id=" << main_id
20 |        << " parent_start_time=" << sylar::Time2Str(parent_start_time)
21 |        << " main_start_time=" << sylar::Time2Str(main_start_time)
22 |        << " restart_count=" << restart_count << "]";
23 |     return ss.str();
24 | }
25 | 
26 | static int real_start(int argc, char** argv,
27 |                      std::function<int(int argc, char** argv)> main_cb) {
28 |     ProcessInfoMgr::GetInstance()->main_id = getpid();
29 |     ProcessInfoMgr::GetInstance()->main_start_time = time(0);
30 |     return main_cb(argc, argv);
31 | }
32 | 
33 | static int real_daemon(int argc, char** argv,
34 |                      std::function<int(int argc, char** argv)> main_cb) {
35 |     daemon(1, 0);
36 |     ProcessInfoMgr::GetInstance()->parent_id = getpid();
37 |     ProcessInfoMgr::GetInstance()->parent_start_time = time(0);
38 |     while(true) {
39 |         pid_t pid = fork();
40 |         if(pid == 0) {
41 |             //子进程返回
42 |             ProcessInfoMgr::GetInstance()->main_id = getpid();
43 |             ProcessInfoMgr::GetInstance()->main_start_time  = time(0);
44 |             SYLAR_LOG_INFO(g_logger) << "process start pid=" << getpid();
45 |             return real_start(argc, argv, main_cb);
46 |         } else if(pid < 0) {
47 |             SYLAR_LOG_ERROR(g_logger) << "fork fail return=" << pid
48 |                 << " errno=" << errno << " errstr=" << strerror(errno);
49 |             return -1;
50 |         } else {
51 |             //父进程返回
52 |             int status = 0;
53 |             waitpid(pid, &status, 0);
54 |             if(status) {
55 |                 if(status == 9) {
56 |                     SYLAR_LOG_INFO(g_logger) << "killed";
57 |                     break;
58 |                 } else {
59 |                     SYLAR_LOG_ERROR(g_logger) << "child crash pid=" << pid
60 |                         << " status=" << status;
61 |                 }
62 |             } else {
63 |                 SYLAR_LOG_INFO(g_logger) << "child finished pid=" << pid;
64 |                 break;
65 |             }
66 |             ProcessInfoMgr::GetInstance()->restart_count += 1;
67 |             sleep(g_daemon_restart_interval->getValue());
68 |         }
69 |     }
70 |     return 0;
71 | }
72 | 
73 | int start_daemon(int argc, char** argv
74 |                  , std::function<int(int argc, char** argv)> main_cb
75 |                  , bool is_daemon) {
76 |     if(!is_daemon) {
77 |         ProcessInfoMgr::GetInstance()->parent_id = getpid();
78 |         ProcessInfoMgr::GetInstance()->parent_start_time = time(0);
79 |         return real_start(argc, argv, main_cb);
80 |     }
81 |     return real_daemon(argc, argv, main_cb);
82 | }
83 | 
84 | }
85 | 


--------------------------------------------------------------------------------
/sylar/daemon.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_DAEMON_H__
 2 | #define __SYLAR_DAEMON_H__
 3 | 
 4 | #include <unistd.h>
 5 | #include <functional>
 6 | #include "sylar/singleton.h"
 7 | 
 8 | namespace sylar {
 9 | 
10 | struct ProcessInfo {
11 |     /// 父进程id
12 |     pid_t parent_id = 0;
13 |     /// 主进程id
14 |     pid_t main_id = 0;
15 |     /// 父进程启动时间
16 |     uint64_t parent_start_time = 0;
17 |     /// 主进程启动时间
18 |     uint64_t main_start_time = 0;
19 |     /// 主进程重启的次数
20 |     uint32_t restart_count = 0;
21 | 
22 |     std::string toString() const;
23 | };
24 | 
25 | typedef sylar::Singleton<ProcessInfo> ProcessInfoMgr;
26 | 
27 | /**
28 |  * @brief 启动程序可以选择用守护进程的方式
29 |  * @param[in] argc 参数个数
30 |  * @param[in] argv 参数值数组
31 |  * @param[in] main_cb 启动函数
32 |  * @param[in] is_daemon 是否守护进程的方式
33 |  * @return 返回程序的执行结果
34 |  */
35 | int start_daemon(int argc, char** argv
36 |                  , std::function<int(int argc, char** argv)> main_cb
37 |                  , bool is_daemon);
38 | 
39 | }
40 | 
41 | #endif
42 | 


--------------------------------------------------------------------------------
/sylar/ds/cache_status.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_DS_CACHE_STATUS_H__
 2 | #define __SYLAR_DS_CACHE_STATUS_H__
 3 | 
 4 | #include <sstream>
 5 | #include <string>
 6 | #include <stdint.h>
 7 | #include "sylar/util.h"
 8 | 
 9 | namespace sylar {
10 | namespace ds {
11 | 
12 | class CacheStatus {
13 | public:
14 |     CacheStatus() {}
15 | 
16 |     int64_t incGet(int64_t v = 1) { return Atomic::addFetch(m_get, v);}
17 |     int64_t incSet(int64_t v = 1) { return Atomic::addFetch(m_set, v);}
18 |     int64_t incDel(int64_t v = 1) { return Atomic::addFetch(m_del, v);}
19 |     int64_t incTimeout(int64_t v = 1) { return Atomic::addFetch(m_timeout, v);}
20 |     int64_t incPrune(int64_t v = 1) { return Atomic::addFetch(m_prune, v);}
21 |     int64_t incHit(int64_t v = 1) { return Atomic::addFetch(m_hit, v);}
22 | 
23 |     int64_t decGet(int64_t v = 1) { return Atomic::subFetch(m_get, v);}
24 |     int64_t decSet(int64_t v = 1) { return Atomic::subFetch(m_set, v);}
25 |     int64_t decDel(int64_t v = 1) { return Atomic::subFetch(m_del, v);}
26 |     int64_t decTimeout(int64_t v = 1) { return Atomic::subFetch(m_timeout, v);}
27 |     int64_t decPrune(int64_t v = 1) { return Atomic::subFetch(m_prune, v);}
28 |     int64_t decHit(int64_t v = 1) { return Atomic::subFetch(m_hit, v);}
29 | 
30 |     int64_t getGet() const { return m_get;}
31 |     int64_t getSet() const { return m_set;}
32 |     int64_t getDel() const { return m_del;}
33 |     int64_t getTimeout() const { return m_timeout;}
34 |     int64_t getPrune() const { return m_prune;}
35 |     int64_t getHit() const { return m_hit;}
36 | 
37 |     double getHitRate() const {
38 |         return m_get ? (m_hit * 1.0 / m_get) : 0;
39 |     }
40 | 
41 |     void merge(const CacheStatus& o) {
42 |         m_get += o.m_get;
43 |         m_set += o.m_set;
44 |         m_del += o.m_del;
45 |         m_timeout += o.m_timeout;
46 |         m_prune += o.m_prune;
47 |         m_hit += o.m_hit;
48 |     }
49 | 
50 |     std::string toString() const {
51 |         std::stringstream ss;
52 |         ss << "get=" << m_get
53 |            << " set=" << m_set
54 |            << " del=" << m_del
55 |            << " prune=" << m_prune
56 |            << " timeout=" << m_timeout
57 |            << " hit=" << m_hit
58 |            << " hit_rate=" << (getHitRate() * 100.0) << "%";
59 |         return ss.str();
60 |     }
61 | private:
62 |     int64_t m_get = 0;
63 |     int64_t m_set = 0;
64 |     int64_t m_del = 0;
65 |     int64_t m_timeout = 0;
66 |     int64_t m_prune = 0;
67 |     int64_t m_hit = 0;
68 | };
69 | 
70 | }
71 | }
72 | 
73 | #endif
74 | 


--------------------------------------------------------------------------------
/sylar/ds/roaring_bitmap.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_DS_ROARING_BITMAP_H__
 2 | #define __SYLAR_DS_ROARING_BITMAP_H__
 3 | 
 4 | #include <stdint.h>
 5 | #include <string>
 6 | #include <vector>
 7 | #include <memory>
 8 | #include <functional>
 9 | #include "sylar/bytearray.h"
10 | #include "roaring.hh"
11 | 
12 | namespace sylar {
13 | namespace ds {
14 | 
15 | class RoaringBitmap {
16 | public:
17 |     typedef std::shared_ptr<RoaringBitmap> ptr;
18 | 
19 |     RoaringBitmap();
20 |     RoaringBitmap(uint32_t size);
21 |     RoaringBitmap(const RoaringBitmap& b);
22 |     ~RoaringBitmap();
23 | 
24 |     RoaringBitmap& operator=(const RoaringBitmap& b);
25 | 
26 |     std::string toString() const;
27 |     bool get(uint32_t idx) const;
28 |     void set(uint32_t idx, bool v);
29 | 
30 |     void set(uint32_t from, uint32_t size, bool v);
31 |     bool get(uint32_t from, uint32_t size, bool v) const;
32 | 
33 |     RoaringBitmap& operator&=(const RoaringBitmap& b);
34 |     RoaringBitmap& operator|=(const RoaringBitmap& b);
35 |     RoaringBitmap& operator-=(const RoaringBitmap& b);
36 |     RoaringBitmap& operator^=(const RoaringBitmap& b);
37 | 
38 |     RoaringBitmap operator& (const RoaringBitmap& b);
39 |     RoaringBitmap operator| (const RoaringBitmap& b);
40 |     RoaringBitmap operator- (const RoaringBitmap& b);
41 |     RoaringBitmap operator^ (const RoaringBitmap& b);
42 | 
43 |     //RoaringBitmap& operator~();
44 | 
45 |     bool operator== (const RoaringBitmap& b) const;
46 |     bool operator!= (const RoaringBitmap& b) const;
47 | 
48 |     RoaringBitmap::ptr compress() const;
49 |     RoaringBitmap::ptr uncompress() const;
50 | 
51 |     bool any() const;
52 | 
53 |     void listPosAsc(std::vector<uint32_t>& pos);
54 | 
55 |     void foreach(std::function<bool(uint32_t)> cb);
56 |     void rforeach(std::function<bool(uint32_t)> cb);
57 | 
58 |     void writeTo(sylar::ByteArray::ptr ba) const;
59 |     bool readFrom(sylar::ByteArray::ptr ba);
60 | 
61 |     //uncompress to compress
62 |     //uncompress to uncompress
63 |     bool cross(const RoaringBitmap& b) const;
64 | 
65 |     float getCompressRate() const;
66 | 
67 |     uint32_t getCount() const;
68 | public:
69 |     typedef RoaringSetBitForwardIterator iterator;
70 |     typedef RoaringSetBitReverseIterator reverse_iterator;
71 | 
72 |     iterator begin() const { return m_bitmap.begin();}
73 |     iterator end() const { return m_bitmap.end(); }
74 | 
75 |     reverse_iterator rbegin() const { return m_bitmap.rbegin();}
76 |     reverse_iterator rend() const { return m_bitmap.rend();}
77 | 
78 | private:
79 |     RoaringBitmap(const Roaring& b);
80 | private:
81 |     Roaring m_bitmap;
82 | };
83 | 
84 | }
85 | }
86 | 
87 | #endif
88 | 


--------------------------------------------------------------------------------
/sylar/email/email.cc:
--------------------------------------------------------------------------------
 1 | #include "email.h"
 2 | #include <fstream>
 3 | #include <sstream>
 4 | #include "sylar/util.h"
 5 | 
 6 | namespace sylar {
 7 | 
 8 | EMailEntity::ptr EMailEntity::CreateAttach(const std::string& filename) {
 9 |     std::ifstream ifs(filename, std::ios::binary);
10 |     std::string buf;
11 |     buf.resize(1024);
12 |     EMailEntity::ptr entity(new EMailEntity);
13 |     while(!ifs.eof()) {
14 |         ifs.read(&buf[0], buf.size());
15 |         entity->m_content.append(buf.c_str(), ifs.gcount());
16 |     }
17 |     entity->m_content = sylar::base64encode(entity->m_content);
18 |     entity->addHeader("Content-Transfer-Encoding", "base64");
19 |     entity->addHeader("Content-Disposition", "attachment");
20 |     entity->addHeader("Content-Type", "application/octet-stream;name=" + sylar::FSUtil::Basename(filename));
21 |     return entity;
22 | }
23 | 
24 | void EMailEntity::addHeader(const std::string& key, const std::string& val) {
25 |     m_headers[key] = val;
26 | }
27 | 
28 | std::string EMailEntity::getHeader(const std::string& key, const std::string& def) {
29 |     auto it = m_headers.find(key);
30 |     return it == m_headers.end() ? def : it->second;
31 | }
32 | 
33 | std::string EMailEntity::toString() const {
34 |     std::stringstream ss;
35 |     for(auto& i : m_headers) {
36 |         ss << i.first << ": " << i.second << "\r\n";
37 |     }
38 |     ss << m_content << "\r\n";
39 |     return ss.str();
40 | }
41 | 
42 | EMail::ptr EMail::Create(const std::string& from_address, const std::string& from_passwd
43 |                          ,const std::string& title, const std::string& body
44 |                          ,const std::vector<std::string>& to_address
45 |                          ,const std::vector<std::string>& cc_address
46 |                          ,const std::vector<std::string>& bcc_address) {
47 |     EMail::ptr email(new EMail);
48 |     email->setFromEMailAddress(from_address);
49 |     email->setFromEMailPasswd(from_passwd);
50 |     email->setTitle(title);
51 |     email->setBody(body);
52 |     email->setToEMailAddress(to_address);
53 |     email->setCcEMailAddress(cc_address);
54 |     email->setBccEMailAddress(bcc_address);
55 |     return email;
56 | }
57 | 
58 | void EMail::addEntity(EMailEntity::ptr entity) {
59 |     m_entitys.push_back(entity);
60 | }
61 | 
62 | }
63 | 


--------------------------------------------------------------------------------
/sylar/email/email.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_EMAIL_EMAIL_H__
 2 | #define __SYLAR_EMAIL_EMAIL_H__
 3 | 
 4 | #include <memory>
 5 | #include <string>
 6 | #include <vector>
 7 | #include <map>
 8 | 
 9 | namespace sylar {
10 | 
11 | class EMailEntity {
12 | public:
13 |     typedef std::shared_ptr<EMailEntity> ptr;
14 |     static EMailEntity::ptr CreateAttach(const std::string& filename);
15 | 
16 |     void addHeader(const std::string& key, const std::string& val);
17 |     std::string getHeader(const std::string& key, const std::string& def = "");
18 | 
19 |     const std::string& getContent() const { return m_content;}
20 |     void setContent(const std::string& v) { m_content = v;}
21 | 
22 |     std::string toString() const;
23 | private:
24 |     std::map<std::string, std::string> m_headers;
25 |     std::string m_content;
26 | };
27 | 
28 | 
29 | class EMail {
30 | public:
31 |     typedef std::shared_ptr<EMail> ptr;
32 |     static EMail::ptr Create(const std::string& from_address, const std::string& from_passwd
33 |                             ,const std::string& title, const std::string& body
34 |                             ,const std::vector<std::string>& to_address
35 |                             ,const std::vector<std::string>& cc_address = {}
36 |                             ,const std::vector<std::string>& bcc_address = {});
37 | 
38 |     const std::string& getFromEMailAddress() const { return m_fromEMailAddress;}
39 |     const std::string& getFromEMailPasswd() const { return m_fromEMailPasswd;}
40 |     const std::string& getTitle() const { return m_title;}
41 |     const std::string& getBody() const { return m_body;}
42 | 
43 |     void setFromEMailAddress(const std::string& v) { m_fromEMailAddress = v;}
44 |     void setFromEMailPasswd(const std::string& v) { m_fromEMailPasswd = v;}
45 |     void setTitle(const std::string& v) { m_title = v;}
46 |     void setBody(const std::string& v) { m_body = v;}
47 | 
48 |     const std::vector<std::string>& getToEMailAddress() const { return m_toEMailAddress;}
49 |     const std::vector<std::string>& getCcEMailAddress() const { return m_ccEMailAddress;}
50 |     const std::vector<std::string>& getBccEMailAddress() const { return m_bccEMailAddress;}
51 | 
52 |     void setToEMailAddress(const std::vector<std::string>& v) { m_toEMailAddress = v;}
53 |     void setCcEMailAddress(const std::vector<std::string>& v) { m_ccEMailAddress = v;}
54 |     void setBccEMailAddress(const std::vector<std::string>& v) { m_bccEMailAddress = v;}
55 | 
56 |     void addEntity(EMailEntity::ptr entity);
57 |     const std::vector<EMailEntity::ptr>& getEntitys() const { return m_entitys;}
58 | private:
59 |     std::string m_fromEMailAddress;
60 |     std::string m_fromEMailPasswd;
61 |     std::string m_title;
62 |     std::string m_body;
63 |     std::vector<std::string> m_toEMailAddress;
64 |     std::vector<std::string> m_ccEMailAddress;
65 |     std::vector<std::string> m_bccEMailAddress;
66 |     std::vector<EMailEntity::ptr> m_entitys;
67 | };
68 | 
69 | }
70 | 
71 | #endif
72 | 


--------------------------------------------------------------------------------
/sylar/email/smtp.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_EMAIL_SMTP_H__
 2 | #define __SYLAR_EMAIL_SMTP_H__
 3 | 
 4 | #include "sylar/streams/socket_stream.h"
 5 | #include "email.h"
 6 | #include <sstream>
 7 | 
 8 | namespace sylar {
 9 | 
10 | struct SmtpResult {
11 |     typedef std::shared_ptr<SmtpResult> ptr;
12 |     enum Result {
13 |         OK = 0,
14 |         IO_ERROR = -1
15 |     };
16 | 
17 |     SmtpResult(int r, const std::string& m)
18 |         :result(r)
19 |         ,msg(m) {
20 |     }
21 | 
22 |     int result;
23 |     std::string msg;
24 | };
25 | 
26 | class SmtpClient : public sylar::SocketStream {
27 | public:
28 |     typedef std::shared_ptr<SmtpClient> ptr;
29 |     static SmtpClient::ptr Create(const std::string& host, uint32_t port, bool ssl= false);
30 |     SmtpResult::ptr send(EMail::ptr email, int64_t timeout_ms = 1000, bool debug = false);
31 | 
32 |     std::string getDebugInfo();
33 | private:
34 |     SmtpResult::ptr doCmd(const std::string& cmd, bool debug);
35 | private:
36 |     SmtpClient(Socket::ptr sock);
37 | private:
38 |     std::string m_host;
39 |     std::stringstream m_ss;
40 |     bool m_authed = false;
41 | };
42 | 
43 | }
44 | 
45 | #endif
46 | 


--------------------------------------------------------------------------------
/sylar/endian.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file endian.h
 3 |  * @brief 字节序操作函数(大端/小端)
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-06-01
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef __SYLAR_ENDIAN_H__
10 | #define __SYLAR_ENDIAN_H__
11 | 
12 | #define SYLAR_LITTLE_ENDIAN 1
13 | #define SYLAR_BIG_ENDIAN 2
14 | 
15 | #include <byteswap.h>
16 | #include <stdint.h>
17 | 
18 | namespace sylar {
19 | 
20 | /**
21 |  * @brief 8字节类型的字节序转化
22 |  */
23 | template<class T>
24 | typename std::enable_if<sizeof(T) == sizeof(uint64_t), T>::type
25 | byteswap(T value) {
26 |     return (T)bswap_64((uint64_t)value);
27 | }
28 | 
29 | /**
30 |  * @brief 4字节类型的字节序转化
31 |  */
32 | template<class T>
33 | typename std::enable_if<sizeof(T) == sizeof(uint32_t), T>::type
34 | byteswap(T value) {
35 |     return (T)bswap_32((uint32_t)value);
36 | }
37 | 
38 | /**
39 |  * @brief 2字节类型的字节序转化
40 |  */
41 | template<class T>
42 | typename std::enable_if<sizeof(T) == sizeof(uint16_t), T>::type
43 | byteswap(T value) {
44 |     return (T)bswap_16((uint16_t)value);
45 | }
46 | 
47 | #if BYTE_ORDER == BIG_ENDIAN
48 | #define SYLAR_BYTE_ORDER SYLAR_BIG_ENDIAN
49 | #else
50 | #define SYLAR_BYTE_ORDER SYLAR_LITTLE_ENDIAN
51 | #endif
52 | 
53 | #if SYLAR_BYTE_ORDER == SYLAR_BIG_ENDIAN
54 | 
55 | /**
56 |  * @brief 只在小端机器上执行byteswap, 在大端机器上什么都不做
57 |  */
58 | template<class T>
59 | T byteswapOnLittleEndian(T t) {
60 |     return t;
61 | }
62 | 
63 | /**
64 |  * @brief 只在大端机器上执行byteswap, 在小端机器上什么都不做
65 |  */
66 | template<class T>
67 | T byteswapOnBigEndian(T t) {
68 |     return byteswap(t);
69 | }
70 | #else
71 | 
72 | /**
73 |  * @brief 只在小端机器上执行byteswap, 在大端机器上什么都不做
74 |  */
75 | template<class T>
76 | T byteswapOnLittleEndian(T t) {
77 |     return byteswap(t);
78 | }
79 | 
80 | /**
81 |  * @brief 只在大端机器上执行byteswap, 在小端机器上什么都不做
82 |  */
83 | template<class T>
84 | T byteswapOnBigEndian(T t) {
85 |     return t;
86 | }
87 | #endif
88 | 
89 | }
90 | 
91 | #endif
92 | 


--------------------------------------------------------------------------------
/sylar/env.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ENV_H__
 2 | #define __SYLAR_ENV_H__
 3 | 
 4 | #include "sylar/singleton.h"
 5 | #include "sylar/thread.h"
 6 | #include <map>
 7 | #include <vector>
 8 | 
 9 | namespace sylar {
10 | 
11 | class Env {
12 | public:
13 |     typedef RWMutex RWMutexType;
14 |     bool init(int argc, char** argv);
15 | 
16 |     void add(const std::string& key, const std::string& val);
17 |     bool has(const std::string& key);
18 |     void del(const std::string& key);
19 |     std::string get(const std::string& key, const std::string& default_value = "");
20 | 
21 |     void addHelp(const std::string& key, const std::string& desc);
22 |     void removeHelp(const std::string& key);
23 |     void printHelp();
24 | 
25 |     const std::string& getExe() const { return m_exe;}
26 |     const std::string& getCwd() const { return m_cwd;}
27 | 
28 |     bool setEnv(const std::string& key, const std::string& val);
29 |     std::string getEnv(const std::string& key, const std::string& default_value = "");
30 | 
31 |     std::string getAbsolutePath(const std::string& path) const;
32 |     std::string getAbsoluteWorkPath(const std::string& path) const;
33 |     std::string getConfigPath();
34 | private:
35 |     RWMutexType m_mutex;
36 |     std::map<std::string, std::string> m_args;
37 |     std::vector<std::pair<std::string, std::string> > m_helps;
38 | 
39 |     std::string m_program;
40 |     std::string m_exe;
41 |     std::string m_cwd;
42 | };
43 | 
44 | typedef sylar::Singleton<Env> EnvMgr;
45 | 
46 | }
47 | 
48 | #endif
49 | 


--------------------------------------------------------------------------------
/sylar/fd_manager.cc:
--------------------------------------------------------------------------------
  1 | #include "fd_manager.h"
  2 | #include "hook.h"
  3 | #include <sys/types.h>
  4 | #include <sys/stat.h>
  5 | #include <unistd.h>
  6 | 
  7 | namespace sylar {
  8 | 
  9 | FdCtx::FdCtx(int fd)
 10 |     :m_isInit(false)
 11 |     ,m_isSocket(false)
 12 |     ,m_sysNonblock(false)
 13 |     ,m_userNonblock(false)
 14 |     ,m_isClosed(false)
 15 |     ,m_fd(fd)
 16 |     ,m_recvTimeout(-1)
 17 |     ,m_sendTimeout(-1) {
 18 |     init();
 19 | }
 20 | 
 21 | FdCtx::~FdCtx() {
 22 | }
 23 | 
 24 | bool FdCtx::init() {
 25 |     if(m_isInit) {
 26 |         return true;
 27 |     }
 28 |     m_recvTimeout = -1;
 29 |     m_sendTimeout = -1;
 30 | 
 31 |     struct stat fd_stat;
 32 |     if(-1 == fstat(m_fd, &fd_stat)) {
 33 |         m_isInit = false;
 34 |         m_isSocket = false;
 35 |     } else {
 36 |         m_isInit = true;
 37 |         m_isSocket = S_ISSOCK(fd_stat.st_mode);
 38 |     }
 39 | 
 40 |     if(m_isSocket) {
 41 |         int flags = fcntl_f(m_fd, F_GETFL, 0);
 42 |         if(!(flags & O_NONBLOCK)) {
 43 |             fcntl_f(m_fd, F_SETFL, flags | O_NONBLOCK);
 44 |         }
 45 |         m_sysNonblock = true;
 46 |     } else {
 47 |         m_sysNonblock = false;
 48 |     }
 49 | 
 50 |     m_userNonblock = false;
 51 |     m_isClosed = false;
 52 |     return m_isInit;
 53 | }
 54 | 
 55 | void FdCtx::setTimeout(int type, uint64_t v) {
 56 |     if(type == SO_RCVTIMEO) {
 57 |         m_recvTimeout = v;
 58 |     } else {
 59 |         m_sendTimeout = v;
 60 |     }
 61 | }
 62 | 
 63 | uint64_t FdCtx::getTimeout(int type) {
 64 |     if(type == SO_RCVTIMEO) {
 65 |         return m_recvTimeout;
 66 |     } else {
 67 |         return m_sendTimeout;
 68 |     }
 69 | }
 70 | 
 71 | FdManager::FdManager() {
 72 |     m_datas.resize(64);
 73 | }
 74 | 
 75 | FdCtx::ptr FdManager::get(int fd, bool auto_create) {
 76 |     if(fd == -1) {
 77 |         return nullptr;
 78 |     }
 79 |     RWMutexType::ReadLock lock(m_mutex);
 80 |     if((int)m_datas.size() <= fd) {
 81 |         if(auto_create == false) {
 82 |             return nullptr;
 83 |         }
 84 |     } else {
 85 |         if(m_datas[fd] || !auto_create) {
 86 |             return m_datas[fd];
 87 |         }
 88 |     }
 89 |     lock.unlock();
 90 | 
 91 |     RWMutexType::WriteLock lock2(m_mutex);
 92 |     FdCtx::ptr ctx(new FdCtx(fd));
 93 |     if(fd >= (int)m_datas.size()) {
 94 |         m_datas.resize(fd * 1.5);
 95 |     }
 96 |     m_datas[fd] = ctx;
 97 |     return ctx;
 98 | }
 99 | 
100 | void FdManager::del(int fd) {
101 |     RWMutexType::WriteLock lock(m_mutex);
102 |     if((int)m_datas.size() <= fd) {
103 |         return;
104 |     }
105 |     m_datas[fd].reset();
106 | }
107 | 
108 | }
109 | 


--------------------------------------------------------------------------------
/sylar/fd_manager.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file fd_manager.h
  3 |  * @brief 文件句柄管理类
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-05-30
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | #ifndef __FD_MANAGER_H__
 10 | #define __FD_MANAGER_H__
 11 | 
 12 | #include <memory>
 13 | #include <vector>
 14 | #include "thread.h"
 15 | #include "singleton.h"
 16 | 
 17 | namespace sylar {
 18 | 
 19 | /**
 20 |  * @brief 文件句柄上下文类
 21 |  * @details 管理文件句柄类型(是否socket)
 22 |  *          是否阻塞,是否关闭,读/写超时时间
 23 |  */
 24 | class FdCtx : public std::enable_shared_from_this<FdCtx> {
 25 | public:
 26 |     typedef std::shared_ptr<FdCtx> ptr;
 27 |     /**
 28 |      * @brief 通过文件句柄构造FdCtx
 29 |      */
 30 |     FdCtx(int fd);
 31 |     /**
 32 |      * @brief 析构函数
 33 |      */
 34 |     ~FdCtx();
 35 | 
 36 |     /**
 37 |      * @brief 是否初始化完成
 38 |      */
 39 |     bool isInit() const { return m_isInit;}
 40 | 
 41 |     /**
 42 |      * @brief 是否socket
 43 |      */
 44 |     bool isSocket() const { return m_isSocket;}
 45 | 
 46 |     /**
 47 |      * @brief 是否已关闭
 48 |      */
 49 |     bool isClose() const { return m_isClosed;}
 50 | 
 51 |     /**
 52 |      * @brief 设置用户主动设置非阻塞
 53 |      * @param[in] v 是否阻塞
 54 |      */
 55 |     void setUserNonblock(bool v) { m_userNonblock = v;}
 56 | 
 57 |     /**
 58 |      * @brief 获取是否用户主动设置的非阻塞
 59 |      */
 60 |     bool getUserNonblock() const { return m_userNonblock;}
 61 | 
 62 |     /**
 63 |      * @brief 设置系统非阻塞
 64 |      * @param[in] v 是否阻塞
 65 |      */
 66 |     void setSysNonblock(bool v) { m_sysNonblock = v;}
 67 | 
 68 |     /**
 69 |      * @brief 获取系统非阻塞
 70 |      */
 71 |     bool getSysNonblock() const { return m_sysNonblock;}
 72 | 
 73 |     /**
 74 |      * @brief 设置超时时间
 75 |      * @param[in] type 类型SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时)
 76 |      * @param[in] v 时间毫秒
 77 |      */
 78 |     void setTimeout(int type, uint64_t v);
 79 | 
 80 |     /**
 81 |      * @brief 获取超时时间
 82 |      * @param[in] type 类型SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时)
 83 |      * @return 超时时间毫秒
 84 |      */
 85 |     uint64_t getTimeout(int type);
 86 | private:
 87 |     /**
 88 |      * @brief 初始化
 89 |      */
 90 |     bool init();
 91 | private:
 92 |     /// 是否初始化
 93 |     bool m_isInit: 1;
 94 |     /// 是否socket
 95 |     bool m_isSocket: 1;
 96 |     /// 是否hook非阻塞
 97 |     bool m_sysNonblock: 1;
 98 |     /// 是否用户主动设置非阻塞
 99 |     bool m_userNonblock: 1;
100 |     /// 是否关闭
101 |     bool m_isClosed: 1;
102 |     /// 文件句柄
103 |     int m_fd;
104 |     /// 读超时时间毫秒
105 |     uint64_t m_recvTimeout;
106 |     /// 写超时时间毫秒
107 |     uint64_t m_sendTimeout;
108 | };
109 | 
110 | /**
111 |  * @brief 文件句柄管理类
112 |  */
113 | class FdManager {
114 | public:
115 |     typedef RWMutex RWMutexType;
116 |     /**
117 |      * @brief 无参构造函数
118 |      */
119 |     FdManager();
120 | 
121 |     /**
122 |      * @brief 获取/创建文件句柄类FdCtx
123 |      * @param[in] fd 文件句柄
124 |      * @param[in] auto_create 是否自动创建
125 |      * @return 返回对应文件句柄类FdCtx::ptr
126 |      */
127 |     FdCtx::ptr get(int fd, bool auto_create = false);
128 | 
129 |     /**
130 |      * @brief 删除文件句柄类
131 |      * @param[in] fd 文件句柄
132 |      */
133 |     void del(int fd);
134 | private:
135 |     /// 读写锁
136 |     RWMutexType m_mutex;
137 |     /// 文件句柄集合
138 |     std::vector<FdCtx::ptr> m_datas;
139 | };
140 | 
141 | /// 文件句柄单例
142 | typedef Singleton<FdManager> FdMgr;
143 | 
144 | }
145 | 
146 | #endif
147 | 


--------------------------------------------------------------------------------
/sylar/fiber.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file fiber.h
  3 |  * @brief 协程封装
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-05-24
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | #ifndef __SYLAR_FIBER_H__
 10 | #define __SYLAR_FIBER_H__
 11 | 
 12 | #include <memory>
 13 | #include <functional>
 14 | #include <ucontext.h>
 15 | 
 16 | namespace sylar {
 17 | 
 18 | class Scheduler;
 19 | 
 20 | /**
 21 |  * @brief 协程类
 22 |  */
 23 | class Fiber : public std::enable_shared_from_this<Fiber> {
 24 | friend class Scheduler;
 25 | public:
 26 |     typedef std::shared_ptr<Fiber> ptr;
 27 | 
 28 |     /**
 29 |      * @brief 协程状态
 30 |      */
 31 |     enum State {
 32 |         /// 初始化状态
 33 |         INIT,
 34 |         /// 暂停状态
 35 |         HOLD,
 36 |         /// 执行中状态
 37 |         EXEC,
 38 |         /// 结束状态
 39 |         TERM,
 40 |         /// 可执行状态
 41 |         READY,
 42 |         /// 异常状态
 43 |         EXCEPT
 44 |     };
 45 | private:
 46 |     /**
 47 |      * @brief 无参构造函数
 48 |      * @attention 每个线程第一个协程的构造
 49 |      */
 50 |     Fiber();
 51 | 
 52 | public:
 53 |     /**
 54 |      * @brief 构造函数
 55 |      * @param[in] cb 协程执行的函数
 56 |      * @param[in] stacksize 协程栈大小
 57 |      * @param[in] use_caller 是否在MainFiber上调度
 58 |      */
 59 |     Fiber(std::function<void()> cb, size_t stacksize = 0, bool use_caller = false);
 60 | 
 61 |     /**
 62 |      * @brief 析构函数
 63 |      */
 64 |     ~Fiber();
 65 | 
 66 |     /**
 67 |      * @brief 重置协程执行函数,并设置状态
 68 |      * @pre getState() 为 INIT, TERM, EXCEPT
 69 |      * @post getState() = INIT
 70 |      */
 71 |     void reset(std::function<void()> cb);
 72 | 
 73 |     /**
 74 |      * @brief 将当前协程切换到运行状态
 75 |      * @pre getState() != EXEC
 76 |      * @post getState() = EXEC
 77 |      */
 78 |     void swapIn();
 79 | 
 80 |     /**
 81 |      * @brief 将当前协程切换到后台
 82 |      */
 83 |     void swapOut();
 84 | 
 85 |     /**
 86 |      * @brief 将当前线程切换到执行状态
 87 |      * @pre 执行的为当前线程的主协程
 88 |      */
 89 |     void call();
 90 | 
 91 |     /**
 92 |      * @brief 将当前线程切换到后台
 93 |      * @pre 执行的为该协程
 94 |      * @post 返回到线程的主协程
 95 |      */
 96 |     void back();
 97 | 
 98 |     /**
 99 |      * @brief 返回协程id
100 |      */
101 |     uint64_t getId() const { return m_id;}
102 | 
103 |     /**
104 |      * @brief 返回协程状态
105 |      */
106 |     State getState() const { return m_state;}
107 | public:
108 | 
109 |     /**
110 |      * @brief 设置当前线程的运行协程
111 |      * @param[in] f 运行协程
112 |      */
113 |     static void SetThis(Fiber* f);
114 | 
115 |     /**
116 |      * @brief 返回当前所在的协程
117 |      */
118 |     static Fiber::ptr GetThis();
119 | 
120 |     /**
121 |      * @brief 将当前协程切换到后台,并设置为READY状态
122 |      * @post getState() = READY
123 |      */
124 |     static void YieldToReady();
125 | 
126 |     /**
127 |      * @brief 将当前协程切换到后台,并设置为HOLD状态
128 |      * @post getState() = HOLD
129 |      */
130 |     static void YieldToHold();
131 | 
132 |     /**
133 |      * @brief 返回当前协程的总数量
134 |      */
135 |     static uint64_t TotalFibers();
136 | 
137 |     /**
138 |      * @brief 协程执行函数
139 |      * @post 执行完成返回到线程主协程
140 |      */
141 |     static void MainFunc();
142 | 
143 |     /**
144 |      * @brief 协程执行函数
145 |      * @post 执行完成返回到线程调度协程
146 |      */
147 |     static void CallerMainFunc();
148 | 
149 |     /**
150 |      * @brief 获取当前协程的id
151 |      */
152 |     static uint64_t GetFiberId();
153 | private:
154 |     /// 协程id
155 |     uint64_t m_id = 0;
156 |     /// 协程运行栈大小
157 |     uint32_t m_stacksize = 0;
158 |     /// 协程状态
159 |     State m_state = INIT;
160 |     /// 协程上下文
161 |     ucontext_t m_ctx;
162 |     /// 协程运行栈指针
163 |     void* m_stack = nullptr;
164 |     /// 协程运行函数
165 |     std::function<void()> m_cb;
166 | };
167 | 
168 | }
169 | 
170 | #endif
171 | 


--------------------------------------------------------------------------------
/sylar/hook.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file hook.h
  3 |  * @brief hook函数封装
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-06-02
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | 
 10 | #ifndef __SYLAR_HOOK_H__
 11 | #define __SYLAR_HOOK_H__
 12 | 
 13 | #include <fcntl.h>
 14 | #include <sys/ioctl.h>
 15 | #include <sys/types.h>
 16 | #include <sys/socket.h>
 17 | #include <stdint.h>
 18 | #include <time.h>
 19 | #include <unistd.h>
 20 | 
 21 | namespace sylar {
 22 |     /**
 23 |      * @brief 当前线程是否hook
 24 |      */
 25 |     bool is_hook_enable();
 26 |     /**
 27 |      * @brief 设置当前线程的hook状态
 28 |      */
 29 |     void set_hook_enable(bool flag);
 30 | }
 31 | 
 32 | extern "C" {
 33 | 
 34 | //sleep
 35 | typedef unsigned int (*sleep_fun)(unsigned int seconds);
 36 | extern sleep_fun sleep_f;
 37 | 
 38 | typedef int (*usleep_fun)(useconds_t usec);
 39 | extern usleep_fun usleep_f;
 40 | 
 41 | typedef int (*nanosleep_fun)(const struct timespec *req, struct timespec *rem);
 42 | extern nanosleep_fun nanosleep_f;
 43 | 
 44 | //socket
 45 | typedef int (*socket_fun)(int domain, int type, int protocol);
 46 | extern socket_fun socket_f;
 47 | 
 48 | typedef int (*connect_fun)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 49 | extern connect_fun connect_f;
 50 | 
 51 | typedef int (*accept_fun)(int s, struct sockaddr *addr, socklen_t *addrlen);
 52 | extern accept_fun accept_f;
 53 | 
 54 | //read
 55 | typedef ssize_t (*read_fun)(int fd, void *buf, size_t count);
 56 | extern read_fun read_f;
 57 | 
 58 | typedef ssize_t (*readv_fun)(int fd, const struct iovec *iov, int iovcnt);
 59 | extern readv_fun readv_f;
 60 | 
 61 | typedef ssize_t (*recv_fun)(int sockfd, void *buf, size_t len, int flags);
 62 | extern recv_fun recv_f;
 63 | 
 64 | typedef ssize_t (*recvfrom_fun)(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
 65 | extern recvfrom_fun recvfrom_f;
 66 | 
 67 | typedef ssize_t (*recvmsg_fun)(int sockfd, struct msghdr *msg, int flags);
 68 | extern recvmsg_fun recvmsg_f;
 69 | 
 70 | //write
 71 | typedef ssize_t (*write_fun)(int fd, const void *buf, size_t count);
 72 | extern write_fun write_f;
 73 | 
 74 | typedef ssize_t (*writev_fun)(int fd, const struct iovec *iov, int iovcnt);
 75 | extern writev_fun writev_f;
 76 | 
 77 | typedef ssize_t (*send_fun)(int s, const void *msg, size_t len, int flags);
 78 | extern send_fun send_f;
 79 | 
 80 | typedef ssize_t (*sendto_fun)(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
 81 | extern sendto_fun sendto_f;
 82 | 
 83 | typedef ssize_t (*sendmsg_fun)(int s, const struct msghdr *msg, int flags);
 84 | extern sendmsg_fun sendmsg_f;
 85 | 
 86 | typedef int (*close_fun)(int fd);
 87 | extern close_fun close_f;
 88 | 
 89 | //
 90 | typedef int (*fcntl_fun)(int fd, int cmd, ... /* arg */ );
 91 | extern fcntl_fun fcntl_f;
 92 | 
 93 | typedef int (*ioctl_fun)(int d, unsigned long int request, ...);
 94 | extern ioctl_fun ioctl_f;
 95 | 
 96 | typedef int (*getsockopt_fun)(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
 97 | extern getsockopt_fun getsockopt_f;
 98 | 
 99 | typedef int (*setsockopt_fun)(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
100 | extern setsockopt_fun setsockopt_f;
101 | 
102 | extern int connect_with_timeout(int fd, const struct sockaddr* addr, socklen_t addrlen, uint64_t timeout_ms);
103 | 
104 | }
105 | 
106 | #endif
107 | 


--------------------------------------------------------------------------------
/sylar/http/http11_common.h:
--------------------------------------------------------------------------------
 1 | #ifndef _http11_common_h
 2 | #define _http11_common_h
 3 | 
 4 | #include <sys/types.h>
 5 | 
 6 | typedef void (*element_cb)(void *data, const char *at, size_t length);
 7 | typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
 8 | 
 9 | #endif
10 | 


--------------------------------------------------------------------------------
/sylar/http/http11_parser.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file bytearray.h
 3 |  * @brief 二进制数组(序列化/反序列化)
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-06-03
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef http11_parser_h
10 | #define http11_parser_h
11 | 
12 | #include "http11_common.h"
13 | 
14 | typedef struct http_parser { 
15 |   int cs;
16 |   size_t body_start;
17 |   int content_len;
18 |   size_t nread;
19 |   size_t mark;
20 |   size_t field_start;
21 |   size_t field_len;
22 |   size_t query_start;
23 |   int xml_sent;
24 |   int json_sent;
25 | 
26 |   void *data;
27 | 
28 |   int uri_relaxed;
29 |   field_cb http_field;
30 |   element_cb request_method;
31 |   element_cb request_uri;
32 |   element_cb fragment;
33 |   element_cb request_path;
34 |   element_cb query_string;
35 |   element_cb http_version;
36 |   element_cb header_done;
37 |   
38 | } http_parser;
39 | 
40 | int http_parser_init(http_parser *parser);
41 | int http_parser_finish(http_parser *parser);
42 | size_t http_parser_execute(http_parser *parser, const char *data, size_t len, size_t off);
43 | int http_parser_has_error(http_parser *parser);
44 | int http_parser_is_finished(http_parser *parser);
45 | 
46 | #define http_parser_nread(parser) (parser)->nread 
47 | 
48 | #endif
49 | 


--------------------------------------------------------------------------------
/sylar/http/http_server.cc:
--------------------------------------------------------------------------------
 1 | #include "http_server.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/http/servlets/config_servlet.h"
 4 | #include "sylar/http/servlets/status_servlet.h"
 5 | 
 6 | namespace sylar {
 7 | namespace http {
 8 | 
 9 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
10 | 
11 | HttpServer::HttpServer(bool keepalive
12 |                ,sylar::IOManager* worker
13 |                ,sylar::IOManager* io_worker
14 |                ,sylar::IOManager* accept_worker)
15 |     :TcpServer(worker, io_worker, accept_worker)
16 |     ,m_isKeepalive(keepalive) {
17 |     m_dispatch.reset(new ServletDispatch);
18 | 
19 |     m_type = "http";
20 |     m_dispatch->addServlet("/_/status", Servlet::ptr(new StatusServlet));
21 |     m_dispatch->addServlet("/_/config", Servlet::ptr(new ConfigServlet));
22 | }
23 | 
24 | void HttpServer::setName(const std::string& v) {
25 |     TcpServer::setName(v);
26 |     m_dispatch->setDefault(std::make_shared<NotFoundServlet>(v));
27 | }
28 | 
29 | void HttpServer::handleClient(Socket::ptr client) {
30 |     SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client;
31 |     HttpSession::ptr session(new HttpSession(client));
32 |     do {
33 |         auto req = session->recvRequest();
34 |         if(!req) {
35 |             SYLAR_LOG_DEBUG(g_logger) << "recv http request fail, errno="
36 |                 << errno << " errstr=" << strerror(errno)
37 |                 << " cliet:" << *client << " keep_alive=" << m_isKeepalive;
38 |             break;
39 |         }
40 | 
41 |         HttpResponse::ptr rsp(new HttpResponse(req->getVersion()
42 |                             ,req->isClose() || !m_isKeepalive));
43 |         rsp->setHeader("Server", getName());
44 |         m_dispatch->handle(req, rsp, session);
45 |         session->sendResponse(rsp);
46 | 
47 |         if(!m_isKeepalive || req->isClose()) {
48 |             break;
49 |         }
50 |     } while(true);
51 |     session->close();
52 | }
53 | 
54 | }
55 | }
56 | 


--------------------------------------------------------------------------------
/sylar/http/http_server.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file http_server.h
 3 |  * @brief HTTP服务器封装
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-06-09
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | 
10 | #ifndef __SYLAR_HTTP_HTTP_SERVER_H__
11 | #define __SYLAR_HTTP_HTTP_SERVER_H__
12 | 
13 | #include "sylar/tcp_server.h"
14 | #include "http_session.h"
15 | #include "servlet.h"
16 | 
17 | namespace sylar {
18 | namespace http {
19 | 
20 | /**
21 |  * @brief HTTP服务器类
22 |  */
23 | class HttpServer : public TcpServer {
24 | public:
25 |     /// 智能指针类型
26 |     typedef std::shared_ptr<HttpServer> ptr;
27 | 
28 |     /**
29 |      * @brief 构造函数
30 |      * @param[in] keepalive 是否长连接
31 |      * @param[in] worker 工作调度器
32 |      * @param[in] accept_worker 接收连接调度器
33 |      */
34 |     HttpServer(bool keepalive = false
35 |                ,sylar::IOManager* worker = sylar::IOManager::GetThis()
36 |                ,sylar::IOManager* io_worker = sylar::IOManager::GetThis()
37 |                ,sylar::IOManager* accept_worker = sylar::IOManager::GetThis());
38 | 
39 |     /**
40 |      * @brief 获取ServletDispatch
41 |      */
42 |     ServletDispatch::ptr getServletDispatch() const { return m_dispatch;}
43 | 
44 |     /**
45 |      * @brief 设置ServletDispatch
46 |      */
47 |     void setServletDispatch(ServletDispatch::ptr v) { m_dispatch = v;}
48 | 
49 |     virtual void setName(const std::string& v) override;
50 | protected:
51 |     virtual void handleClient(Socket::ptr client) override;
52 | private:
53 |     /// 是否支持长连接
54 |     bool m_isKeepalive;
55 |     /// Servlet分发器
56 |     ServletDispatch::ptr m_dispatch;
57 | };
58 | 
59 | }
60 | }
61 | 
62 | #endif
63 | 


--------------------------------------------------------------------------------
/sylar/http/http_session.cc:
--------------------------------------------------------------------------------
 1 | #include "http_session.h"
 2 | #include "http_parser.h"
 3 | 
 4 | namespace sylar {
 5 | namespace http {
 6 | 
 7 | HttpSession::HttpSession(Socket::ptr sock, bool owner)
 8 |     :SocketStream(sock, owner) {
 9 | }
10 | 
11 | HttpRequest::ptr HttpSession::recvRequest() {
12 |     HttpRequestParser::ptr parser(new HttpRequestParser);
13 |     uint64_t buff_size = HttpRequestParser::GetHttpRequestBufferSize();
14 |     //uint64_t buff_size = 100;
15 |     std::shared_ptr<char> buffer(
16 |             new char[buff_size], [](char* ptr){
17 |                 delete[] ptr;
18 |             });
19 |     char* data = buffer.get();
20 |     int offset = 0;
21 |     do {
22 |         int len = read(data + offset, buff_size - offset);
23 |         if(len <= 0) {
24 |             close();
25 |             return nullptr;
26 |         }
27 |         len += offset;
28 |         size_t nparse = parser->execute(data, len);
29 |         if(parser->hasError()) {
30 |             close();
31 |             return nullptr;
32 |         }
33 |         offset = len - nparse;
34 |         if(offset == (int)buff_size) {
35 |             close();
36 |             return nullptr;
37 |         }
38 |         if(parser->isFinished()) {
39 |             break;
40 |         }
41 |     } while(true);
42 |     int64_t length = parser->getContentLength();
43 |     if(length > 0) {
44 |         std::string body;
45 |         body.resize(length);
46 | 
47 |         int len = 0;
48 |         if(length >= offset) {
49 |             memcpy(&body[0], data, offset);
50 |             len = offset;
51 |         } else {
52 |             memcpy(&body[0], data, length);
53 |             len = length;
54 |         }
55 |         length -= offset;
56 |         if(length > 0) {
57 |             if(readFixSize(&body[len], length) <= 0) {
58 |                 close();
59 |                 return nullptr;
60 |             }
61 |         }
62 |         parser->getData()->setBody(body);
63 |     }
64 | 
65 |     parser->getData()->init();
66 |     return parser->getData();
67 | }
68 | 
69 | int HttpSession::sendResponse(HttpResponse::ptr rsp) {
70 |     std::stringstream ss;
71 |     ss << *rsp;
72 |     std::string data = ss.str();
73 |     return writeFixSize(data.c_str(), data.size());
74 | }
75 | 
76 | }
77 | }
78 | 


--------------------------------------------------------------------------------
/sylar/http/http_session.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file http_session.h
 3 |  * @brief HTTPSession封装
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-06-07
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | 
10 | #ifndef __SYLAR_HTTP_SESSION_H__
11 | #define __SYLAR_HTTP_SESSION_H__
12 | 
13 | #include "sylar/streams/socket_stream.h"
14 | #include "http.h"
15 | 
16 | namespace sylar {
17 | namespace http {
18 | 
19 | /**
20 |  * @brief HTTPSession封装
21 |  */
22 | class HttpSession : public SocketStream {
23 | public:
24 |     /// 智能指针类型定义
25 |     typedef std::shared_ptr<HttpSession> ptr;
26 | 
27 |     /**
28 |      * @brief 构造函数
29 |      * @param[in] sock Socket类型
30 |      * @param[in] owner 是否托管
31 |      */
32 |     HttpSession(Socket::ptr sock, bool owner = true);
33 | 
34 |     /**
35 |      * @brief 接收HTTP请求
36 |      */
37 |     HttpRequest::ptr recvRequest();
38 | 
39 |     /**
40 |      * @brief 发送HTTP响应
41 |      * @param[in] rsp HTTP响应
42 |      * @return >0 发送成功
43 |      *         =0 对方关闭
44 |      *         <0 Socket异常
45 |      */
46 |     int sendResponse(HttpResponse::ptr rsp);
47 | };
48 | 
49 | }
50 | }
51 | 
52 | #endif
53 | 


--------------------------------------------------------------------------------
/sylar/http/httpclient_parser.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  *
 3 |  * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
 4 |  * All rights reserved.
 5 |  * 
 6 |  * Redistribution and use in source and binary forms, with or without
 7 |  * modification, are permitted provided that the following conditions are
 8 |  * met:
 9 |  * 
10 |  *     * Redistributions of source code must retain the above copyright
11 |  *       notice, this list of conditions and the following disclaimer.
12 |  * 
13 |  *     * Redistributions in binary form must reproduce the above copyright
14 |  *       notice, this list of conditions and the following disclaimer in the
15 |  *       documentation and/or other materials provided with the distribution.
16 |  * 
17 |  *     * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
18 |  *       of its contributors may be used to endorse or promote products
19 |  *       derived from this software without specific prior written
20 |  *       permission.
21 |  * 
22 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23 |  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 |  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 |  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26 |  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |  */
34 | 
35 | #ifndef httpclient_parser_h
36 | #define httpclient_parser_h
37 | 
38 | #include "http11_common.h"
39 | 
40 | typedef struct httpclient_parser { 
41 |   int cs;
42 |   size_t body_start;
43 |   int content_len;
44 |   int status;
45 |   int chunked;
46 |   int chunks_done;
47 |   int close;
48 |   size_t nread;
49 |   size_t mark;
50 |   size_t field_start;
51 |   size_t field_len;
52 | 
53 |   void *data;
54 | 
55 |   field_cb http_field;
56 |   element_cb reason_phrase;
57 |   element_cb status_code;
58 |   element_cb chunk_size;
59 |   element_cb http_version;
60 |   element_cb header_done;
61 |   element_cb last_chunk;
62 |   
63 |   
64 | } httpclient_parser;
65 | 
66 | int httpclient_parser_init(httpclient_parser *parser);
67 | int httpclient_parser_finish(httpclient_parser *parser);
68 | int httpclient_parser_execute(httpclient_parser *parser, const char *data, size_t len, size_t off);
69 | int httpclient_parser_has_error(httpclient_parser *parser);
70 | int httpclient_parser_is_finished(httpclient_parser *parser);
71 | 
72 | #define httpclient_parser_nread(parser) (parser)->nread 
73 | 
74 | #endif
75 | 


--------------------------------------------------------------------------------
/sylar/http/servlets/config_servlet.cc:
--------------------------------------------------------------------------------
 1 | #include "config_servlet.h"
 2 | #include "sylar/config.h"
 3 | 
 4 | namespace sylar {
 5 | namespace http {
 6 | 
 7 | ConfigServlet::ConfigServlet()
 8 |     :Servlet("ConfigServlet") {
 9 | }
10 | 
11 | int32_t ConfigServlet::handle(sylar::http::HttpRequest::ptr request
12 |                               ,sylar::http::HttpResponse::ptr response
13 |                               ,sylar::http::HttpSession::ptr session) {
14 |     std::string type = request->getParam("type");
15 |     if(type == "json") {
16 |         response->setHeader("Content-Type", "text/json charset=utf-8");
17 |     } else {
18 |         response->setHeader("Content-Type", "text/yaml charset=utf-8");
19 |     }
20 |     YAML::Node node;
21 |     sylar::Config::Visit([&node](ConfigVarBase::ptr base) {
22 |         YAML::Node n;
23 |         try {
24 |             n = YAML::Load(base->toString());
25 |         } catch(...) {
26 |             return;
27 |         }
28 |         node[base->getName()] = n;
29 |         node[base->getName() + "$description"] = base->getDescription();
30 |     });
31 |     if(type == "json") {
32 |         Json::Value jvalue;
33 |         if(YamlToJson(node, jvalue)) {
34 |             response->setBody(JsonUtil::ToString(jvalue));
35 |             return 0;
36 |         }
37 |     }
38 |     std::stringstream ss;
39 |     ss << node;
40 |     response->setBody(ss.str());
41 |     return 0;
42 | }
43 | 
44 | }
45 | }
46 | 


--------------------------------------------------------------------------------
/sylar/http/servlets/config_servlet.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_HTTP_SERVLETS_CONFIG_SERVLET_H__
 2 | #define __SYLAR_HTTP_SERVLETS_CONFIG_SERVLET_H__
 3 | 
 4 | #include "sylar/http/servlet.h"
 5 | 
 6 | namespace sylar {
 7 | namespace http {
 8 | 
 9 | class ConfigServlet : public Servlet {
10 | public:
11 |     ConfigServlet();
12 |     virtual int32_t handle(sylar::http::HttpRequest::ptr request
13 |                    , sylar::http::HttpResponse::ptr response
14 |                    , sylar::http::HttpSession::ptr session) override;
15 | };
16 | 
17 | }
18 | }
19 | 
20 | #endif
21 | 


--------------------------------------------------------------------------------
/sylar/http/servlets/status_servlet.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_HTTP_SERVLETS_STATUS_SERVLET_H__
 2 | #define __SYLAR_HTTP_SERVLETS_STATUS_SERVLET_H__
 3 | 
 4 | #include "sylar/http/servlet.h"
 5 | 
 6 | namespace sylar {
 7 | namespace http {
 8 | 
 9 | class StatusServlet : public Servlet {
10 | public:
11 |     StatusServlet();
12 |     virtual int32_t handle(sylar::http::HttpRequest::ptr request
13 |                    , sylar::http::HttpResponse::ptr response
14 |                    , sylar::http::HttpSession::ptr session) override;
15 | };
16 | 
17 | }
18 | }
19 | 
20 | #endif
21 | 


--------------------------------------------------------------------------------
/sylar/http/session_data.cc:
--------------------------------------------------------------------------------
 1 | #include "session_data.h"
 2 | #include "sylar/util.h"
 3 | 
 4 | namespace sylar {
 5 | namespace http {
 6 | 
 7 | SessionData::SessionData(bool auto_gen)
 8 |     :m_lastAccessTime(time(0)) {
 9 |     if(auto_gen) {
10 |         std::stringstream ss;
11 |         ss << sylar::GetCurrentUS() << "|" << rand() << "|" << rand() << "|" << rand();
12 |         m_id = sylar::md5(ss.str());
13 |     }
14 | }
15 | 
16 | void SessionData::del(const std::string& key) {
17 |     sylar::RWMutex::WriteLock lock(m_mutex);
18 |     m_datas.erase(key);
19 | }
20 | 
21 | bool SessionData::has(const std::string& key) {
22 |     sylar::RWMutex::ReadLock lock(m_mutex);
23 |     auto it = m_datas.find(key);
24 |     return it != m_datas.end();
25 | }
26 | 
27 | void SessionDataManager::add(SessionData::ptr info) {
28 |     sylar::RWMutex::WriteLock lock(m_mutex);
29 |     m_datas[info->getId()] = info;
30 | }
31 | 
32 | SessionData::ptr SessionDataManager::get(const std::string& id) {
33 |     sylar::RWMutex::ReadLock lock(m_mutex);
34 |     auto it = m_datas.find(id);
35 |     if(it != m_datas.end()) {
36 |         it->second->setLastAccessTime(time(0));
37 |         return it->second;
38 |     }
39 |     return nullptr;
40 | }
41 | 
42 | void SessionDataManager::check(int64_t ts) {
43 |     uint64_t now = time(0) - ts;
44 |     std::vector<std::string> keys;
45 |     sylar::RWMutex::ReadLock lock(m_mutex);
46 |     for(auto& i : m_datas) {
47 |         if(i.second->getLastAccessTime() < now) {
48 |             keys.push_back(i.first);
49 |         }
50 |     }
51 |     lock.unlock();
52 |     for(auto& i : keys) {
53 |         del(i);
54 |     }
55 | }
56 | 
57 | void SessionDataManager::del(const std::string& id) {
58 |     sylar::RWMutex::WriteLock lock(m_mutex);
59 |     m_datas.erase(id);
60 | }
61 | 
62 | }
63 | }
64 | 


--------------------------------------------------------------------------------
/sylar/http/session_data.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_HTTP_SESSION_DATA_H__
 2 | #define __SYLAR_HTTP_SESSION_DATA_H__
 3 | 
 4 | #include "sylar/mutex.h"
 5 | #include "sylar/singleton.h"
 6 | #include <boost/any.hpp>
 7 | #include <unordered_map>
 8 | 
 9 | namespace sylar {
10 | namespace http {
11 | 
12 | class SessionData {
13 | public:
14 |     typedef std::shared_ptr<SessionData> ptr;
15 |     SessionData(bool auto_gen = false);
16 | 
17 |     template<class T>
18 |     void setData(const std::string& key, const T& v) {
19 |         sylar::RWMutex::WriteLock lock(m_mutex);
20 |         m_datas[key] = v;
21 |     }
22 | 
23 |     template<class T>
24 |     T getData(const std::string& key, const T& def = T()) {
25 |         sylar::RWMutex::ReadLock lock(m_mutex);
26 |         auto it = m_datas.find(key);
27 |         if(it == m_datas.end()) {
28 |             return def;
29 |         }
30 |         boost::any v = it->second;
31 |         lock.unlock();
32 |         try {
33 |             return boost::any_cast<T>(v);
34 |         } catch (...) {
35 |         }
36 |         return def;
37 |     }
38 | 
39 |     void del(const std::string& key);
40 | 
41 |     bool has(const std::string& key);
42 |     uint64_t getLastAccessTime() const { return m_lastAccessTime;}
43 |     void setLastAccessTime(uint64_t v) { m_lastAccessTime = v;}
44 | 
45 |     const std::string& getId() const { return m_id;}
46 |     void setId(const std::string& val) { m_id = val;}
47 | private:
48 |     sylar::RWMutex m_mutex;
49 |     std::unordered_map<std::string, boost::any> m_datas;
50 |     uint64_t m_lastAccessTime;
51 |     std::string m_id;
52 | };
53 | 
54 | class SessionDataManager {
55 | public:
56 |     void add(SessionData::ptr info);
57 |     void del(const std::string& id);
58 |     SessionData::ptr get(const std::string& id);
59 |     void check(int64_t ts = 3600);
60 | private:
61 |     sylar::RWMutex m_mutex;
62 |     std::unordered_map<std::string, SessionData::ptr> m_datas;
63 | };
64 | 
65 | typedef sylar::Singleton<SessionDataManager> SessionDataMgr;
66 | 
67 | }
68 | }
69 | 
70 | #endif
71 | 


--------------------------------------------------------------------------------
/sylar/http/ws_connection.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_HTTP_WS_CONNECTION_H__
 2 | #define __SYLAR_HTTP_WS_CONNECTION_H__
 3 | 
 4 | #include "sylar/http/http_connection.h"
 5 | #include "sylar/http/ws_session.h"
 6 | 
 7 | namespace sylar {
 8 | namespace http {
 9 | 
10 | class WSConnection : public HttpConnection {
11 | public:
12 |     typedef std::shared_ptr<WSConnection> ptr;
13 |     WSConnection(Socket::ptr sock, bool owner = true);
14 |     static std::pair<HttpResult::ptr, WSConnection::ptr> Create(const std::string& url
15 |                                     ,uint64_t timeout_ms
16 |                                     , const std::map<std::string, std::string>& headers = {});
17 |     static std::pair<HttpResult::ptr, WSConnection::ptr> Create(Uri::ptr uri
18 |                                     ,uint64_t timeout_ms
19 |                                     , const std::map<std::string, std::string>& headers = {});
20 |     WSFrameMessage::ptr recvMessage();
21 |     int32_t sendMessage(WSFrameMessage::ptr msg, bool fin = true);
22 |     int32_t sendMessage(const std::string& msg, int32_t opcode = WSFrameHead::TEXT_FRAME, bool fin = true);
23 |     int32_t ping();
24 |     int32_t pong();
25 | };
26 | 
27 | }
28 | }
29 | 
30 | #endif
31 | 


--------------------------------------------------------------------------------
/sylar/http/ws_server.cc:
--------------------------------------------------------------------------------
 1 | #include "ws_server.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | namespace sylar {
 5 | namespace http {
 6 | 
 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
 8 | 
 9 | WSServer::WSServer(sylar::IOManager* worker, sylar::IOManager* io_worker, sylar::IOManager* accept_worker)
10 |     :TcpServer(worker, io_worker, accept_worker) {
11 |     m_dispatch.reset(new WSServletDispatch);
12 |     m_type = "websocket_server";
13 | }
14 | 
15 | void WSServer::handleClient(Socket::ptr client) {
16 |     SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client;
17 |     WSSession::ptr session(new WSSession(client));
18 |     do {
19 |         HttpRequest::ptr header = session->handleShake();
20 |         if(!header) {
21 |             SYLAR_LOG_DEBUG(g_logger) << "handleShake error";
22 |             break;
23 |         }
24 |         WSServlet::ptr servlet = m_dispatch->getWSServlet(header->getPath());
25 |         if(!servlet) {
26 |             SYLAR_LOG_DEBUG(g_logger) << "no match WSServlet";
27 |             break;
28 |         }
29 |         int rt = servlet->onConnect(header, session);
30 |         if(rt) {
31 |             SYLAR_LOG_DEBUG(g_logger) << "onConnect return " << rt;
32 |             break;
33 |         }
34 |         while(true) {
35 |             auto msg = session->recvMessage();
36 |             if(!msg) {
37 |                 break;
38 |             }
39 |             rt = servlet->handle(header, msg, session);
40 |             if(rt) {
41 |                 SYLAR_LOG_DEBUG(g_logger) << "handle return " << rt;
42 |                 break;
43 |             }
44 |         }
45 |         servlet->onClose(header, session);
46 |     } while(0);
47 |     session->close();
48 | }
49 | 
50 | }
51 | }
52 | 


--------------------------------------------------------------------------------
/sylar/http/ws_server.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_HTTP_WS_SERVER_H__
 2 | #define __SYLAR_HTTP_WS_SERVER_H__
 3 | 
 4 | #include "sylar/tcp_server.h"
 5 | #include "ws_session.h"
 6 | #include "ws_servlet.h"
 7 | 
 8 | namespace sylar {
 9 | namespace http {
10 | 
11 | class WSServer : public TcpServer {
12 | public:
13 |     typedef std::shared_ptr<WSServer> ptr;
14 | 
15 |     WSServer(sylar::IOManager* worker = sylar::IOManager::GetThis()
16 |              , sylar::IOManager* io_worker = sylar::IOManager::GetThis()
17 |              , sylar::IOManager* accept_worker = sylar::IOManager::GetThis());
18 | 
19 |     WSServletDispatch::ptr getWSServletDispatch() const { return m_dispatch;}
20 |     void setWSServletDispatch(WSServletDispatch::ptr v) { m_dispatch = v;}
21 | protected:
22 |     virtual void handleClient(Socket::ptr client) override;
23 | protected:
24 |     WSServletDispatch::ptr m_dispatch;
25 | };
26 | 
27 | }
28 | }
29 | 
30 | #endif
31 | 


--------------------------------------------------------------------------------
/sylar/http/ws_servlet.cc:
--------------------------------------------------------------------------------
 1 | #include "ws_servlet.h"
 2 | 
 3 | namespace sylar {
 4 | namespace http {
 5 | 
 6 | FunctionWSServlet::FunctionWSServlet(callback cb
 7 |                                      ,on_connect_cb connect_cb
 8 |                                      ,on_close_cb close_cb)
 9 |     :WSServlet("FunctionWSServlet")
10 |     ,m_callback(cb)
11 |     ,m_onConnect(connect_cb)
12 |     ,m_onClose(close_cb) {
13 | }
14 | 
15 | int32_t FunctionWSServlet::onConnect(sylar::http::HttpRequest::ptr header
16 |                                      ,sylar::http::WSSession::ptr session) {
17 |     if(m_onConnect) {
18 |         return m_onConnect(header, session);
19 |     }
20 |     return 0;
21 | }
22 | 
23 | int32_t FunctionWSServlet::onClose(sylar::http::HttpRequest::ptr header
24 |                                      ,sylar::http::WSSession::ptr session) {
25 |     if(m_onClose) {
26 |         return m_onClose(header, session);
27 |     }
28 |     return 0;
29 | }
30 | 
31 | int32_t FunctionWSServlet::handle(sylar::http::HttpRequest::ptr header
32 |                                    ,sylar::http::WSFrameMessage::ptr msg
33 |                                    ,sylar::http::WSSession::ptr session) {
34 |     if(m_callback) {
35 |         return m_callback(header, msg, session);
36 |     }
37 |     return 0;
38 | }
39 | 
40 | WSServletDispatch::WSServletDispatch() {
41 |     m_name = "WSServletDispatch";
42 | }
43 | 
44 | void WSServletDispatch::addServlet(const std::string& uri
45 |                     ,FunctionWSServlet::callback cb
46 |                     ,FunctionWSServlet::on_connect_cb connect_cb
47 |                     ,FunctionWSServlet::on_close_cb close_cb) {
48 |     ServletDispatch::addServlet(uri, std::make_shared<FunctionWSServlet>(cb, connect_cb, close_cb));
49 | }
50 | 
51 | void WSServletDispatch::addGlobServlet(const std::string& uri
52 |                     ,FunctionWSServlet::callback cb
53 |                     ,FunctionWSServlet::on_connect_cb connect_cb
54 |                     ,FunctionWSServlet::on_close_cb close_cb) {
55 |     ServletDispatch::addGlobServlet(uri, std::make_shared<FunctionWSServlet>(cb, connect_cb, close_cb));
56 | }
57 | 
58 | WSServlet::ptr WSServletDispatch::getWSServlet(const std::string& uri) {
59 |     auto slt = getMatchedServlet(uri);
60 |     return std::dynamic_pointer_cast<WSServlet>(slt);
61 | }
62 | 
63 | }
64 | }
65 | 


--------------------------------------------------------------------------------
/sylar/http/ws_servlet.h:
--------------------------------------------------------------------------------
 1 | #ifndef __HTTP_WS_SERVLET_H__
 2 | #define __HTTP_WS_SERVLET_H__
 3 | 
 4 | #include "ws_session.h"
 5 | #include "sylar/thread.h"
 6 | #include "servlet.h"
 7 | 
 8 | namespace sylar {
 9 | namespace http {
10 | 
11 | class WSServlet : public Servlet {
12 | public:
13 |     typedef std::shared_ptr<WSServlet> ptr;
14 |     WSServlet(const std::string& name)
15 |         :Servlet(name) {
16 |     }
17 |     virtual ~WSServlet() {}
18 | 
19 |     virtual int32_t handle(sylar::http::HttpRequest::ptr request
20 |                    , sylar::http::HttpResponse::ptr response
21 |                    , sylar::http::HttpSession::ptr session) override {
22 |         return 0;
23 |     }
24 | 
25 |     virtual int32_t onConnect(sylar::http::HttpRequest::ptr header
26 |                               ,sylar::http::WSSession::ptr session) = 0;
27 |     virtual int32_t onClose(sylar::http::HttpRequest::ptr header
28 |                              ,sylar::http::WSSession::ptr session) = 0;
29 |     virtual int32_t handle(sylar::http::HttpRequest::ptr header
30 |                            ,sylar::http::WSFrameMessage::ptr msg
31 |                            ,sylar::http::WSSession::ptr session) = 0;
32 |     const std::string& getName() const { return m_name;}
33 | protected:
34 |     std::string m_name;
35 | };
36 | 
37 | class FunctionWSServlet : public WSServlet {
38 | public:
39 |     typedef std::shared_ptr<FunctionWSServlet> ptr;
40 |     typedef std::function<int32_t (sylar::http::HttpRequest::ptr header
41 |                               ,sylar::http::WSSession::ptr session)> on_connect_cb;
42 |     typedef std::function<int32_t (sylar::http::HttpRequest::ptr header
43 |                              ,sylar::http::WSSession::ptr session)> on_close_cb; 
44 |     typedef std::function<int32_t (sylar::http::HttpRequest::ptr header
45 |                            ,sylar::http::WSFrameMessage::ptr msg
46 |                            ,sylar::http::WSSession::ptr session)> callback;
47 | 
48 |     FunctionWSServlet(callback cb
49 |                       ,on_connect_cb connect_cb = nullptr
50 |                       ,on_close_cb close_cb = nullptr);
51 | 
52 |     virtual int32_t onConnect(sylar::http::HttpRequest::ptr header
53 |                               ,sylar::http::WSSession::ptr session) override;
54 |     virtual int32_t onClose(sylar::http::HttpRequest::ptr header
55 |                              ,sylar::http::WSSession::ptr session) override;
56 |     virtual int32_t handle(sylar::http::HttpRequest::ptr header
57 |                            ,sylar::http::WSFrameMessage::ptr msg
58 |                            ,sylar::http::WSSession::ptr session) override;
59 | protected:
60 |     callback m_callback;
61 |     on_connect_cb m_onConnect;
62 |     on_close_cb m_onClose;
63 | };
64 | 
65 | class WSServletDispatch : public ServletDispatch {
66 | public:
67 |     typedef std::shared_ptr<WSServletDispatch> ptr;
68 |     typedef RWMutex RWMutexType;
69 | 
70 |     WSServletDispatch();
71 |     void addServlet(const std::string& uri
72 |                     ,FunctionWSServlet::callback cb
73 |                     ,FunctionWSServlet::on_connect_cb connect_cb = nullptr
74 |                     ,FunctionWSServlet::on_close_cb close_cb = nullptr);
75 |     void addGlobServlet(const std::string& uri
76 |                     ,FunctionWSServlet::callback cb
77 |                     ,FunctionWSServlet::on_connect_cb connect_cb = nullptr
78 |                     ,FunctionWSServlet::on_close_cb close_cb = nullptr);
79 |     WSServlet::ptr getWSServlet(const std::string& uri);
80 | };
81 | 
82 | }
83 | }
84 | 
85 | #endif
86 | 


--------------------------------------------------------------------------------
/sylar/http/ws_session.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_HTTP_WS_SESSION_H__
 2 | #define __SYLAR_HTTP_WS_SESSION_H__
 3 | 
 4 | #include "sylar/config.h"
 5 | #include "sylar/http/http_session.h"
 6 | #include <stdint.h>
 7 | 
 8 | namespace sylar {
 9 | namespace http {
10 | 
11 | #pragma pack(1)
12 | struct WSFrameHead {
13 |     enum OPCODE {
14 |         /// 数据分片帧
15 |         CONTINUE = 0,
16 |         /// 文本帧
17 |         TEXT_FRAME = 1,
18 |         /// 二进制帧
19 |         BIN_FRAME = 2,
20 |         /// 断开连接
21 |         CLOSE = 8,
22 |         /// PING
23 |         PING = 0x9,
24 |         /// PONG
25 |         PONG = 0xA
26 |     };
27 |     uint32_t opcode: 4;
28 |     bool rsv3: 1;
29 |     bool rsv2: 1;
30 |     bool rsv1: 1;
31 |     bool fin: 1;
32 |     uint32_t payload: 7;
33 |     bool mask: 1;
34 | 
35 |     std::string toString() const;
36 | };
37 | #pragma pack()
38 | 
39 | class WSFrameMessage {
40 | public:
41 |     typedef std::shared_ptr<WSFrameMessage> ptr;
42 |     WSFrameMessage(int opcode = 0, const std::string& data = "");
43 | 
44 |     int getOpcode() const { return m_opcode;}
45 |     void setOpcode(int v) { m_opcode = v;}
46 | 
47 |     const std::string& getData() const { return m_data;}
48 |     std::string& getData() { return m_data;}
49 |     void setData(const std::string& v) { m_data = v;}
50 | private:
51 |     int m_opcode;
52 |     std::string m_data;
53 | };
54 | 
55 | class WSSession : public HttpSession {
56 | public:
57 |     typedef std::shared_ptr<WSSession> ptr;
58 |     WSSession(Socket::ptr sock, bool owner = true);
59 | 
60 |     /// server client
61 |     HttpRequest::ptr handleShake();
62 | 
63 |     WSFrameMessage::ptr recvMessage();
64 |     int32_t sendMessage(WSFrameMessage::ptr msg, bool fin = true);
65 |     int32_t sendMessage(const std::string& msg, int32_t opcode = WSFrameHead::TEXT_FRAME, bool fin = true);
66 |     int32_t ping();
67 |     int32_t pong();
68 | private:
69 |     bool handleServerShake();
70 |     bool handleClientShake();
71 | };
72 | 
73 | extern sylar::ConfigVar<uint32_t>::ptr g_websocket_message_max_size;
74 | WSFrameMessage::ptr WSRecvMessage(Stream* stream, bool client);
75 | int32_t WSSendMessage(Stream* stream, WSFrameMessage::ptr msg, bool client, bool fin);
76 | int32_t WSPing(Stream* stream);
77 | int32_t WSPong(Stream* stream);
78 | 
79 | }
80 | }
81 | 
82 | #endif
83 | 


--------------------------------------------------------------------------------
/sylar/library.cc:
--------------------------------------------------------------------------------
 1 | #include "library.h"
 2 | 
 3 | #include <dlfcn.h>
 4 | #include "sylar/config.h"
 5 | #include "sylar/env.h"
 6 | #include "sylar/log.h"
 7 | 
 8 | namespace sylar {
 9 | 
10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
11 | 
12 | typedef Module* (*create_module)();
13 | typedef void (*destory_module)(Module*);
14 | 
15 | class ModuleCloser {
16 | public:
17 |     ModuleCloser(void* handle, destory_module d)
18 |         :m_handle(handle)
19 |         ,m_destory(d) {
20 |     }
21 | 
22 |     void operator()(Module* module) {
23 |         std::string name = module->getName();
24 |         std::string version = module->getVersion();
25 |         std::string path = module->getFilename();
26 |         m_destory(module);
27 |         int rt = dlclose(m_handle);
28 |         if(rt) {
29 |             SYLAR_LOG_ERROR(g_logger) << "dlclose handle fail handle="
30 |                 << m_handle << " name=" << name
31 |                 << " version=" << version
32 |                 << " path=" << path
33 |                 << " error=" << dlerror();
34 |         } else {
35 |             SYLAR_LOG_INFO(g_logger) << "destory module=" << name
36 |                 << " version=" << version
37 |                 << " path=" << path
38 |                 << " handle=" << m_handle
39 |                 << " success";
40 |         }
41 |     }
42 | private:
43 |     void* m_handle;
44 |     destory_module m_destory;
45 | };
46 | 
47 | Module::ptr Library::GetModule(const std::string& path) {
48 |     void* handle = dlopen(path.c_str(), RTLD_NOW);
49 |     if(!handle) {
50 |         SYLAR_LOG_ERROR(g_logger) << "cannot load library path="
51 |             << path << " error=" << dlerror();
52 |         return nullptr;
53 |     }
54 | 
55 |     create_module create = (create_module)dlsym(handle, "CreateModule");
56 |     if(!create) {
57 |         SYLAR_LOG_ERROR(g_logger) << "cannot load symbol CreateModule in "
58 |             << path << " error=" << dlerror();
59 |         dlclose(handle);
60 |         return nullptr;
61 |     }
62 | 
63 |     destory_module destory = (destory_module)dlsym(handle, "DestoryModule");
64 |     if(!destory) {
65 |         SYLAR_LOG_ERROR(g_logger) << "cannot load symbol DestoryModule in "
66 |             << path << " error=" << dlerror();
67 |         dlclose(handle);
68 |         return nullptr;
69 |     }
70 | 
71 |     Module::ptr module(create(), ModuleCloser(handle, destory));
72 |     module->setFilename(path);
73 |     SYLAR_LOG_INFO(g_logger) << "load module name=" << module->getName()
74 |         << " version=" << module->getVersion()
75 |         << " path=" << module->getFilename()
76 |         << " success";
77 |     Config::LoadFromConfDir(sylar::EnvMgr::GetInstance()->getConfigPath(), true);
78 |     return module;
79 | }
80 | 
81 | }
82 | 


--------------------------------------------------------------------------------
/sylar/library.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_LIBRARY_H__
 2 | #define __SYLAR_LIBRARY_H__
 3 | 
 4 | #include <memory>
 5 | #include "module.h"
 6 | 
 7 | namespace sylar {
 8 | 
 9 | class Library {
10 | public:
11 |     static Module::ptr GetModule(const std::string& path);
12 | };
13 | 
14 | }
15 | 
16 | #endif
17 | 


--------------------------------------------------------------------------------
/sylar/macro.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file macro.h
 3 |  * @brief 常用宏的封装
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-06-01
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef __SYLAR_MACRO_H__
10 | #define __SYLAR_MACRO_H__
11 | 
12 | #include <string.h>
13 | #include <assert.h>
14 | #include "log.h"
15 | #include "util.h"
16 | 
17 | #if defined __GNUC__ || defined __llvm__
18 | /// LIKCLY 宏的封装, 告诉编译器优化,条件大概率成立
19 | #   define SYLAR_LIKELY(x)       __builtin_expect(!!(x), 1)
20 | /// LIKCLY 宏的封装, 告诉编译器优化,条件大概率不成立
21 | #   define SYLAR_UNLIKELY(x)     __builtin_expect(!!(x), 0)
22 | #else
23 | #   define SYLAR_LIKELY(x)      (x)
24 | #   define SYLAR_UNLIKELY(x)      (x)
25 | #endif
26 | 
27 | /// 断言宏封装
28 | #define SYLAR_ASSERT(x) \
29 |     if(SYLAR_UNLIKELY(!(x))) { \
30 |         SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ASSERTION: " #x \
31 |             << "\nbacktrace:\n" \
32 |             << sylar::BacktraceToString(100, 2, "    "); \
33 |         assert(x); \
34 |     }
35 | 
36 | /// 断言宏封装
37 | #define SYLAR_ASSERT2(x, w) \
38 |     if(SYLAR_UNLIKELY(!(x))) { \
39 |         SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ASSERTION: " #x \
40 |             << "\n" << w \
41 |             << "\nbacktrace:\n" \
42 |             << sylar::BacktraceToString(100, 2, "    "); \
43 |         assert(x); \
44 |     }
45 | 
46 | #endif
47 | 


--------------------------------------------------------------------------------
/sylar/main.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/application.h"
 2 | #include <stdlib.h>
 3 | #include <time.h>
 4 | 
 5 | int main(int argc, char** argv) {
 6 |     setenv("TZ", ":/etc/localtime", 1);
 7 |     tzset();
 8 |     srand(time(0));
 9 |     sylar::Application app;
10 |     if(app.init(argc, argv)) {
11 |         return app.run();
12 |     }
13 |     return 0;
14 | }
15 | 


--------------------------------------------------------------------------------
/sylar/mutex.cc:
--------------------------------------------------------------------------------
 1 | #include "mutex.h"
 2 | #include "macro.h"
 3 | #include "scheduler.h"
 4 | 
 5 | namespace sylar {
 6 | 
 7 | Semaphore::Semaphore(uint32_t count) {
 8 |     if(sem_init(&m_semaphore, 0, count)) {
 9 |         throw std::logic_error("sem_init error");
10 |     }
11 | }
12 | 
13 | Semaphore::~Semaphore() {
14 |     sem_destroy(&m_semaphore);
15 | }
16 | 
17 | void Semaphore::wait() {
18 |     if(sem_wait(&m_semaphore)) {
19 |         throw std::logic_error("sem_wait error");
20 |     }
21 | }
22 | 
23 | void Semaphore::notify() {
24 |     if(sem_post(&m_semaphore)) {
25 |         throw std::logic_error("sem_post error");
26 |     }
27 | }
28 | 
29 | FiberSemaphore::FiberSemaphore(size_t initial_concurrency)
30 |     :m_concurrency(initial_concurrency) {
31 | }
32 | 
33 | FiberSemaphore::~FiberSemaphore() {
34 |     SYLAR_ASSERT(m_waiters.empty());
35 | }
36 | 
37 | bool FiberSemaphore::tryWait() {
38 |     SYLAR_ASSERT(Scheduler::GetThis());
39 |     {
40 |         MutexType::Lock lock(m_mutex);
41 |         if(m_concurrency > 0u) {
42 |             --m_concurrency;
43 |             return true;
44 |         }
45 |         return false;
46 |     }
47 | }
48 | 
49 | void FiberSemaphore::wait() {
50 |     SYLAR_ASSERT(Scheduler::GetThis());
51 |     {
52 |         MutexType::Lock lock(m_mutex);
53 |         if(m_concurrency > 0u) {
54 |             --m_concurrency;
55 |             return;
56 |         }
57 |         m_waiters.push_back(std::make_pair(Scheduler::GetThis(), Fiber::GetThis()));
58 |     }
59 |     Fiber::YieldToHold();
60 | }
61 | 
62 | void FiberSemaphore::notify() {
63 |     MutexType::Lock lock(m_mutex);
64 |     if(!m_waiters.empty()) {
65 |         auto next = m_waiters.front();
66 |         m_waiters.pop_front();
67 |         next.first->schedule(next.second);
68 |     } else {
69 |         ++m_concurrency;
70 |     }
71 | }
72 | 
73 | }
74 | 


--------------------------------------------------------------------------------
/sylar/noncopyable.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file noncopyable.h
 3 |  * @brief 不可拷贝对象封装
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-05-31
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef __SYLAR_NONCOPYABLE_H__
10 | #define __SYLAR_NONCOPYABLE_H__
11 | 
12 | namespace sylar {
13 | 
14 | /**
15 |  * @brief 对象无法拷贝,赋值
16 |  */
17 | class Noncopyable {
18 | public:
19 |     /**
20 |      * @brief 默认构造函数
21 |      */
22 |     Noncopyable() = default;
23 | 
24 |     /**
25 |      * @brief 默认析构函数
26 |      */
27 |     ~Noncopyable() = default;
28 | 
29 |     /**
30 |      * @brief 拷贝构造函数(禁用)
31 |      */
32 |     Noncopyable(const Noncopyable&) = delete;
33 | 
34 |     /**
35 |      * @brief 赋值函数(禁用)
36 |      */
37 |     Noncopyable& operator=(const Noncopyable&) = delete;
38 | };
39 | 
40 | }
41 | 
42 | #endif
43 | 


--------------------------------------------------------------------------------
/sylar/ns/name_server_module.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_NS_NAME_SERVER_MODULE_H__
 2 | #define __SYLAR_NS_NAME_SERVER_MODULE_H__
 3 | 
 4 | #include "sylar/module.h"
 5 | #include "ns_protocol.h"
 6 | 
 7 | namespace sylar {
 8 | namespace ns {
 9 | 
10 | class NameServerModule;
11 | class NSClientInfo {
12 | friend class NameServerModule;
13 | public:
14 |     typedef std::shared_ptr<NSClientInfo> ptr;
15 | private:
16 |     NSNode::ptr m_node;
17 |     std::map<std::string, std::set<uint32_t> > m_domain2cmds;
18 | };
19 | 
20 | class NameServerModule : public RockModule {
21 | public:
22 |     typedef std::shared_ptr<NameServerModule> ptr;
23 |     NameServerModule();
24 | 
25 |     virtual bool handleRockRequest(sylar::RockRequest::ptr request
26 |                         ,sylar::RockResponse::ptr response
27 |                         ,sylar::RockStream::ptr stream) override;
28 |     virtual bool handleRockNotify(sylar::RockNotify::ptr notify
29 |                         ,sylar::RockStream::ptr stream) override;
30 |     virtual bool onConnect(sylar::Stream::ptr stream) override;
31 |     virtual bool onDisconnect(sylar::Stream::ptr stream) override;
32 |     virtual std::string statusString() override;
33 | private:
34 |     bool handleRegister(sylar::RockRequest::ptr request
35 |                         ,sylar::RockResponse::ptr response
36 |                         ,sylar::RockStream::ptr stream);
37 |     bool handleQuery(sylar::RockRequest::ptr request
38 |                         ,sylar::RockResponse::ptr response
39 |                         ,sylar::RockStream::ptr stream);
40 |     bool handleTick(sylar::RockRequest::ptr request
41 |                         ,sylar::RockResponse::ptr response
42 |                         ,sylar::RockStream::ptr stream);
43 | 
44 | private:
45 |     NSClientInfo::ptr get(sylar::RockStream::ptr rs);
46 |     void set(sylar::RockStream::ptr rs, NSClientInfo::ptr info);
47 | 
48 |     void setQueryDomain(sylar::RockStream::ptr rs, const std::set<std::string>& ds);
49 | 
50 |     void doNotify(std::set<std::string>& domains, std::shared_ptr<NotifyMessage> nty);
51 | 
52 |     std::set<sylar::RockStream::ptr> getStreams(const std::string& domain);
53 | private:
54 |     NSDomainSet::ptr m_domains;
55 | 
56 |     sylar::RWMutex m_mutex;
57 |     std::map<sylar::RockStream::ptr, NSClientInfo::ptr> m_sessions;
58 | 
59 |     /// sessoin 关注的域名
60 |     std::map<sylar::RockStream::ptr, std::set<std::string> > m_queryDomains;
61 |     /// 域名对应关注的session
62 |     std::map<std::string, std::set<sylar::RockStream::ptr> > m_domainToSessions;
63 | };
64 | 
65 | }
66 | }
67 | 
68 | #endif
69 | 


--------------------------------------------------------------------------------
/sylar/ns/ns_client.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_NS_NS_CLIENT_H__
 2 | #define __SYLAR_NS_NS_CLIENT_H__
 3 | 
 4 | #include "sylar/rock/rock_stream.h"
 5 | #include "ns_protocol.h"
 6 | 
 7 | namespace sylar {
 8 | namespace ns {
 9 | 
10 | class NSClient : public RockConnection {
11 | public:
12 |     typedef std::shared_ptr<NSClient> ptr;
13 |     NSClient();
14 |     ~NSClient();
15 | 
16 |     const std::set<std::string>& getQueryDomains();
17 |     void setQueryDomains(const std::set<std::string>& v);
18 | 
19 |     void addQueryDomain(const std::string& domain);
20 |     void delQueryDomain(const std::string& domain);
21 | 
22 |     bool hasQueryDomain(const std::string& domain);
23 | 
24 |     RockResult::ptr query();
25 | 
26 |     void init();
27 |     void uninit();
28 |     NSDomainSet::ptr getDomains() const { return m_domains;}
29 | private:
30 |     void onQueryDomainChange();
31 |     bool onConnect(sylar::AsyncSocketStream::ptr stream);
32 |     void onDisconnect(sylar::AsyncSocketStream::ptr stream);
33 |     bool onNotify(sylar::RockNotify::ptr ,sylar::RockStream::ptr);
34 | 
35 |     void onTimer();
36 | private:
37 |     sylar::RWMutex m_mutex;
38 |     std::set<std::string> m_queryDomains;
39 |     NSDomainSet::ptr m_domains;
40 |     uint32_t m_sn = 0;
41 |     sylar::Timer::ptr m_timer;
42 | };
43 | 
44 | }
45 | }
46 | 
47 | #endif
48 | 


--------------------------------------------------------------------------------
/sylar/ns/ns_protobuf.proto:
--------------------------------------------------------------------------------
 1 | package sylar.ns;
 2 | 
 3 | message Node {
 4 |     optional string ip = 1;     //ip地址
 5 |     optional uint32 port = 2;   //端口号
 6 |     optional uint32 weight = 3; //权重
 7 | }
 8 | 
 9 | message RegisterInfo {
10 |     optional string domain = 1; //域名
11 |     repeated uint32 cmds = 2;  //命令字
12 |     optional Node node = 3;     //节点信息
13 | }
14 | 
15 | message RegisterRequest {
16 |     repeated RegisterInfo infos = 1;    //注册信息
17 | }
18 | 
19 | message QueryRequest {
20 |     repeated string domains = 1;         //域名
21 | }
22 | 
23 | message NodeInfo {
24 |     optional string domain = 1;
25 |     optional uint32 cmd = 2;
26 |     repeated Node nodes = 3;
27 | }
28 | 
29 | message QueryResponse {
30 |     repeated NodeInfo infos = 1;
31 | }
32 | 
33 | message NotifyMessage {
34 |     repeated NodeInfo dels = 1;
35 |     repeated NodeInfo updates = 2;
36 | }
37 | 


--------------------------------------------------------------------------------
/sylar/orm/column.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ORM_COLUMN_H__
 2 | #define __SYLAR_ORM_COLUMN_H__
 3 | 
 4 | #include <memory>
 5 | #include <string>
 6 | #include "tinyxml2.h"
 7 | 
 8 | namespace sylar {
 9 | namespace orm {
10 | 
11 | class Table;
12 | class Column {
13 | friend class Table;
14 | public:
15 |     typedef std::shared_ptr<Column> ptr;
16 |     enum Type {
17 |         TYPE_NULL = 0,
18 |         TYPE_INT8,
19 |         TYPE_UINT8,
20 |         TYPE_INT16,
21 |         TYPE_UINT16,
22 |         TYPE_INT32,
23 |         TYPE_UINT32,
24 |         TYPE_FLOAT,
25 |         TYPE_DOUBLE,
26 |         TYPE_INT64,
27 |         TYPE_UINT64,
28 |         TYPE_STRING,
29 |         TYPE_TEXT,
30 |         TYPE_BLOB,
31 |         TYPE_TIMESTAMP
32 |     };
33 | 
34 |     const std::string& getName() const { return m_name;}
35 |     const std::string& getType() const { return m_type;}
36 |     const std::string& getDesc() const { return m_desc;}
37 |     const std::string& getDefault() const { return m_default;}
38 | 
39 |     std::string getDefaultValueString();
40 |     std::string getSQLite3Default();
41 | 
42 |     bool isAutoIncrement() const { return m_autoIncrement;}
43 |     Type getDType() const { return m_dtype;}
44 | 
45 |     bool init(const tinyxml2::XMLElement& node);
46 | 
47 |     std::string getMemberDefine() const;
48 |     std::string getGetFunDefine() const;
49 |     std::string getSetFunDefine() const;
50 |     std::string getSetFunImpl(const std::string& class_name, int idx) const;
51 |     int getIndex() const { return m_index;}
52 | 
53 |     static Type ParseType(const std::string& v);
54 |     static std::string TypeToString(Type type);
55 | 
56 |     std::string getDTypeString() { return TypeToString(m_dtype);}
57 |     std::string getSQLite3TypeString();
58 |     std::string getMySQLTypeString();
59 | 
60 |     std::string getBindString();
61 |     std::string getGetString();
62 |     const std::string& getUpdate() const { return m_update;}
63 | private:
64 |     std::string m_name;
65 |     std::string m_type;
66 |     std::string m_default;
67 |     std::string m_update;
68 |     std::string m_desc;
69 |     int m_index;
70 | 
71 |     bool m_autoIncrement;
72 |     Type m_dtype;
73 |     int m_length;
74 | };
75 | 
76 | }
77 | }
78 | 
79 | #endif
80 | 


--------------------------------------------------------------------------------
/sylar/orm/index.cc:
--------------------------------------------------------------------------------
 1 | #include "index.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/util.h"
 4 | 
 5 | namespace sylar {
 6 | namespace orm {
 7 | 
 8 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("orm");
 9 | 
10 | Index::Type Index::ParseType(const std::string& v) {
11 | #define XX(a, b) \
12 |     if(v == b) {\
13 |         return a; \
14 |     }
15 |     XX(TYPE_PK, "pk");
16 |     XX(TYPE_UNIQ, "uniq");
17 |     XX(TYPE_INDEX, "index");
18 | #undef XX
19 |     return TYPE_NULL;
20 | }
21 | 
22 | std::string Index::TypeToString(Type v) {
23 | #define XX(a, b) \
24 |     if(v == a) { \
25 |         return b; \
26 |     }
27 |     XX(TYPE_PK, "pk");
28 |     XX(TYPE_UNIQ, "uniq");
29 |     XX(TYPE_INDEX, "index");
30 | #undef XX
31 |     return "";
32 | }
33 | 
34 | bool Index::init(const tinyxml2::XMLElement& node) {
35 |     if(!node.Attribute("name")) {
36 |         SYLAR_LOG_ERROR(g_logger) << "index name not exists";
37 |         return false;
38 |     }
39 |     m_name = node.Attribute("name");
40 | 
41 |     if(!node.Attribute("type")) {
42 |         SYLAR_LOG_ERROR(g_logger) << "index name=" << m_name << " type is null";
43 |         return false;
44 |     }
45 | 
46 |     m_type = node.Attribute("type");
47 |     m_dtype = ParseType(m_type);
48 |     if(m_dtype == TYPE_NULL) {
49 |         SYLAR_LOG_ERROR(g_logger) << "index name=" << m_name << " type=" << m_type
50 |             << " invalid (pk, index, uniq)";
51 |         return false;
52 |     }
53 | 
54 |     if(!node.Attribute("cols")) {
55 |         SYLAR_LOG_ERROR(g_logger) << "index name=" << m_name << " cols is null";
56 |     }
57 |     std::string tmp = node.Attribute("cols");
58 |     m_cols = sylar::split(tmp, ',');
59 | 
60 |     if(node.Attribute("desc")) {
61 |         m_desc = node.Attribute("desc");
62 |     }
63 |     return true;
64 | }
65 | 
66 | }
67 | }
68 | 


--------------------------------------------------------------------------------
/sylar/orm/index.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ORM_INDEX_H__
 2 | #define __SYLAR_ORM_INDEX_H__
 3 | 
 4 | #include <memory>
 5 | #include <string>
 6 | #include <vector>
 7 | #include "tinyxml2.h"
 8 | 
 9 | namespace sylar {
10 | namespace orm {
11 | 
12 | class Index {
13 | public:
14 |     enum Type {
15 |         TYPE_NULL = 0,
16 |         TYPE_PK,
17 |         TYPE_UNIQ,
18 |         TYPE_INDEX
19 |     };
20 |     typedef std::shared_ptr<Index> ptr;
21 |     const std::string& getName() const { return m_name;}
22 |     const std::string& getType() const { return m_type;}
23 |     const std::string& getDesc() const { return m_desc;}
24 |     const std::vector<std::string>& getCols() const { return m_cols;}
25 |     Type getDType() const { return m_dtype;}
26 |     bool init(const tinyxml2::XMLElement& node);
27 | 
28 |     bool isPK() const { return m_type == "pk";}
29 | 
30 |     static Type ParseType(const std::string& v);
31 |     static std::string TypeToString(Type v);
32 | private:
33 |     std::string m_name;
34 |     std::string m_type;
35 |     std::string m_desc;
36 |     std::vector<std::string> m_cols;
37 | 
38 |     Type m_dtype;
39 | };
40 | 
41 | }
42 | }
43 | 
44 | #endif
45 | 


--------------------------------------------------------------------------------
/sylar/orm/orm.cc:
--------------------------------------------------------------------------------
 1 | #include "table.h"
 2 | #include "sylar/util.h"
 3 | #include "sylar/log.h"
 4 | 
 5 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("orm");
 6 | 
 7 | void gen_cmake(const std::string& path, const std::map<std::string, sylar::orm::Table::ptr>& tbs) {
 8 |     std::ofstream ofs(path + "/CMakeLists.txt");
 9 |     ofs << "cmake_minimum_required(VERSION 3.0)" << std::endl;
10 |     ofs << "project(orm_data)" << std::endl;
11 |     ofs << std::endl;
12 |     ofs << "set(LIB_SRC" << std::endl;
13 |     for(auto& i : tbs) {
14 |         ofs << "    " << sylar::replace(i.second->getNamespace(), ".", "/")
15 |             << "/" << sylar::ToLower(i.second->getFilename()) << ".cc" << std::endl;
16 |     }
17 |     ofs << ")" << std::endl;
18 |     ofs << "add_library(orm_data ${LIB_SRC})" << std::endl;
19 |     ofs << "force_redefine_file_macro_for_sources(orm_data)" << std::endl;
20 | }
21 | 
22 | 
23 | int main(int argc, char** argv) {
24 |     if(argc < 2) {
25 |         std::cout << "use as[" << argv[0] << " orm_config_path orm_output_path]" << std::endl;
26 |     }
27 | 
28 |     std::string out_path = "./orm_out";
29 |     std::string input_path = "bin/orm_conf";
30 |     if(argc > 1) {
31 |         input_path = argv[1];
32 |     }
33 |     if(argc > 2) {
34 |         out_path = argv[2];
35 |     }
36 |     std::vector<std::string> files;
37 |     sylar::FSUtil::ListAllFile(files, input_path, ".xml");
38 |     std::vector<sylar::orm::Table::ptr> tbs;
39 |     bool has_error = false;
40 |     for(auto& i : files) {
41 |         SYLAR_LOG_INFO(g_logger) << "init xml=" << i << " begin";
42 |         tinyxml2::XMLDocument doc;
43 |         if(doc.LoadFile(i.c_str())) {
44 |             SYLAR_LOG_ERROR(g_logger) << "error: " << doc.ErrorStr();
45 |             has_error = true;
46 |         } else {
47 |             sylar::orm::Table::ptr table(new sylar::orm::Table);
48 |             if(!table->init(*doc.RootElement())) {
49 |                 SYLAR_LOG_ERROR(g_logger) << "table init error";
50 |                 has_error = true;
51 |             } else {
52 |                 tbs.push_back(table);
53 |             }
54 |         }
55 |         SYLAR_LOG_INFO(g_logger) << "init xml=" << i << " end";
56 |     }
57 |     if(has_error) {
58 |         return 0;
59 |     }
60 | 
61 |     std::map<std::string, sylar::orm::Table::ptr> orm_tbs;
62 |     for(auto& i : tbs) {
63 |         i->gen(out_path);
64 |         orm_tbs[i->getName()] = i;
65 |     }
66 |     gen_cmake(out_path, orm_tbs);
67 |     return 0;
68 | }
69 | 


--------------------------------------------------------------------------------
/sylar/orm/table.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ORM_TABLE_H__
 2 | #define __SYLAR_ORM_TABLE_H__
 3 | 
 4 | #include "column.h"
 5 | #include "index.h"
 6 | #include <fstream>
 7 | 
 8 | namespace sylar {
 9 | namespace orm {
10 | 
11 | class Table {
12 | public:
13 |     typedef std::shared_ptr<Table> ptr;
14 |     const std::string& getName() const { return m_name;}
15 |     const std::string& getNamespace() const { return m_namespace;}
16 |     const std::string& getDesc() const { return m_desc;}
17 | 
18 |     const std::vector<Column::ptr>& getCols() const { return m_cols;}
19 |     const std::vector<Index::ptr>& getIdxs() const { return  m_idxs;}
20 |     bool init(const tinyxml2::XMLElement& node);
21 | 
22 |     void gen(const std::string& path);
23 | 
24 |     std::string getFilename() const;
25 | private:
26 |     void gen_inc(const std::string& path);
27 |     void gen_src(const std::string& path);
28 |     std::string genToStringInc();
29 |     std::string genToStringSrc(const std::string& class_name);
30 |     std::string genToInsertSQL(const std::string& class_name);
31 |     std::string genToUpdateSQL(const std::string& class_name);
32 |     std::string genToDeleteSQL(const std::string& class_name);
33 | 
34 |     std::vector<Column::ptr> getPKs() const;
35 |     Column::ptr getCol(const std::string& name) const;
36 | 
37 |     std::string genWhere() const;
38 | 
39 |     void gen_dao_inc(std::ofstream& ofs);
40 |     void gen_dao_src(std::ofstream& ofs);
41 | 
42 |     enum DBType {
43 |         TYPE_SQLITE3 = 1,
44 |         TYPE_MYSQL = 2
45 |     };
46 | private:
47 |     std::string m_name;
48 |     std::string m_namespace;
49 |     std::string m_desc;
50 |     std::string m_subfix = "_info";
51 |     DBType m_type = TYPE_SQLITE3;
52 |     std::string m_dbclass = "sylar::IDB";
53 |     std::string m_queryclass = "sylar::IDB";
54 |     std::string m_updateclass = "sylar::IDB";
55 |     std::vector<Column::ptr> m_cols;
56 |     std::vector<Index::ptr> m_idxs;
57 | };
58 | 
59 | }
60 | }
61 | 
62 | #endif
63 | 


--------------------------------------------------------------------------------
/sylar/orm/util.cc:
--------------------------------------------------------------------------------
 1 | #include "util.h"
 2 | #include "sylar/util.h"
 3 | 
 4 | namespace sylar {
 5 | namespace orm {
 6 | 
 7 | std::string GetAsVariable(const std::string& v) {
 8 |     return sylar::ToLower(v);
 9 | }
10 | 
11 | std::string GetAsClassName(const std::string& v) {
12 |     auto vs = sylar::split(v, '_');
13 |     std::stringstream ss;
14 |     for(auto& i : vs) {
15 |         i[0] = toupper(i[0]);
16 |         ss << i;
17 |     }
18 |     return ss.str();
19 | }
20 | 
21 | std::string GetAsMemberName(const std::string& v) {
22 |     auto class_name = GetAsClassName(v);
23 |     class_name[0] = tolower(class_name[0]);
24 |     return "m_" + class_name;
25 | }
26 | 
27 | std::string GetAsGetFunName(const std::string& v) {
28 |     auto class_name = GetAsClassName(v);
29 |     return "get" + class_name;
30 | }
31 | 
32 | std::string GetAsSetFunName(const std::string& v) {
33 |     auto class_name = GetAsClassName(v);
34 |     return "set" + class_name;
35 | }
36 | 
37 | std::string XmlToString(const tinyxml2::XMLNode& node) {
38 |     return "";
39 | }
40 | 
41 | std::string GetAsDefineMacro(const std::string& v) {
42 |     std::string tmp = sylar::replace(v, '.', '_');
43 |     tmp = sylar::ToUpper(tmp);
44 |     return "__" + tmp + "__";
45 | }
46 | 
47 | }
48 | }
49 | 


--------------------------------------------------------------------------------
/sylar/orm/util.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ORM_UTIL_H__
 2 | #define __SYLAR_ORM_UTIL_H__
 3 | 
 4 | #include <tinyxml2.h>
 5 | #include <string>
 6 | 
 7 | namespace sylar {
 8 | namespace orm {
 9 | 
10 | std::string GetAsVariable(const std::string& v);
11 | std::string GetAsClassName(const std::string& v);
12 | std::string GetAsMemberName(const std::string& v);
13 | std::string GetAsGetFunName(const std::string& v);
14 | std::string GetAsSetFunName(const std::string& v);
15 | std::string XmlToString(const tinyxml2::XMLNode& node);
16 | std::string GetAsDefineMacro(const std::string& v);
17 | 
18 | }
19 | }
20 | 
21 | #endif
22 | 


--------------------------------------------------------------------------------
/sylar/protocol.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/protocol.h"
 2 | #include "sylar/util.h"
 3 | 
 4 | namespace sylar {
 5 | 
 6 | ByteArray::ptr Message::toByteArray() {
 7 |     ByteArray::ptr ba(new ByteArray);
 8 |     if(serializeToByteArray(ba)) {
 9 |         return ba;
10 |     }
11 |     return nullptr;
12 | }
13 | 
14 | Request::Request()
15 |     :m_sn(0)
16 |     ,m_cmd(0) {
17 | }
18 | 
19 | bool Request::serializeToByteArray(ByteArray::ptr bytearray) {
20 |     bytearray->writeFuint8(getType());
21 |     bytearray->writeUint32(m_sn);
22 |     bytearray->writeUint32(m_cmd);
23 |     return true;
24 | }
25 | 
26 | bool Request::parseFromByteArray(ByteArray::ptr bytearray) {
27 |     m_sn = bytearray->readUint32();
28 |     m_cmd = bytearray->readUint32();
29 |     return true;
30 | }
31 | 
32 | Response::Response()
33 |     :m_sn(0)
34 |     ,m_cmd(0)
35 |     ,m_result(404)
36 |     ,m_resultStr("unhandle") {
37 | }
38 | 
39 | bool Response::serializeToByteArray(ByteArray::ptr bytearray) {
40 |     bytearray->writeFuint8(getType());
41 |     bytearray->writeUint32(m_sn);
42 |     bytearray->writeUint32(m_cmd);
43 |     bytearray->writeUint32(m_result);
44 |     bytearray->writeStringVint(m_resultStr);
45 |     return true;
46 | }
47 | 
48 | bool Response::parseFromByteArray(ByteArray::ptr bytearray) {
49 |     m_sn = bytearray->readUint32();
50 |     m_cmd = bytearray->readUint32();
51 |     m_result = bytearray->readUint32();
52 |     m_resultStr = bytearray->readStringVint();
53 |     return true;
54 | }
55 | 
56 | Notify::Notify()
57 |     :m_notify(0) {
58 | }
59 | 
60 | bool Notify::serializeToByteArray(ByteArray::ptr bytearray) {
61 |     bytearray->writeFuint8(getType());
62 |     bytearray->writeUint32(m_notify);
63 |     return true;
64 | }
65 | 
66 | bool Notify::parseFromByteArray(ByteArray::ptr bytearray) {
67 |     m_notify = bytearray->readUint32();
68 |     return true;
69 | }
70 | 
71 | }
72 | 


--------------------------------------------------------------------------------
/sylar/protocol.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file protocol.h
  3 |  * @brief 自定义协议
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-07-03
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | #ifndef __SYLAR_PROTOCOL_H__
 10 | #define __SYLAR_PROTOCOL_H__
 11 | 
 12 | #include <memory>
 13 | #include "sylar/stream.h"
 14 | #include "sylar/bytearray.h"
 15 | 
 16 | namespace sylar {
 17 | 
 18 | class Message {
 19 | public:
 20 |     typedef std::shared_ptr<Message> ptr;
 21 |     enum MessageType {
 22 |         REQUEST = 1,
 23 |         RESPONSE = 2,
 24 |         NOTIFY = 3
 25 |     };
 26 |     virtual ~Message() {}
 27 | 
 28 |     virtual ByteArray::ptr toByteArray();
 29 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) = 0;
 30 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) = 0;
 31 | 
 32 |     virtual std::string toString() const = 0;
 33 |     virtual const std::string& getName() const = 0;
 34 |     virtual int32_t getType() const = 0;
 35 | };
 36 | 
 37 | class MessageDecoder {
 38 | public:
 39 |     typedef std::shared_ptr<MessageDecoder> ptr;
 40 | 
 41 |     virtual ~MessageDecoder() {}
 42 |     virtual Message::ptr parseFrom(Stream::ptr stream) = 0;
 43 |     virtual int32_t serializeTo(Stream::ptr stream, Message::ptr msg) = 0;
 44 | };
 45 | 
 46 | class Request : public Message {
 47 | public:
 48 |     typedef std::shared_ptr<Request> ptr;
 49 | 
 50 |     Request();
 51 | 
 52 |     uint32_t getSn() const { return m_sn;}
 53 |     uint32_t getCmd() const { return m_cmd;}
 54 | 
 55 |     void setSn(uint32_t v) { m_sn = v;}
 56 |     void setCmd(uint32_t v) { m_cmd = v;}
 57 | 
 58 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) override;
 59 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) override;
 60 | protected:
 61 |     uint32_t m_sn;
 62 |     uint32_t m_cmd;
 63 | };
 64 | 
 65 | class Response : public Message {
 66 | public:
 67 |     typedef std::shared_ptr<Response> ptr;
 68 | 
 69 |     Response();
 70 | 
 71 |     uint32_t getSn() const { return m_sn;}
 72 |     uint32_t getCmd() const { return m_cmd;}
 73 |     uint32_t getResult() const { return m_result;}
 74 |     const std::string& getResultStr() const { return m_resultStr;}
 75 | 
 76 |     void setSn(uint32_t v) { m_sn = v;}
 77 |     void setCmd(uint32_t v) { m_cmd = v;}
 78 |     void setResult(uint32_t v) { m_result = v;}
 79 |     void setResultStr(const std::string& v) { m_resultStr = v;}
 80 | 
 81 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) override;
 82 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) override;
 83 | protected:
 84 |     uint32_t m_sn;
 85 |     uint32_t m_cmd;
 86 |     uint32_t m_result;
 87 |     std::string m_resultStr;
 88 | };
 89 | 
 90 | class Notify : public Message {
 91 | public:
 92 |     typedef std::shared_ptr<Notify> ptr;
 93 |     Notify();
 94 | 
 95 |     uint32_t getNotify() const { return m_notify;}
 96 |     void setNotify(uint32_t v) { m_notify = v;}
 97 | 
 98 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) override;
 99 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) override;
100 | protected:
101 |     uint32_t m_notify;
102 | };
103 | 
104 | }
105 | 
106 | #endif
107 | 


--------------------------------------------------------------------------------
/sylar/rock/rock_protocol.h:
--------------------------------------------------------------------------------
  1 | #ifndef __SYLAR_ROCK_ROCK_PROTOCOL_H__
  2 | #define __SYLAR_ROCK_ROCK_PROTOCOL_H__
  3 | 
  4 | #include "sylar/protocol.h"
  5 | #include "google/protobuf/message.h"
  6 | 
  7 | namespace sylar {
  8 | 
  9 | class RockBody {
 10 | public:
 11 |     typedef std::shared_ptr<RockBody> ptr;
 12 |     virtual ~RockBody(){}
 13 | 
 14 |     void setBody(const std::string& v) { m_body = v;}
 15 |     const std::string& getBody() const { return m_body;}
 16 | 
 17 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray);
 18 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray);
 19 | 
 20 |     template<class T>
 21 |     std::shared_ptr<T> getAsPB() const {
 22 |         try {
 23 |             std::shared_ptr<T> data(new T);
 24 |             if(data->ParseFromString(m_body)) {
 25 |                 return data;
 26 |             }
 27 |         } catch (...) {
 28 |         }
 29 |         return nullptr;
 30 |     }
 31 | 
 32 |     template<class T>
 33 |     bool setAsPB(const T& v) {
 34 |         try {
 35 |             return v.SerializeToString(&m_body);
 36 |         } catch (...) {
 37 |         }
 38 |         return false;
 39 |     }
 40 | protected:
 41 |     std::string m_body;
 42 | };
 43 | 
 44 | class RockResponse;
 45 | class RockRequest : public Request, public RockBody {
 46 | public:
 47 |     typedef std::shared_ptr<RockRequest> ptr;
 48 | 
 49 |     std::shared_ptr<RockResponse> createResponse();
 50 | 
 51 |     virtual std::string toString() const override;
 52 |     virtual const std::string& getName() const override;
 53 |     virtual int32_t getType() const override;
 54 | 
 55 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) override;
 56 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) override;
 57 | };
 58 | 
 59 | class RockResponse : public Response, public RockBody {
 60 | public:
 61 |     typedef std::shared_ptr<RockResponse> ptr;
 62 | 
 63 |     virtual std::string toString() const override;
 64 |     virtual const std::string& getName() const override;
 65 |     virtual int32_t getType() const override;
 66 | 
 67 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) override;
 68 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) override;
 69 | };
 70 | 
 71 | class RockNotify : public Notify, public RockBody {
 72 | public:
 73 |     typedef std::shared_ptr<RockNotify> ptr;
 74 | 
 75 |     virtual std::string toString() const override;
 76 |     virtual const std::string& getName() const override;
 77 |     virtual int32_t getType() const override;
 78 | 
 79 |     virtual bool serializeToByteArray(ByteArray::ptr bytearray) override;
 80 |     virtual bool parseFromByteArray(ByteArray::ptr bytearray) override;
 81 | };
 82 | 
 83 | struct RockMsgHeader {
 84 |     RockMsgHeader();
 85 |     uint8_t magic[2];
 86 |     uint8_t version;
 87 |     uint8_t flag;
 88 |     int32_t length;
 89 | };
 90 | 
 91 | class RockMessageDecoder : public MessageDecoder {
 92 | public:
 93 |     typedef std::shared_ptr<RockMessageDecoder> ptr;
 94 | 
 95 |     virtual Message::ptr parseFrom(Stream::ptr stream) override;
 96 |     virtual int32_t serializeTo(Stream::ptr stream, Message::ptr msg) override;
 97 | };
 98 | 
 99 | }
100 | 
101 | #endif
102 | 


--------------------------------------------------------------------------------
/sylar/rock/rock_server.cc:
--------------------------------------------------------------------------------
 1 | #include "rock_server.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/module.h"
 4 | 
 5 | namespace sylar {
 6 | 
 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
 8 | 
 9 | RockServer::RockServer(const std::string& type
10 |                        ,sylar::IOManager* worker
11 |                        ,sylar::IOManager* io_worker
12 |                        ,sylar::IOManager* accept_worker)
13 |     :TcpServer(worker, io_worker, accept_worker) {
14 |     m_type = type;
15 | }
16 | 
17 | void RockServer::handleClient(Socket::ptr client) {
18 |     SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client;
19 |     sylar::RockSession::ptr session(new sylar::RockSession(client));
20 |     session->setWorker(m_worker);
21 |     ModuleMgr::GetInstance()->foreach(Module::ROCK,
22 |             [session](Module::ptr m) {
23 |         m->onConnect(session);
24 |     });
25 |     session->setDisconnectCb(
26 |         [](AsyncSocketStream::ptr stream) {
27 |              ModuleMgr::GetInstance()->foreach(Module::ROCK,
28 |                     [stream](Module::ptr m) {
29 |                 m->onDisconnect(stream);
30 |             });
31 |         }
32 |     );
33 |     session->setRequestHandler(
34 |         [](sylar::RockRequest::ptr req
35 |            ,sylar::RockResponse::ptr rsp
36 |            ,sylar::RockStream::ptr conn)->bool {
37 |             //SYLAR_LOG_INFO(g_logger) << "handleReq " << req->toString()
38 |             //                         << " body=" << req->getBody();
39 |             bool rt = false;
40 |             ModuleMgr::GetInstance()->foreach(Module::ROCK,
41 |                     [&rt, req, rsp, conn](Module::ptr m) {
42 |                 if(rt) {
43 |                     return;
44 |                 }
45 |                 rt = m->handleRequest(req, rsp, conn);
46 |             });
47 |             return rt;
48 |         }
49 |     ); 
50 |     session->setNotifyHandler(
51 |         [](sylar::RockNotify::ptr nty
52 |            ,sylar::RockStream::ptr conn)->bool {
53 |             SYLAR_LOG_INFO(g_logger) << "handleNty " << nty->toString()
54 |                                      << " body=" << nty->getBody();
55 |             bool rt = false;
56 |             ModuleMgr::GetInstance()->foreach(Module::ROCK,
57 |                     [&rt, nty, conn](Module::ptr m) {
58 |                 if(rt) {
59 |                     return;
60 |                 }
61 |                 rt = m->handleNotify(nty, conn);
62 |             });
63 |             return rt;
64 |         }
65 |     );
66 |     session->start();
67 | }
68 | 
69 | }
70 | 


--------------------------------------------------------------------------------
/sylar/rock/rock_server.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ROCK_SERVER_H__
 2 | #define __SYLAR_ROCK_SERVER_H__
 3 | 
 4 | #include "sylar/rock/rock_stream.h"
 5 | #include "sylar/tcp_server.h"
 6 | 
 7 | namespace sylar {
 8 | 
 9 | class RockServer : public TcpServer {
10 | public:
11 |     typedef std::shared_ptr<RockServer> ptr;
12 |     RockServer(const std::string& type = "rock"
13 |                ,sylar::IOManager* worker = sylar::IOManager::GetThis()
14 |                ,sylar::IOManager* io_worker = sylar::IOManager::GetThis()
15 |                ,sylar::IOManager* accept_worker = sylar::IOManager::GetThis());
16 | 
17 | protected:
18 |     virtual void handleClient(Socket::ptr client) override;
19 | };
20 | 
21 | }
22 | 
23 | #endif
24 | 


--------------------------------------------------------------------------------
/sylar/singleton.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file singleton.h
 3 |  * @brief 单例模式封装
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-05-18
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef __SYLAR_SINGLETON_H__
10 | #define __SYLAR_SINGLETON_H__
11 | 
12 | #include <memory>
13 | 
14 | namespace sylar {
15 | 
16 | namespace {
17 | 
18 | template<class T, class X, int N>
19 | T& GetInstanceX() {
20 |     static T v;
21 |     return v;
22 | }
23 | 
24 | template<class T, class X, int N>
25 | std::shared_ptr<T> GetInstancePtr() {
26 |     static std::shared_ptr<T> v(new T);
27 |     return v;
28 | }
29 | 
30 | 
31 | }
32 | 
33 | /**
34 |  * @brief 单例模式封装类
35 |  * @details T 类型
36 |  *          X 为了创造多个实例对应的Tag
37 |  *          N 同一个Tag创造多个实例索引
38 |  */
39 | template<class T, class X = void, int N = 0>
40 | class Singleton {
41 | public:
42 |     /**
43 |      * @brief 返回单例裸指针
44 |      */
45 |     static T* GetInstance() {
46 |         static T v;
47 |         return &v;
48 |         //return &GetInstanceX<T, X, N>();
49 |     }
50 | };
51 | 
52 | /**
53 |  * @brief 单例模式智能指针封装类
54 |  * @details T 类型
55 |  *          X 为了创造多个实例对应的Tag
56 |  *          N 同一个Tag创造多个实例索引
57 |  */
58 | template<class T, class X = void, int N = 0>
59 | class SingletonPtr {
60 | public:
61 |     /**
62 |      * @brief 返回单例智能指针
63 |      */
64 |     static std::shared_ptr<T> GetInstance() {
65 |         static std::shared_ptr<T> v(new T);
66 |         return v;
67 |         //return GetInstancePtr<T, X, N>();
68 |     }
69 | };
70 | 
71 | }
72 | 
73 | #endif
74 | 


--------------------------------------------------------------------------------
/sylar/stream.cc:
--------------------------------------------------------------------------------
 1 | #include "stream.h"
 2 | 
 3 | namespace sylar {
 4 | 
 5 | int Stream::readFixSize(void* buffer, size_t length) {
 6 |     size_t offset = 0;
 7 |     int64_t left = length;
 8 |     while(left > 0) {
 9 |         int64_t len = read((char*)buffer + offset, left);
10 |         if(len <= 0) {
11 |             return len;
12 |         }
13 |         offset += len;
14 |         left -= len;
15 |     }
16 |     return length;
17 | }
18 | 
19 | int Stream::readFixSize(ByteArray::ptr ba, size_t length) {
20 |     int64_t left = length;
21 |     while(left > 0) {
22 |         int64_t len = read(ba, left);
23 |         if(len <= 0) {
24 |             return len;
25 |         }
26 |         left -= len;
27 |     }
28 |     return length;
29 | }
30 | 
31 | int Stream::writeFixSize(const void* buffer, size_t length) {
32 |     size_t offset = 0;
33 |     int64_t left = length;
34 |     while(left > 0) {
35 |         int64_t len = write((const char*)buffer + offset, left);
36 |         if(len <= 0) {
37 |             return len;
38 |         }
39 |         offset += len;
40 |         left -= len;
41 |     }
42 |     return length;
43 | 
44 | }
45 | 
46 | int Stream::writeFixSize(ByteArray::ptr ba, size_t length) {
47 |     int64_t left = length;
48 |     while(left > 0) {
49 |         int64_t len = write(ba, left);
50 |         if(len <= 0) {
51 |             return len;
52 |         }
53 |         left -= len;
54 |     }
55 |     return length;
56 | }
57 | 
58 | }
59 | 


--------------------------------------------------------------------------------
/sylar/stream.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file stream.h
  3 |  * @brief 流接口
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-06-06
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | #ifndef __SYLAR_STREAM_H__
 10 | #define __SYLAR_STREAM_H__
 11 | 
 12 | #include <memory>
 13 | #include "bytearray.h"
 14 | 
 15 | namespace sylar {
 16 | 
 17 | /**
 18 |  * @brief 流结构
 19 |  */
 20 | class Stream {
 21 | public:
 22 |     typedef std::shared_ptr<Stream> ptr;
 23 |     /**
 24 |      * @brief 析构函数
 25 |      */
 26 |     virtual ~Stream() {}
 27 | 
 28 |     /**
 29 |      * @brief 读数据
 30 |      * @param[out] buffer 接收数据的内存
 31 |      * @param[in] length 接收数据的内存大小
 32 |      * @return
 33 |      *      @retval >0 返回接收到的数据的实际大小
 34 |      *      @retval =0 被关闭
 35 |      *      @retval <0 出现流错误
 36 |      */
 37 |     virtual int read(void* buffer, size_t length) = 0;
 38 | 
 39 |     /**
 40 |      * @brief 读数据
 41 |      * @param[out] ba 接收数据的ByteArray
 42 |      * @param[in] length 接收数据的内存大小
 43 |      * @return
 44 |      *      @retval >0 返回接收到的数据的实际大小
 45 |      *      @retval =0 被关闭
 46 |      *      @retval <0 出现流错误
 47 |      */
 48 |     virtual int read(ByteArray::ptr ba, size_t length) = 0;
 49 | 
 50 |     /**
 51 |      * @brief 读固定长度的数据
 52 |      * @param[out] buffer 接收数据的内存
 53 |      * @param[in] length 接收数据的内存大小
 54 |      * @return
 55 |      *      @retval >0 返回接收到的数据的实际大小
 56 |      *      @retval =0 被关闭
 57 |      *      @retval <0 出现流错误
 58 |      */
 59 |     virtual int readFixSize(void* buffer, size_t length);
 60 | 
 61 |     /**
 62 |      * @brief 读固定长度的数据
 63 |      * @param[out] ba 接收数据的ByteArray
 64 |      * @param[in] length 接收数据的内存大小
 65 |      * @return
 66 |      *      @retval >0 返回接收到的数据的实际大小
 67 |      *      @retval =0 被关闭
 68 |      *      @retval <0 出现流错误
 69 |      */
 70 |     virtual int readFixSize(ByteArray::ptr ba, size_t length);
 71 | 
 72 |     /**
 73 |      * @brief 写数据
 74 |      * @param[in] buffer 写数据的内存
 75 |      * @param[in] length 写入数据的内存大小
 76 |      * @return
 77 |      *      @retval >0 返回写入到的数据的实际大小
 78 |      *      @retval =0 被关闭
 79 |      *      @retval <0 出现流错误
 80 |      */
 81 |     virtual int write(const void* buffer, size_t length) = 0;
 82 | 
 83 |     /**
 84 |      * @brief 写数据
 85 |      * @param[in] ba 写数据的ByteArray
 86 |      * @param[in] length 写入数据的内存大小
 87 |      * @return
 88 |      *      @retval >0 返回写入到的数据的实际大小
 89 |      *      @retval =0 被关闭
 90 |      *      @retval <0 出现流错误
 91 |      */
 92 |     virtual int write(ByteArray::ptr ba, size_t length) = 0;
 93 | 
 94 |     /**
 95 |      * @brief 写固定长度的数据
 96 |      * @param[in] buffer 写数据的内存
 97 |      * @param[in] length 写入数据的内存大小
 98 |      * @return
 99 |      *      @retval >0 返回写入到的数据的实际大小
100 |      *      @retval =0 被关闭
101 |      *      @retval <0 出现流错误
102 |      */
103 |     virtual int writeFixSize(const void* buffer, size_t length);
104 | 
105 |     /**
106 |      * @brief 写固定长度的数据
107 |      * @param[in] ba 写数据的ByteArray
108 |      * @param[in] length 写入数据的内存大小
109 |      * @return
110 |      *      @retval >0 返回写入到的数据的实际大小
111 |      *      @retval =0 被关闭
112 |      *      @retval <0 出现流错误
113 |      */
114 |     virtual int writeFixSize(ByteArray::ptr ba, size_t length);
115 | 
116 |     /**
117 |      * @brief 关闭流
118 |      */
119 |     virtual void close() = 0;
120 | };
121 | 
122 | }
123 | 
124 | #endif
125 | 


--------------------------------------------------------------------------------
/sylar/streams/socket_stream.cc:
--------------------------------------------------------------------------------
 1 | #include "socket_stream.h"
 2 | #include "sylar/util.h"
 3 | 
 4 | namespace sylar {
 5 | 
 6 | SocketStream::SocketStream(Socket::ptr sock, bool owner)
 7 |     :m_socket(sock)
 8 |     ,m_owner(owner) {
 9 | }
10 | 
11 | SocketStream::~SocketStream() {
12 |     if(m_owner && m_socket) {
13 |         m_socket->close();
14 |     }
15 | }
16 | 
17 | bool SocketStream::isConnected() const {
18 |     return m_socket && m_socket->isConnected();
19 | }
20 | 
21 | int SocketStream::read(void* buffer, size_t length) {
22 |     if(!isConnected()) {
23 |         return -1;
24 |     }
25 |     return m_socket->recv(buffer, length);
26 | }
27 | 
28 | int SocketStream::read(ByteArray::ptr ba, size_t length) {
29 |     if(!isConnected()) {
30 |         return -1;
31 |     }
32 |     std::vector<iovec> iovs;
33 |     ba->getWriteBuffers(iovs, length);
34 |     int rt = m_socket->recv(&iovs[0], iovs.size());
35 |     if(rt > 0) {
36 |         ba->setPosition(ba->getPosition() + rt);
37 |     }
38 |     return rt;
39 | }
40 | 
41 | int SocketStream::write(const void* buffer, size_t length) {
42 |     if(!isConnected()) {
43 |         return -1;
44 |     }
45 |     return m_socket->send(buffer, length);
46 | }
47 | 
48 | int SocketStream::write(ByteArray::ptr ba, size_t length) {
49 |     if(!isConnected()) {
50 |         return -1;
51 |     }
52 |     std::vector<iovec> iovs;
53 |     ba->getReadBuffers(iovs, length);
54 |     int rt = m_socket->send(&iovs[0], iovs.size());
55 |     if(rt > 0) {
56 |         ba->setPosition(ba->getPosition() + rt);
57 |     }
58 |     return rt;
59 | }
60 | 
61 | void SocketStream::close() {
62 |     if(m_socket) {
63 |         m_socket->close();
64 |     }
65 | }
66 | 
67 | Address::ptr SocketStream::getRemoteAddress() {
68 |     if(m_socket) {
69 |         return m_socket->getRemoteAddress();
70 |     }
71 |     return nullptr;
72 | }
73 | 
74 | Address::ptr SocketStream::getLocalAddress() {
75 |     if(m_socket) {
76 |         return m_socket->getLocalAddress();
77 |     }
78 |     return nullptr;
79 | }
80 | 
81 | std::string SocketStream::getRemoteAddressString() {
82 |     auto addr = getRemoteAddress();
83 |     if(addr) {
84 |         return addr->toString();
85 |     }
86 |     return "";
87 | }
88 | 
89 | std::string SocketStream::getLocalAddressString() {
90 |     auto addr = getLocalAddress();
91 |     if(addr) {
92 |         return addr->toString();
93 |     }
94 |     return "";
95 | }
96 | 
97 | }
98 | 


--------------------------------------------------------------------------------
/sylar/streams/socket_stream.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file socket_stream.h
  3 |  * @brief Socket流式接口封装
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-06-06
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | #ifndef __SYLAR_SOCKET_STREAM_H__
 10 | #define __SYLAR_SOCKET_STREAM_H__
 11 | 
 12 | #include "sylar/stream.h"
 13 | #include "sylar/socket.h"
 14 | #include "sylar/mutex.h"
 15 | #include "sylar/iomanager.h"
 16 | 
 17 | namespace sylar {
 18 | 
 19 | /**
 20 |  * @brief Socket流
 21 |  */
 22 | class SocketStream : public Stream {
 23 | public:
 24 |     typedef std::shared_ptr<SocketStream> ptr;
 25 | 
 26 |     /**
 27 |      * @brief 构造函数
 28 |      * @param[in] sock Socket类
 29 |      * @param[in] owner 是否完全控制
 30 |      */
 31 |     SocketStream(Socket::ptr sock, bool owner = true);
 32 | 
 33 |     /**
 34 |      * @brief 析构函数
 35 |      * @details 如果m_owner=true,则close
 36 |      */
 37 |     ~SocketStream();
 38 | 
 39 |     /**
 40 |      * @brief 读取数据
 41 |      * @param[out] buffer 待接收数据的内存
 42 |      * @param[in] length 待接收数据的内存长度
 43 |      * @return
 44 |      *      @retval >0 返回实际接收到的数据长度
 45 |      *      @retval =0 socket被远端关闭
 46 |      *      @retval <0 socket错误
 47 |      */
 48 |     virtual int read(void* buffer, size_t length) override;
 49 | 
 50 |     /**
 51 |      * @brief 读取数据
 52 |      * @param[out] ba 接收数据的ByteArray
 53 |      * @param[in] length 待接收数据的内存长度
 54 |      * @return
 55 |      *      @retval >0 返回实际接收到的数据长度
 56 |      *      @retval =0 socket被远端关闭
 57 |      *      @retval <0 socket错误
 58 |      */
 59 |     virtual int read(ByteArray::ptr ba, size_t length) override;
 60 | 
 61 |     /**
 62 |      * @brief 写入数据
 63 |      * @param[in] buffer 待发送数据的内存
 64 |      * @param[in] length 待发送数据的内存长度
 65 |      * @return
 66 |      *      @retval >0 返回实际接收到的数据长度
 67 |      *      @retval =0 socket被远端关闭
 68 |      *      @retval <0 socket错误
 69 |      */
 70 |     virtual int write(const void* buffer, size_t length) override;
 71 | 
 72 |     /**
 73 |      * @brief 写入数据
 74 |      * @param[in] ba 待发送数据的ByteArray
 75 |      * @param[in] length 待发送数据的内存长度
 76 |      * @return
 77 |      *      @retval >0 返回实际接收到的数据长度
 78 |      *      @retval =0 socket被远端关闭
 79 |      *      @retval <0 socket错误
 80 |      */
 81 |     virtual int write(ByteArray::ptr ba, size_t length) override;
 82 | 
 83 |     /**
 84 |      * @brief 关闭socket
 85 |      */
 86 |     virtual void close() override;
 87 | 
 88 |     /**
 89 |      * @brief 返回Socket类
 90 |      */
 91 |     Socket::ptr getSocket() const { return m_socket;}
 92 | 
 93 |     /**
 94 |      * @brief 返回是否连接
 95 |      */
 96 |     bool isConnected() const;
 97 | 
 98 |     Address::ptr getRemoteAddress();
 99 |     Address::ptr getLocalAddress();
100 |     std::string getRemoteAddressString();
101 |     std::string getLocalAddressString();
102 | protected:
103 |     /// Socket类
104 |     Socket::ptr m_socket;
105 |     /// 是否主控
106 |     bool m_owner;
107 | };
108 | 
109 | }
110 | 
111 | #endif
112 | 


--------------------------------------------------------------------------------
/sylar/streams/zlib_stream.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_STREAMS_ZLIB_STREAM_H__
 2 | #define __SYLAR_STREAMS_ZLIB_STREAM_H__
 3 | 
 4 | #include "sylar/stream.h"
 5 | #include <sys/uio.h>
 6 | #include <zlib.h>
 7 | #include <stdint.h>
 8 | #include <vector>
 9 | #include <string>
10 | #include <memory>
11 | 
12 | namespace sylar {
13 | 
14 | class ZlibStream : public Stream {
15 | public:
16 |     typedef std::shared_ptr<ZlibStream> ptr;
17 | 
18 |     enum Type {
19 |         ZLIB,
20 |         DEFLATE,
21 |         GZIP
22 |     };
23 | 
24 |     enum Strategy {
25 |         DEFAULT = Z_DEFAULT_STRATEGY,
26 |         FILTERED = Z_FILTERED,
27 |         HUFFMAN = Z_HUFFMAN_ONLY,
28 |         FIXED = Z_FIXED,
29 |         RLE = Z_RLE
30 |     };
31 | 
32 |     enum CompressLevel {
33 |         NO_COMPRESSION = Z_NO_COMPRESSION,
34 |         BEST_SPEED = Z_BEST_SPEED,
35 |         BEST_COMPRESSION = Z_BEST_COMPRESSION,
36 |         DEFAULT_COMPRESSION = Z_DEFAULT_COMPRESSION
37 |     };
38 | 
39 |     static ZlibStream::ptr CreateGzip(bool encode, uint32_t buff_size = 4096);
40 |     static ZlibStream::ptr CreateZlib(bool encode, uint32_t buff_size = 4096);
41 |     static ZlibStream::ptr CreateDeflate(bool encode, uint32_t buff_size = 4096);
42 |     static ZlibStream::ptr Create(bool encode, uint32_t buff_size = 4096,
43 |             Type type = DEFLATE, int level = DEFAULT_COMPRESSION, int window_bits = 15
44 |             ,int memlevel = 8, Strategy strategy = DEFAULT);
45 | 
46 |     ZlibStream(bool encode, uint32_t buff_size = 4096);
47 |     ~ZlibStream();
48 | 
49 |     virtual int read(void* buffer, size_t length) override;
50 |     virtual int read(ByteArray::ptr ba, size_t length) override;
51 |     virtual int write(const void* buffer, size_t length) override;
52 |     virtual int write(ByteArray::ptr ba, size_t length) override;
53 |     virtual void close() override;
54 | 
55 |     int flush();
56 | 
57 |     bool isFree() const { return m_free;}
58 |     void setFree(bool v) { m_free = v;}
59 | 
60 |     bool isEncode() const { return m_encode;}
61 |     void setEndcode(bool v) { m_encode = v;}
62 | 
63 |     std::vector<iovec>& getBuffers() { return m_buffs;}
64 |     std::string getResult() const;
65 |     sylar::ByteArray::ptr getByteArray();
66 | private:
67 |     int init(Type type = DEFLATE, int level = DEFAULT_COMPRESSION
68 |              ,int window_bits = 15, int memlevel = 8, Strategy strategy = DEFAULT);
69 | 
70 |     int encode(const iovec* v, const uint64_t& size, bool finish);
71 |     int decode(const iovec* v, const uint64_t& size, bool finish);
72 | private:
73 |     z_stream m_zstream;
74 |     uint32_t m_buffSize;
75 |     bool m_encode;
76 |     bool m_free;
77 |     std::vector<iovec> m_buffs;
78 | };
79 | 
80 | }
81 | 
82 | #endif
83 | 


--------------------------------------------------------------------------------
/sylar/sylar.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file sylar.h
 3 |  * @brief sylar头文件
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-05-24
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef __SYLAR_SYLAR_H__
10 | #define __SYLAR_SYLAR_H__
11 | 
12 | #include "address.h"
13 | #include "application.h"
14 | #include "bytearray.h"
15 | #include "config.h"
16 | #include "daemon.h"
17 | #include "endian.h"
18 | #include "env.h"
19 | #include "fd_manager.h"
20 | #include "fiber.h"
21 | #include "hook.h"
22 | #include "iomanager.h"
23 | #include "library.h"
24 | #include "log.h"
25 | #include "macro.h"
26 | #include "module.h"
27 | #include "mutex.h"
28 | #include "noncopyable.h"
29 | #include "protocol.h"
30 | #include "scheduler.h"
31 | #include "singleton.h"
32 | #include "socket.h"
33 | #include "stream.h"
34 | #include "tcp_server.h"
35 | #include "thread.h"
36 | #include "timer.h"
37 | #include "uri.h"
38 | #include "util.h"
39 | #include "worker.h"
40 | 
41 | #include "db/db.h"
42 | #include "db/mysql.h"
43 | #include "db/sqlite3.h"
44 | 
45 | #include "ds/cache_status.h"
46 | #include "ds/lru_cache.h"
47 | #include "ds/timed_cache.h"
48 | #include "ds/timed_lru_cache.h"
49 | 
50 | #include "email/email.h"
51 | #include "email/smtp.h"
52 | 
53 | #include "http/http.h"
54 | #include "http/http11_common.h"
55 | #include "http/http11_parser.h"
56 | #include "http/http_connection.h"
57 | #include "http/http_parser.h"
58 | #include "http/http_server.h"
59 | #include "http/http_session.h"
60 | #include "http/httpclient_parser.h"
61 | #include "http/servlet.h"
62 | #include "http/session_data.h"
63 | #include "http/ws_connection.h"
64 | #include "http/ws_server.h"
65 | #include "http/ws_servlet.h"
66 | #include "http/ws_session.h"
67 | 
68 | #include "rock/rock_protocol.h"
69 | #include "rock/rock_server.h"
70 | #include "rock/rock_stream.h"
71 | 
72 | #include "streams/async_socket_stream.h"
73 | #include "streams/load_balance.h"
74 | #include "streams/socket_stream.h"
75 | #include "streams/zlib_stream.h"
76 | 
77 | #include "util/crypto_util.h"
78 | #include "util/hash_util.h"
79 | #include "util/json_util.h"
80 | 
81 | #endif
82 | 


--------------------------------------------------------------------------------
/sylar/test.proto:
--------------------------------------------------------------------------------
1 | package test;
2 | 
3 | message Hello {
4 |     optional string name = 1;
5 | }
6 | 


--------------------------------------------------------------------------------
/sylar/thread.cc:
--------------------------------------------------------------------------------
 1 | #include "thread.h"
 2 | #include "log.h"
 3 | #include "util.h"
 4 | 
 5 | namespace sylar {
 6 | 
 7 | static thread_local Thread* t_thread = nullptr;
 8 | static thread_local std::string t_thread_name = "UNKNOW";
 9 | 
10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
11 | 
12 | Thread* Thread::GetThis() {
13 |     return t_thread;
14 | }
15 | 
16 | const std::string& Thread::GetName() {
17 |     return t_thread_name;
18 | }
19 | 
20 | void Thread::SetName(const std::string& name) {
21 |     if(name.empty()) {
22 |         return;
23 |     }
24 |     if(t_thread) {
25 |         t_thread->m_name = name;
26 |     }
27 |     t_thread_name = name;
28 | }
29 | 
30 | Thread::Thread(std::function<void()> cb, const std::string& name)
31 |     :m_cb(cb)
32 |     ,m_name(name) {
33 |     if(name.empty()) {
34 |         m_name = "UNKNOW";
35 |     }
36 |     int rt = pthread_create(&m_thread, nullptr, &Thread::run, this);
37 |     if(rt) {
38 |         SYLAR_LOG_ERROR(g_logger) << "pthread_create thread fail, rt=" << rt
39 |             << " name=" << name;
40 |         throw std::logic_error("pthread_create error");
41 |     }
42 |     m_semaphore.wait();
43 | }
44 | 
45 | Thread::~Thread() {
46 |     if(m_thread) {
47 |         pthread_detach(m_thread);
48 |     }
49 | }
50 | 
51 | void Thread::join() {
52 |     if(m_thread) {
53 |         int rt = pthread_join(m_thread, nullptr);
54 |         if(rt) {
55 |             SYLAR_LOG_ERROR(g_logger) << "pthread_join thread fail, rt=" << rt
56 |                 << " name=" << m_name;
57 |             throw std::logic_error("pthread_join error");
58 |         }
59 |         m_thread = 0;
60 |     }
61 | }
62 | 
63 | void* Thread::run(void* arg) {
64 |     Thread* thread = (Thread*)arg;
65 |     t_thread = thread;
66 |     t_thread_name = thread->m_name;
67 |     thread->m_id = sylar::GetThreadId();
68 |     pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str());
69 | 
70 |     std::function<void()> cb;
71 |     cb.swap(thread->m_cb);
72 | 
73 |     thread->m_semaphore.notify();
74 | 
75 |     cb();
76 |     return 0;
77 | }
78 | 
79 | }
80 | 


--------------------------------------------------------------------------------
/sylar/thread.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @file thread.h
 3 |  * @brief 线程相关的封装
 4 |  * @author sylar.yin
 5 |  * @email 564628276@qq.com
 6 |  * @date 2019-05-31
 7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
 8 |  */
 9 | #ifndef __SYLAR_THREAD_H__
10 | #define __SYLAR_THREAD_H__
11 | 
12 | #include "mutex.h"
13 | 
14 | namespace sylar {
15 | 
16 | /**
17 |  * @brief 线程类
18 |  */
19 | class Thread : Noncopyable {
20 | public:
21 |     /// 线程智能指针类型
22 |     typedef std::shared_ptr<Thread> ptr;
23 | 
24 |     /**
25 |      * @brief 构造函数
26 |      * @param[in] cb 线程执行函数
27 |      * @param[in] name 线程名称
28 |      */
29 |     Thread(std::function<void()> cb, const std::string& name);
30 | 
31 |     /**
32 |      * @brief 析构函数
33 |      */
34 |     ~Thread();
35 | 
36 |     /**
37 |      * @brief 线程ID
38 |      */
39 |     pid_t getId() const { return m_id;}
40 | 
41 |     /**
42 |      * @brief 线程名称
43 |      */
44 |     const std::string& getName() const { return m_name;}
45 | 
46 |     /**
47 |      * @brief 等待线程执行完成
48 |      */
49 |     void join();
50 | 
51 |     /**
52 |      * @brief 获取当前的线程指针
53 |      */
54 |     static Thread* GetThis();
55 | 
56 |     /**
57 |      * @brief 获取当前的线程名称
58 |      */
59 |     static const std::string& GetName();
60 | 
61 |     /**
62 |      * @brief 设置当前线程名称
63 |      * @param[in] name 线程名称
64 |      */
65 |     static void SetName(const std::string& name);
66 | private:
67 | 
68 |     /**
69 |      * @brief 线程执行函数
70 |      */
71 |     static void* run(void* arg);
72 | private:
73 |     /// 线程id
74 |     pid_t m_id = -1;
75 |     /// 线程结构
76 |     pthread_t m_thread = 0;
77 |     /// 线程执行函数
78 |     std::function<void()> m_cb;
79 |     /// 线程名称
80 |     std::string m_name;
81 |     /// 信号量
82 |     Semaphore m_semaphore;
83 | };
84 | 
85 | }
86 | 
87 | #endif
88 | 


--------------------------------------------------------------------------------
/sylar/util/crypto_util.h:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @file crypto_util.h
  3 |  * @brief 加解密工具函数
  4 |  * @author sylar.yin
  5 |  * @email 564628276@qq.com
  6 |  * @date 2019-07-02
  7 |  * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top)
  8 |  */
  9 | #ifndef __SYLAR_UTIL_CRYPTO_UTIL_H__
 10 | #define __SYLAR_UTIL_CRYPTO_UTIL_H__
 11 | 
 12 | #include <openssl/ssl.h>
 13 | #include <openssl/evp.h>
 14 | #include <stdint.h>
 15 | #include <memory>
 16 | #include <string>
 17 | 
 18 | namespace sylar {
 19 | 
 20 | class CryptoUtil {
 21 | public:
 22 |     //key 32字节
 23 |     static int32_t AES256Ecb(const void* key
 24 |                             ,const void* in
 25 |                             ,int32_t in_len
 26 |                             ,void* out
 27 |                             ,bool encode);
 28 | 
 29 |     //key 16字节
 30 |     static int32_t AES128Ecb(const void* key
 31 |                             ,const void* in
 32 |                             ,int32_t in_len
 33 |                             ,void* out
 34 |                             ,bool encode);
 35 | 
 36 |     //key 32字节
 37 |     //iv 16字节
 38 |     static int32_t AES256Cbc(const void* key, const void* iv
 39 |                             ,const void* in, int32_t in_len
 40 |                             ,void* out, bool encode);
 41 | 
 42 |     //key 16字节
 43 |     //iv 16字节
 44 |     static int32_t AES128Cbc(const void* key, const void* iv
 45 |                             ,const void* in, int32_t in_len
 46 |                             ,void* out, bool encode);
 47 | 
 48 |     static int32_t Crypto(const EVP_CIPHER* cipher, bool enc
 49 |                           ,const void* key, const void* iv
 50 |                           ,const void* in, int32_t in_len
 51 |                           ,void* out, int32_t* out_len);
 52 | };
 53 | 
 54 | 
 55 | class RSACipher {
 56 | public:
 57 |     typedef std::shared_ptr<RSACipher> ptr;
 58 | 
 59 |     static int32_t GenerateKey(const std::string& pubkey_file
 60 |                                ,const std::string& prikey_file
 61 |                                ,uint32_t length = 1024);
 62 | 
 63 |     static RSACipher::ptr Create(const std::string& pubkey_file
 64 |                                 ,const std::string& prikey_file);
 65 | 
 66 |     RSACipher();
 67 |     ~RSACipher();
 68 | 
 69 |     int32_t privateEncrypt(const void* from, int flen,
 70 |                            void* to, int padding = RSA_NO_PADDING);
 71 |     int32_t publicEncrypt(const void* from, int flen,
 72 |                            void* to, int padding = RSA_NO_PADDING);
 73 |     int32_t privateDecrypt(const void* from, int flen,
 74 |                            void* to, int padding = RSA_NO_PADDING);
 75 |     int32_t publicDecrypt(const void* from, int flen,
 76 |                            void* to, int padding = RSA_NO_PADDING);
 77 |     int32_t privateEncrypt(const void* from, int flen,
 78 |                            std::string& to, int padding = RSA_NO_PADDING);
 79 |     int32_t publicEncrypt(const void* from, int flen,
 80 |                            std::string& to, int padding = RSA_NO_PADDING);
 81 |     int32_t privateDecrypt(const void* from, int flen,
 82 |                            std::string& to, int padding = RSA_NO_PADDING);
 83 |     int32_t publicDecrypt(const void* from, int flen,
 84 |                            std::string& to, int padding = RSA_NO_PADDING);
 85 | 
 86 | 
 87 |     const std::string& getPubkeyStr() const { return m_pubkeyStr;}
 88 |     const std::string& getPrikeyStr() const { return m_prikeyStr;}
 89 | 
 90 |     int32_t getPubRSASize();
 91 |     int32_t getPriRSASize();
 92 | private:
 93 |     RSA* m_pubkey;
 94 |     RSA* m_prikey;
 95 |     std::string m_pubkeyStr;
 96 |     std::string m_prikeyStr;
 97 | };
 98 | 
 99 | 
100 | }
101 | 
102 | #endif
103 | 


--------------------------------------------------------------------------------
/sylar/util/hash_util.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_UTIL_HASH_UTIL_H__
 2 | #define __SYLAR_UTIL_HASH_UTIL_H__
 3 | 
 4 | #include <stdint.h>
 5 | #include <string>
 6 | #include <vector>
 7 | 
 8 | namespace sylar {
 9 | 
10 | uint32_t murmur3_hash(const char * str, const uint32_t & seed = 1060627423);
11 | uint64_t murmur3_hash64(const char * str, const uint32_t & seed = 1060627423, const uint32_t& seed2 = 1050126127);
12 | uint32_t murmur3_hash(const void* str, const uint32_t& size, const uint32_t & seed = 1060627423);
13 | uint64_t murmur3_hash64(const void* str, const uint32_t& size,  const uint32_t & seed = 1060627423, const uint32_t& seed2 = 1050126127);
14 | uint32_t quick_hash(const char * str);
15 | uint32_t quick_hash(const void* str, uint32_t size);
16 | 
17 | std::string base64decode(const std::string &src);
18 | std::string base64encode(const std::string &data);
19 | std::string base64encode(const void *data, size_t len);
20 | 
21 | // Returns result in hex
22 | std::string md5(const std::string &data);
23 | std::string sha1(const std::string &data);
24 | // Returns result in blob
25 | std::string md5sum(const std::string &data);
26 | std::string md5sum(const void *data, size_t len);
27 | std::string sha0sum(const std::string &data);
28 | std::string sha0sum(const void *data, size_t len);
29 | std::string sha1sum(const std::string &data);
30 | std::string sha1sum(const void *data, size_t len);
31 | std::string hmac_md5(const std::string &text, const std::string &key);
32 | std::string hmac_sha1(const std::string &text, const std::string &key);
33 | std::string hmac_sha256(const std::string &text, const std::string &key);
34 | 
35 | /// Output must be of size len * 2, and will *not* be null-terminated
36 | void hexstring_from_data(const void *data, size_t len, char *output);
37 | std::string hexstring_from_data(const void *data, size_t len);
38 | std::string hexstring_from_data(const std::string &data);
39 | 
40 | /// Output must be of size length / 2, and will *not* be null-terminated
41 | /// std::invalid_argument will be thrown if hexstring is not hex
42 | void data_from_hexstring(const char *hexstring, size_t length, void *output);
43 | std::string data_from_hexstring(const char *hexstring, size_t length);
44 | std::string data_from_hexstring(const std::string &data);
45 | 
46 | std::string replace(const std::string &str, char find, char replaceWith);
47 | std::string replace(const std::string &str, char find, const std::string &replaceWith);
48 | std::string replace(const std::string &str, const std::string &find, const std::string &replaceWith);
49 | 
50 | std::vector<std::string> split(const std::string &str, char delim, size_t max = ~0);
51 | std::vector<std::string> split(const std::string &str, const char *delims, size_t max = ~0);
52 | 
53 | std::string random_string(size_t len
54 |         ,const std::string& chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
55 | }
56 | 
57 | #endif
58 | 


--------------------------------------------------------------------------------
/sylar/util/json_util.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_UTIL_JSON_UTIL_H__
 2 | #define __SYLAR_UTIL_JSON_UTIL_H__
 3 | 
 4 | #include <string>
 5 | #include <iostream>
 6 | #include <json/json.h>
 7 | 
 8 | namespace sylar {
 9 | 
10 | class JsonUtil {
11 | public:
12 |     static bool NeedEscape(const std::string& v);
13 |     static std::string Escape(const std::string& v);
14 |     static std::string GetString(const Json::Value& json
15 |                           ,const std::string& name
16 |                           ,const std::string& default_value = "");
17 |     static double GetDouble(const Json::Value& json
18 |                      ,const std::string& name
19 |                      ,double default_value = 0);
20 |     static int32_t GetInt32(const Json::Value& json
21 |                      ,const std::string& name
22 |                      ,int32_t default_value = 0);
23 |     static uint32_t GetUint32(const Json::Value& json
24 |                        ,const std::string& name
25 |                        ,uint32_t default_value = 0);
26 |     static int64_t GetInt64(const Json::Value& json
27 |                      ,const std::string& name
28 |                      ,int64_t default_value = 0);
29 |     static uint64_t GetUint64(const Json::Value& json
30 |                        ,const std::string& name
31 |                        ,uint64_t default_value = 0);
32 |     static bool FromString(Json::Value& json, const std::string& v);
33 |     static std::string ToString(const Json::Value& json);
34 | };
35 | 
36 | }
37 | 
38 | #endif
39 | 


--------------------------------------------------------------------------------
/sylar/worker.cc:
--------------------------------------------------------------------------------
  1 | #include "worker.h"
  2 | #include "config.h"
  3 | #include "util.h"
  4 | 
  5 | namespace sylar {
  6 | 
  7 | static sylar::ConfigVar<std::map<std::string, std::map<std::string, std::string> > >::ptr g_worker_config
  8 |     = sylar::Config::Lookup("workers", std::map<std::string, std::map<std::string, std::string> >(), "worker config");
  9 | 
 10 | WorkerGroup::WorkerGroup(uint32_t batch_size, sylar::Scheduler* s)
 11 |     :m_batchSize(batch_size)
 12 |     ,m_finish(false)
 13 |     ,m_scheduler(s)
 14 |     ,m_sem(batch_size) {
 15 | }
 16 | 
 17 | WorkerGroup::~WorkerGroup() {
 18 |     waitAll();
 19 | }
 20 | 
 21 | void WorkerGroup::schedule(std::function<void()> cb, int thread) {
 22 |     m_sem.wait();
 23 |     m_scheduler->schedule(std::bind(&WorkerGroup::doWork
 24 |                           ,shared_from_this(), cb), thread);
 25 | }
 26 | 
 27 | void WorkerGroup::doWork(std::function<void()> cb) {
 28 |     cb();
 29 |     m_sem.notify();
 30 | }
 31 | 
 32 | void WorkerGroup::waitAll() {
 33 |     if(!m_finish) {
 34 |         m_finish = true;
 35 |         for(uint32_t i = 0; i < m_batchSize; ++i) {
 36 |             m_sem.wait();
 37 |         }
 38 |     }
 39 | }
 40 | 
 41 | WorkerManager::WorkerManager()
 42 |     :m_stop(false) {
 43 | }
 44 | 
 45 | void WorkerManager::add(Scheduler::ptr s) {
 46 |     m_datas[s->getName()].push_back(s);
 47 | }
 48 | 
 49 | Scheduler::ptr WorkerManager::get(const std::string& name) {
 50 |     auto it = m_datas.find(name);
 51 |     if(it == m_datas.end()) {
 52 |         return nullptr;
 53 |     }
 54 |     if(it->second.size() == 1) {
 55 |         return it->second[0];
 56 |     }
 57 |     return it->second[rand() % it->second.size()];
 58 | }
 59 | 
 60 | IOManager::ptr WorkerManager::getAsIOManager(const std::string& name) {
 61 |     return std::dynamic_pointer_cast<IOManager>(get(name));
 62 | }
 63 | 
 64 | bool WorkerManager::init(const std::map<std::string, std::map<std::string, std::string> >& v) {
 65 |     for(auto& i : v) {
 66 |         std::string name = i.first;
 67 |         int32_t thread_num = sylar::GetParamValue(i.second, "thread_num", 1);
 68 |         int32_t worker_num = sylar::GetParamValue(i.second, "worker_num", 1);
 69 | 
 70 |         for(int32_t x = 0; x < worker_num; ++x) {
 71 |             Scheduler::ptr s;
 72 |             if(!x) {
 73 |                 s = std::make_shared<IOManager>(thread_num, false, name);
 74 |             } else {
 75 |                 s = std::make_shared<IOManager>(thread_num, false, name + "-" + std::to_string(x));
 76 |             }
 77 |             add(s);
 78 |         }
 79 |     }
 80 |     m_stop = m_datas.empty();
 81 |     return true;
 82 | }
 83 | 
 84 | bool WorkerManager::init() {
 85 |     auto workers = g_worker_config->getValue();
 86 |     return init(workers);
 87 | }
 88 | 
 89 | void WorkerManager::stop() {
 90 |     if(m_stop) {
 91 |         return;
 92 |     }
 93 |     for(auto& i : m_datas) {
 94 |         for(auto& n : i.second) {
 95 |             n->schedule([](){});
 96 |             n->stop();
 97 |         }
 98 |     }
 99 |     m_datas.clear();
100 |     m_stop = true;
101 | }
102 | 
103 | uint32_t WorkerManager::getCount() {
104 |     return m_datas.size();
105 | }
106 | 
107 | std::ostream& WorkerManager::dump(std::ostream& os) {
108 |     for(auto& i : m_datas) {
109 |         for(auto& n : i.second) {
110 |             n->dump(os) << std::endl;
111 |         }
112 |     }
113 |     return os;
114 | }
115 | 
116 | }
117 | 


--------------------------------------------------------------------------------
/sylar/worker.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_WORKER_H__
 2 | #define __SYLAR_WORKER_H__
 3 | 
 4 | #include "mutex.h"
 5 | #include "singleton.h"
 6 | #include "log.h"
 7 | #include "iomanager.h"
 8 | 
 9 | namespace sylar {
10 | 
11 | class WorkerGroup : Noncopyable, public std::enable_shared_from_this<WorkerGroup> {
12 | public:
13 |     typedef std::shared_ptr<WorkerGroup> ptr;
14 |     static WorkerGroup::ptr Create(uint32_t batch_size, sylar::Scheduler* s = sylar::Scheduler::GetThis()) {
15 |         return std::make_shared<WorkerGroup>(batch_size, s);
16 |     }
17 | 
18 |     WorkerGroup(uint32_t batch_size, sylar::Scheduler* s = sylar::Scheduler::GetThis());
19 |     ~WorkerGroup();
20 | 
21 |     void schedule(std::function<void()> cb, int thread = -1);
22 |     void waitAll();
23 | private:
24 |     void doWork(std::function<void()> cb);
25 | private:
26 |     uint32_t m_batchSize;
27 |     bool m_finish;
28 |     Scheduler* m_scheduler;
29 |     FiberSemaphore m_sem;
30 | };
31 | 
32 | class WorkerManager {
33 | public:
34 |     WorkerManager();
35 |     void add(Scheduler::ptr s);
36 |     Scheduler::ptr get(const std::string& name);
37 |     IOManager::ptr getAsIOManager(const std::string& name);
38 | 
39 |     template<class FiberOrCb>
40 |     void schedule(const std::string& name, FiberOrCb fc, int thread = -1) {
41 |         auto s = get(name);
42 |         if(s) {
43 |             s->schedule(fc, thread);
44 |         } else {
45 |             static sylar::Logger::ptr s_logger = SYLAR_LOG_NAME("system");
46 |             SYLAR_LOG_ERROR(s_logger) << "schedule name=" << name
47 |                 << " not exists";
48 |         }
49 |     }
50 | 
51 |     template<class Iter>
52 |     void schedule(const std::string& name, Iter begin, Iter end) {
53 |         auto s = get(name);
54 |         if(s) {
55 |             s->schedule(begin, end);
56 |         } else {
57 |             static sylar::Logger::ptr s_logger = SYLAR_LOG_NAME("system");
58 |             SYLAR_LOG_ERROR(s_logger) << "schedule name=" << name
59 |                 << " not exists";
60 |         }
61 |     }
62 | 
63 |     bool init();
64 |     bool init(const std::map<std::string, std::map<std::string, std::string> >& v);
65 |     void stop();
66 | 
67 |     bool isStoped() const { return m_stop;}
68 |     std::ostream& dump(std::ostream& os);
69 | 
70 |     uint32_t getCount();
71 | private:
72 |     std::map<std::string, std::vector<Scheduler::ptr> > m_datas;
73 |     bool m_stop;
74 | };
75 | 
76 | typedef sylar::Singleton<WorkerManager> WorkerMgr;
77 | 
78 | }
79 | 
80 | #endif
81 | 


--------------------------------------------------------------------------------
/sylar/zk_client.h:
--------------------------------------------------------------------------------
 1 | #ifndef __SYLAR_ZK_CLIENT_H__
 2 | #define __SYLAR_ZK_CLIENT_H__
 3 | 
 4 | #include <memory>
 5 | #include <functional>
 6 | #include <string>
 7 | #include <stdint.h>
 8 | #include <vector>
 9 | 
10 | #ifndef THREADED
11 | #define THREADED
12 | #endif
13 | 
14 | #include <zookeeper/zookeeper.h>
15 | 
16 | namespace sylar {
17 | 
18 | class ZKClient : public std::enable_shared_from_this<ZKClient> {
19 | public:
20 |     class EventType {
21 |     public:
22 |         static const int CREATED; // = ZOO_CREATED_EVENT;
23 |         static const int DELETED; // = ZOO_DELETED_EVENT;
24 |         static const int CHANGED; // = ZOO_CHANGED_EVENT;
25 |         static const int CHILD  ; // = ZOO_CHILD_EVENT;
26 |         static const int SESSION; // = ZOO_SESSION_EVENT;
27 |         static const int NOWATCHING; // = ZOO_NOTWATCHING_EVENT;
28 |     };
29 |     class FlagsType {
30 |     public:
31 |         static const int EPHEMERAL; // = ZOO_EPHEMERAL;
32 |         static const int SEQUENCE;  //  = ZOO_SEQUENCE;
33 |         static const int CONTAINER; // = ZOO_CONTAINER;
34 |     };
35 |     class StateType {
36 |     public:
37 |         static const int EXPIRED_SESSION; // = ZOO_EXPIRED_SESSION_STATE;
38 |         static const int AUTH_FAILED; // = ZOO_AUTH_FAILED_STATE;
39 |         static const int CONNECTING; // = ZOO_CONNECTING_STATE;
40 |         static const int ASSOCIATING; // = ZOO_ASSOCIATING_STATE;
41 |         static const int CONNECTED; // = ZOO_CONNECTED_STATE;
42 |         static const int READONLY; // = ZOO_READONLY_STATE;
43 |         static const int NOTCONNECTED; // = ZOO_NOTCONNECTED_STATE;
44 |     };
45 | 
46 |     typedef std::shared_ptr<ZKClient> ptr;
47 |     typedef std::function<void(int type, int stat, const std::string& path, ZKClient::ptr)> watcher_callback;
48 |     typedef void(*log_callback)(const char *message);
49 | 
50 |     ZKClient();
51 |     ~ZKClient();
52 | 
53 |     bool init(const std::string& hosts, int recv_timeout, watcher_callback cb, log_callback lcb = nullptr);
54 |     int32_t setServers(const std::string& hosts);
55 | 
56 |     int32_t create(const std::string& path, const std::string& val, std::string& new_path
57 |                    , const struct ACL_vector* acl = &ZOO_OPEN_ACL_UNSAFE
58 |                    , int flags = 0);
59 |     int32_t exists(const std::string& path, bool watch, Stat* stat = nullptr);
60 |     int32_t del(const std::string& path, int version = -1);
61 |     int32_t get(const std::string& path, std::string& val, bool watch, Stat* stat = nullptr);
62 |     int32_t getConfig(std::string& val, bool watch, Stat* stat = nullptr);
63 |     int32_t set(const std::string& path, const std::string& val, int version = -1, Stat* stat = nullptr);
64 |     int32_t getChildren(const std::string& path, std::vector<std::string>& val, bool watch, Stat* stat = nullptr);
65 |     int32_t close();
66 |     int32_t getState();
67 |     std::string  getCurrentServer();
68 | 
69 |     bool reconnect();
70 | private:
71 |     static void OnWatcher(zhandle_t *zh, int type, int stat, const char *path,void *watcherCtx);
72 |     typedef std::function<void(int type, int stat, const std::string& path)> watcher_callback2;
73 | private:
74 |     zhandle_t* m_handle;
75 |     std::string m_hosts;
76 |     watcher_callback2 m_watcherCb;
77 |     log_callback m_logCb;
78 |     int32_t m_recvTimeout;
79 | };
80 | 
81 | }
82 | 
83 | #endif
84 | 


--------------------------------------------------------------------------------
/template/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 2.8)
 2 | project(project_name)
 3 | 
 4 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sylar)
 5 | 
 6 | include (sylar/cmake/utils.cmake)
 7 | 
 8 | set(CMAKE_VERBOSE_MAKEFILE ON)
 9 | set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -rdynamic -O0 -ggdb -std=c++11 -Wall -Wno-deprecated -Werror -Wno-unused-function -Wno-builtin-macro-redefined")
10 | 
11 | include_directories(.)
12 | include_directories(/apps/sylar/include)
13 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar)
14 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart)
15 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart)
16 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart/yaml-cpp/include)
17 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart/jsoncpp-1.8.4/include)
18 | link_directories(/apps/sylar/lib)
19 | 
20 | find_package(Boost REQUIRED)
21 | if(Boost_FOUND)
22 |     include_directories(${Boost_INCLUDE_DIRS})
23 | endif()
24 | 
25 | #find_package(Protobuf REQUIRED)
26 | #if(Protobuf_FOUND)
27 | #    include_directories(${Protobuf_INCLUDE_DIRS})
28 | #endif()
29 | find_package(OpenSSL REQUIRED)
30 | if(OPENSSL_FOUND)
31 |     include_directories(${OPENSSL_INCLUDE_DIR})
32 | endif()
33 | 
34 | set(LIB_SRC
35 |         template/my_module.cc
36 |     )
37 | 
38 | #PROTOBUF_GENERATE_CPP(PB_SRCS PB_HDRS sylar/test.proto)
39 | #list(APPEND LIB_SRC ${PB_SRCS})
40 | #
41 | #message(STATUS ${LIB_SRC})
42 | 
43 | add_library(project_name SHARED ${LIB_SRC})
44 | force_redefine_file_macro_for_sources(project_name)
45 | 
46 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
47 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
48 | 


--------------------------------------------------------------------------------
/template/bin/conf/log.yml:
--------------------------------------------------------------------------------
 1 | logs:
 2 |     - name: root
 3 |       level: info
 4 |       appenders:
 5 |           - type: FileLogAppender
 6 |             file: /apps/logs/project_name/root.log
 7 |           - type: StdoutLogAppender
 8 |     - name: system
 9 |       level: info
10 |       appenders:
11 |           - type: FileLogAppender
12 |             file: /apps/logs/project_name/system.log
13 |           - type: StdoutLogAppender
14 | 


--------------------------------------------------------------------------------
/template/bin/conf/server.yml:
--------------------------------------------------------------------------------
 1 | servers:
 2 |     - address: ["0.0.0.0:8090", "127.0.0.1:0", "/tmp/test.sock"]
 3 |       keepalive: 1
 4 |       timeout: 1000
 5 |       name: sylar/1.1
 6 |       accept_worker: accept
 7 |       io_worker: io
 8 |       process_worker:  io
 9 |       type: http
10 |     - address: ["0.0.0.0:8062", "0.0.0.0:8061"]
11 |       timeout: 1000
12 |       name: sylar-rock/1.0
13 |       accept_worker: accept
14 |       io_worker: io
15 |       process_worker:  io
16 |       type: rock
17 | 


--------------------------------------------------------------------------------
/template/bin/conf/system.yml:
--------------------------------------------------------------------------------
1 | server:
2 |     work_path: /apps/work/project_name
3 |     pid_file: project_name.pid
4 | 


--------------------------------------------------------------------------------
/template/bin/conf/worker.yml:
--------------------------------------------------------------------------------
1 | workers:
2 |     io:
3 |         thread_num: 4
4 |     accept:
5 |         thread_num: 1
6 | 


--------------------------------------------------------------------------------
/template/move.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | if [ ! -d bin/module ]
 4 | then
 5 |     mkdir bin/module
 6 | else
 7 |     unlink bin/project_name
 8 |     unlink bin/module/libproject_name.so
 9 | fi
10 | 
11 | cp sylar/bin/sylar bin/project_name
12 | cp lib/libproject_name.so bin/module/
13 | 


--------------------------------------------------------------------------------
/template/template/my_module.cc:
--------------------------------------------------------------------------------
 1 | #include "my_module.h"
 2 | #include "sylar/config.h"
 3 | #include "sylar/log.h"
 4 | 
 5 | namespace name_space {
 6 | 
 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 8 | 
 9 | MyModule::MyModule()
10 |     :sylar::Module("project_name", "1.0", "") {
11 | }
12 | 
13 | bool MyModule::onLoad() {
14 |     SYLAR_LOG_INFO(g_logger) << "onLoad";
15 |     return true;
16 | }
17 | 
18 | bool MyModule::onUnload() {
19 |     SYLAR_LOG_INFO(g_logger) << "onUnload";
20 |     return true;
21 | }
22 | 
23 | bool MyModule::onServerReady() {
24 |     SYLAR_LOG_INFO(g_logger) << "onServerReady";
25 |     return true;
26 | }
27 | 
28 | bool MyModule::onServerUp() {
29 |     SYLAR_LOG_INFO(g_logger) << "onServerUp";
30 |     return true;
31 | }
32 | 
33 | }
34 | 
35 | extern "C" {
36 | 
37 | sylar::Module* CreateModule() {
38 |     sylar::Module* module = new name_space::MyModule;
39 |     SYLAR_LOG_INFO(name_space::g_logger) << "CreateModule " << module;
40 |     return module;
41 | }
42 | 
43 | void DestoryModule(sylar::Module* module) {
44 |     SYLAR_LOG_INFO(name_space::g_logger) << "CreateModule " << module;
45 |     delete module;
46 | }
47 | 
48 | }
49 | 


--------------------------------------------------------------------------------
/template/template/my_module.h:
--------------------------------------------------------------------------------
 1 | #include "sylar/module.h"
 2 | 
 3 | namespace name_space {
 4 | 
 5 | class MyModule : public sylar::Module {
 6 | public:
 7 |     typedef std::shared_ptr<MyModule> ptr;
 8 |     MyModule();
 9 |     bool onLoad() override;
10 |     bool onUnload() override;
11 |     bool onServerReady() override;
12 |     bool onServerUp() override;
13 | };
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/tests/test.cc:
--------------------------------------------------------------------------------
 1 | #include <iostream>
 2 | #include "sylar/log.h"
 3 | #include "sylar/util.h"
 4 | 
 5 | int main(int argc, char** argv) {
 6 |     sylar::Logger::ptr logger(new sylar::Logger);
 7 |     logger->addAppender(sylar::LogAppender::ptr(new sylar::StdoutLogAppender));
 8 | 
 9 |     sylar::FileLogAppender::ptr file_appender(new sylar::FileLogAppender("./log.txt"));
10 |     sylar::LogFormatter::ptr fmt(new sylar::LogFormatter("%d%T%p%T%m%n"));
11 |     file_appender->setFormatter(fmt);
12 |     file_appender->setLevel(sylar::LogLevel::ERROR);
13 | 
14 |     logger->addAppender(file_appender);
15 | 
16 |     //sylar::LogEvent::ptr event(new sylar::LogEvent(__FILE__, __LINE__, 0, sylar::GetThreadId(), sylar::GetFiberId(), time(0)));
17 |     //event->getSS() << "hello sylar log";
18 |     //logger->log(sylar::LogLevel::DEBUG, event);
19 |     std::cout << "hello sylar log" << std::endl;
20 | 
21 |     SYLAR_LOG_INFO(logger) << "test macro";
22 |     SYLAR_LOG_ERROR(logger) << "test macro error";
23 | 
24 |     SYLAR_LOG_FMT_ERROR(logger, "test macro fmt error %s", "aa");
25 | 
26 |     auto l = sylar::LoggerMgr::GetInstance()->getLogger("xx");
27 |     SYLAR_LOG_INFO(l) << "xxx";
28 |     return 0;
29 | }
30 | 


--------------------------------------------------------------------------------
/tests/test_address.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/address.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | void test() {
 7 |     std::vector<sylar::Address::ptr> addrs;
 8 | 
 9 |     SYLAR_LOG_INFO(g_logger) << "begin";
10 |     bool v = sylar::Address::Lookup(addrs, "localhost:3080");
11 |     //bool v = sylar::Address::Lookup(addrs, "www.baidu.com", AF_INET);
12 |     //bool v = sylar::Address::Lookup(addrs, "www.sylar.top", AF_INET);
13 |     SYLAR_LOG_INFO(g_logger) << "end";
14 |     if(!v) {
15 |         SYLAR_LOG_ERROR(g_logger) << "lookup fail";
16 |         return;
17 |     }
18 | 
19 |     for(size_t i = 0; i < addrs.size(); ++i) {
20 |         SYLAR_LOG_INFO(g_logger) << i << " - " << addrs[i]->toString();
21 |     }
22 | 
23 |     auto addr = sylar::Address::LookupAny("localhost:4080");
24 |     if(addr) {
25 |         SYLAR_LOG_INFO(g_logger) << *addr;
26 |     } else {
27 |         SYLAR_LOG_ERROR(g_logger) << "error";
28 |     }
29 | }
30 | 
31 | void test_iface() {
32 |     std::multimap<std::string, std::pair<sylar::Address::ptr, uint32_t> > results;
33 | 
34 |     bool v = sylar::Address::GetInterfaceAddresses(results);
35 |     if(!v) {
36 |         SYLAR_LOG_ERROR(g_logger) << "GetInterfaceAddresses fail";
37 |         return;
38 |     }
39 | 
40 |     for(auto& i: results) {
41 |         SYLAR_LOG_INFO(g_logger) << i.first << " - " << i.second.first->toString() << " - "
42 |             << i.second.second;
43 |     }
44 | }
45 | 
46 | void test_ipv4() {
47 |     //auto addr = sylar::IPAddress::Create("www.sylar.top");
48 |     auto addr = sylar::IPAddress::Create("127.0.0.8");
49 |     if(addr) {
50 |         SYLAR_LOG_INFO(g_logger) << addr->toString();
51 |     }
52 | }
53 | 
54 | int main(int argc, char** argv) {
55 |     //test_ipv4();
56 |     //test_iface();
57 |     test();
58 |     return 0;
59 | }
60 | 


--------------------------------------------------------------------------------
/tests/test_application.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/application.h"
 2 | 
 3 | int main(int argc, char** argv) {
 4 |     sylar::Application app;
 5 |     if(app.init(argc, argv)) {
 6 |         return app.run();
 7 |     }
 8 |     return 0;
 9 | }
10 | 


--------------------------------------------------------------------------------
/tests/test_array.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include "sylar/ds/array.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | struct PidVid {
 7 |     PidVid(uint32_t p = 0, uint32_t v = 0)
 8 |         :pid(p), vid(v) {}
 9 |     uint32_t pid;
10 |     uint32_t vid;
11 | 
12 |     bool operator<(const PidVid& o) const {
13 |         return memcmp(this, &o, sizeof(o)) < 0;
14 |     }
15 | };
16 | 
17 | void gen() {
18 |     sylar::ds::Array<int> tmp;
19 |     std::vector<int> vs;
20 |     for(int i = 0; i < 10000; ++i) {
21 |         int v = rand();
22 |         tmp.insert(v);
23 |         vs.push_back(v);
24 |         SYLAR_ASSERT(tmp.isSorted());
25 |     }
26 | 
27 |     std::ofstream ofs("./array.data");
28 |     tmp.writeTo(ofs);
29 | 
30 |     for(auto& i : vs) {
31 |         auto idx = tmp.exists(i);
32 |         SYLAR_ASSERT(idx >= 0);
33 |         tmp.erase(idx);
34 |         SYLAR_ASSERT(tmp.isSorted());
35 |     }
36 |     SYLAR_ASSERT(tmp.size() == 0);
37 |     
38 | }
39 | 
40 | void test() {
41 |     for(int i = 0; i < 10000; ++i) {
42 |         SYLAR_LOG_INFO(g_logger) << "i=" << i;
43 |         std::ifstream ifs("./array.data");
44 |         sylar::ds::Array<int> tmp;
45 |         if(!tmp.readFrom(ifs)) {
46 |             SYLAR_LOG_INFO(g_logger) << "error";
47 |         }
48 |         SYLAR_ASSERT(tmp.isSorted());
49 |         if(i % 100 == 0) {
50 |             SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1);
51 |         }
52 |     }
53 | }
54 | 
55 | int main(int argc, char** argv) {
56 |     gen();
57 |     test();
58 |     return 0;
59 | }
60 | 


--------------------------------------------------------------------------------
/tests/test_bytearray.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/bytearray.h"
 2 | #include "sylar/sylar.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | void test() {
 6 | #define XX(type, len, write_fun, read_fun, base_len) {\
 7 |     std::vector<type> vec; \
 8 |     for(int i = 0; i < len; ++i) { \
 9 |         vec.push_back(rand()); \
10 |     } \
11 |     sylar::ByteArray::ptr ba(new sylar::ByteArray(base_len)); \
12 |     for(auto& i : vec) { \
13 |         ba->write_fun(i); \
14 |     } \
15 |     ba->setPosition(0); \
16 |     for(size_t i = 0; i < vec.size(); ++i) { \
17 |         type v = ba->read_fun(); \
18 |         SYLAR_ASSERT(v == vec[i]); \
19 |     } \
20 |     SYLAR_ASSERT(ba->getReadSize() == 0); \
21 |     SYLAR_LOG_INFO(g_logger) << #write_fun "/" #read_fun \
22 |                     " (" #type " ) len=" << len \
23 |                     << " base_len=" << base_len \
24 |                     << " size=" << ba->getSize(); \
25 | }
26 | 
27 |     XX(int8_t,  100, writeFint8, readFint8, 1);
28 |     XX(uint8_t, 100, writeFuint8, readFuint8, 1);
29 |     XX(int16_t,  100, writeFint16,  readFint16, 1);
30 |     XX(uint16_t, 100, writeFuint16, readFuint16, 1);
31 |     XX(int32_t,  100, writeFint32,  readFint32, 1);
32 |     XX(uint32_t, 100, writeFuint32, readFuint32, 1);
33 |     XX(int64_t,  100, writeFint64,  readFint64, 1);
34 |     XX(uint64_t, 100, writeFuint64, readFuint64, 1);
35 | 
36 |     XX(int32_t,  100, writeInt32,  readInt32, 1);
37 |     XX(uint32_t, 100, writeUint32, readUint32, 1);
38 |     XX(int64_t,  100, writeInt64,  readInt64, 1);
39 |     XX(uint64_t, 100, writeUint64, readUint64, 1);
40 | #undef XX
41 | 
42 | #define XX(type, len, write_fun, read_fun, base_len) {\
43 |     std::vector<type> vec; \
44 |     for(int i = 0; i < len; ++i) { \
45 |         vec.push_back(rand()); \
46 |     } \
47 |     sylar::ByteArray::ptr ba(new sylar::ByteArray(base_len)); \
48 |     for(auto& i : vec) { \
49 |         ba->write_fun(i); \
50 |     } \
51 |     ba->setPosition(0); \
52 |     for(size_t i = 0; i < vec.size(); ++i) { \
53 |         type v = ba->read_fun(); \
54 |         SYLAR_ASSERT(v == vec[i]); \
55 |     } \
56 |     SYLAR_ASSERT(ba->getReadSize() == 0); \
57 |     SYLAR_LOG_INFO(g_logger) << #write_fun "/" #read_fun \
58 |                     " (" #type " ) len=" << len \
59 |                     << " base_len=" << base_len \
60 |                     << " size=" << ba->getSize(); \
61 |     ba->setPosition(0); \
62 |     SYLAR_ASSERT(ba->writeToFile("/tmp/" #type "_" #len "-" #read_fun ".dat")); \
63 |     sylar::ByteArray::ptr ba2(new sylar::ByteArray(base_len * 2)); \
64 |     SYLAR_ASSERT(ba2->readFromFile("/tmp/" #type "_" #len "-" #read_fun ".dat")); \
65 |     ba2->setPosition(0); \
66 |     SYLAR_ASSERT(ba->toString() == ba2->toString()); \
67 |     SYLAR_ASSERT(ba->getPosition() == 0); \
68 |     SYLAR_ASSERT(ba2->getPosition() == 0); \
69 | }
70 |     XX(int8_t,  100, writeFint8, readFint8, 1);
71 |     XX(uint8_t, 100, writeFuint8, readFuint8, 1);
72 |     XX(int16_t,  100, writeFint16,  readFint16, 1);
73 |     XX(uint16_t, 100, writeFuint16, readFuint16, 1);
74 |     XX(int32_t,  100, writeFint32,  readFint32, 1);
75 |     XX(uint32_t, 100, writeFuint32, readFuint32, 1);
76 |     XX(int64_t,  100, writeFint64,  readFint64, 1);
77 |     XX(uint64_t, 100, writeFuint64, readFuint64, 1);
78 | 
79 |     XX(int32_t,  100, writeInt32,  readInt32, 1);
80 |     XX(uint32_t, 100, writeUint32, readUint32, 1);
81 |     XX(int64_t,  100, writeInt64,  readInt64, 1);
82 |     XX(uint64_t, 100, writeUint64, readUint64, 1);
83 | 
84 | #undef XX
85 | }
86 | 
87 | int main(int argc, char** argv) {
88 |     test();
89 |     return 0;
90 | }
91 | 


--------------------------------------------------------------------------------
/tests/test_daemon.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/daemon.h"
 2 | #include "sylar/iomanager.h"
 3 | #include "sylar/log.h"
 4 | 
 5 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 6 | 
 7 | sylar::Timer::ptr timer;
 8 | int server_main(int argc, char** argv) {
 9 |     SYLAR_LOG_INFO(g_logger) << sylar::ProcessInfoMgr::GetInstance()->toString();
10 |     sylar::IOManager iom(1);
11 |     timer = iom.addTimer(1000, [](){
12 |             SYLAR_LOG_INFO(g_logger) << "onTimer";
13 |             static int count = 0;
14 |             if(++count > 10) {
15 |                 exit(1);
16 |             }
17 |     }, true);
18 |     return 0;
19 | }
20 | 
21 | int main(int argc, char** argv) {
22 |     return sylar::start_daemon(argc, argv, server_main, argc != 1);
23 | }
24 | 


--------------------------------------------------------------------------------
/tests/test_dict.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include "sylar/ds/dict.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | struct PidVid {
 7 |     PidVid(uint32_t p = 0, uint32_t v = 0)
 8 |         :pid(p), vid(v) {}
 9 |     uint32_t pid;
10 |     uint32_t vid;
11 | 
12 |     bool operator<(const PidVid& o) const {
13 |         return memcmp(this, &o, sizeof(o)) < 0;
14 |     }
15 | };
16 | 
17 | void gen() {
18 |     sylar::ds::Dict<int, PidVid> tmp;
19 |     for(int i = 0; i < 500000; ++i) {
20 |         int32_t len = rand() % 10 + 5;
21 |         int k = rand();
22 |         std::vector<PidVid> pvs;
23 |         for(int n = 0; n < len; ++n) {
24 |             pvs.push_back(PidVid(rand(), rand()));
25 |         }
26 |         tmp.insert(k, pvs.data(), pvs.size());
27 |     }
28 | 
29 |     std::ofstream ofs("./dict.data");
30 |     tmp.writeTo(ofs);
31 | }
32 | 
33 | void test() {
34 |     for(int i = 0; i < 10000; ++i) {
35 |         SYLAR_LOG_INFO(g_logger) << "i=" << i;
36 |         std::ifstream ifs("./dict.data");
37 |         sylar::ds::Dict<int, PidVid> tmp;
38 |         if(!tmp.readFrom(ifs)) {
39 |             SYLAR_LOG_INFO(g_logger) << "error";
40 |         }
41 |         if(i % 100 == 0) {
42 |             SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1);
43 |         }
44 |     }
45 | }
46 | 
47 | int main(int argc, char** argv) {
48 |     gen();
49 |     test();
50 |     return 0;
51 | }
52 | 


--------------------------------------------------------------------------------
/tests/test_email.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/email/email.h"
 2 | #include "sylar/email/smtp.h"
 3 | 
 4 | void test() {
 5 |     sylar::EMail::ptr email = sylar::EMail::Create(
 6 |             "user@163.com", "passwd",
 7 |             "hello world", "<B>hi xxx</B>hell world", {"564628276@qq.com"});
 8 |     sylar::EMailEntity::ptr entity = sylar::EMailEntity::CreateAttach("sylar/sylar.h");
 9 |     if(entity) {
10 |         email->addEntity(entity);
11 |     }
12 | 
13 |     entity = sylar::EMailEntity::CreateAttach("sylar/address.cc");
14 |     if(entity) {
15 |         email->addEntity(entity);
16 |     }
17 | 
18 |     auto client = sylar::SmtpClient::Create("smtp.163.com", 465, true);
19 |     if(!client) {
20 |         std::cout << "connect smtp.163.com:25 fail" << std::endl;
21 |         return;
22 |     }
23 | 
24 |     auto result = client->send(email, true);
25 |     std::cout << "result=" << result->result << " msg=" << result->msg << std::endl;
26 |     std::cout << client->getDebugInfo() << std::endl;
27 |     //result = client->send(email, true);
28 |     //std::cout << "result=" << result->result << " msg=" << result->msg << std::endl;
29 |     //std::cout << client->getDebugInfo() << std::endl;
30 | }
31 | 
32 | int main(int argc, char** argv) {
33 |     sylar::IOManager iom(1);
34 |     iom.schedule(test);
35 |     iom.stop();
36 |     return 0;
37 | }
38 | 


--------------------------------------------------------------------------------
/tests/test_env.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/env.h"
 2 | #include <unistd.h>
 3 | #include <iostream>
 4 | #include <fstream>
 5 | 
 6 | struct A {
 7 |     A() {
 8 |         std::ifstream ifs("/proc/" + std::to_string(getpid()) + "/cmdline", std::ios::binary);
 9 |         std::string content;
10 |         content.resize(4096);
11 | 
12 |         ifs.read(&content[0], content.size());
13 |         content.resize(ifs.gcount());
14 | 
15 |         for(size_t i = 0; i < content.size(); ++i) {
16 |             std::cout << i << " - " << content[i] << " - " << (int)content[i] << std::endl;
17 |         }
18 |     }
19 | };
20 | 
21 | A a;
22 | 
23 | int main(int argc, char** argv) {
24 |     std::cout << "argc=" << argc << std::endl;
25 |     sylar::EnvMgr::GetInstance()->addHelp("s", "start with the terminal");
26 |     sylar::EnvMgr::GetInstance()->addHelp("d", "run as daemon");
27 |     sylar::EnvMgr::GetInstance()->addHelp("p", "print help");
28 |     if(!sylar::EnvMgr::GetInstance()->init(argc, argv)) {
29 |         sylar::EnvMgr::GetInstance()->printHelp();
30 |         return 0;
31 |     }
32 | 
33 |     std::cout << "exe=" << sylar::EnvMgr::GetInstance()->getExe() << std::endl;
34 |     std::cout << "cwd=" << sylar::EnvMgr::GetInstance()->getCwd() << std::endl;
35 | 
36 |     std::cout << "path=" << sylar::EnvMgr::GetInstance()->getEnv("PATH", "xxx") << std::endl;
37 |     std::cout << "test=" << sylar::EnvMgr::GetInstance()->getEnv("TEST", "") << std::endl;
38 |     std::cout << "set env " << sylar::EnvMgr::GetInstance()->setEnv("TEST", "yy") << std::endl;
39 |     std::cout << "test=" << sylar::EnvMgr::GetInstance()->getEnv("TEST", "") << std::endl;
40 |     if(sylar::EnvMgr::GetInstance()->has("p")) {
41 |         sylar::EnvMgr::GetInstance()->printHelp();
42 |     }
43 |     return 0;
44 | }
45 | 


--------------------------------------------------------------------------------
/tests/test_fiber.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | 
 3 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 4 | 
 5 | void run_in_fiber() {
 6 |     SYLAR_LOG_INFO(g_logger) << "run_in_fiber begin";
 7 |     sylar::Fiber::YieldToHold();
 8 |     SYLAR_LOG_INFO(g_logger) << "run_in_fiber end";
 9 |     sylar::Fiber::YieldToHold();
10 | }
11 | 
12 | void test_fiber() {
13 |     SYLAR_LOG_INFO(g_logger) << "main begin -1";
14 |     {
15 |         sylar::Fiber::GetThis();
16 |         SYLAR_LOG_INFO(g_logger) << "main begin";
17 |         sylar::Fiber::ptr fiber(new sylar::Fiber(run_in_fiber));
18 |         fiber->swapIn();
19 |         SYLAR_LOG_INFO(g_logger) << "main after swapIn";
20 |         fiber->swapIn();
21 |         SYLAR_LOG_INFO(g_logger) << "main after end";
22 |         fiber->swapIn();
23 |     }
24 |     SYLAR_LOG_INFO(g_logger) << "main after end2";
25 | }
26 | 
27 | int main(int argc, char** argv) {
28 |     sylar::Thread::SetName("main");
29 | 
30 |     std::vector<sylar::Thread::ptr> thrs;
31 |     for(int i = 0; i < 3; ++i) {
32 |         thrs.push_back(sylar::Thread::ptr(
33 |                     new sylar::Thread(&test_fiber, "name_" + std::to_string(i))));
34 |     }
35 |     for(auto i : thrs) {
36 |         i->join();
37 |     }
38 |     return 0;
39 | }
40 | 


--------------------------------------------------------------------------------
/tests/test_hashmap.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include "sylar/ds/hash_map.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | struct PidVid {
 7 |     PidVid(uint32_t p = 0, uint32_t v = 0)
 8 |         :pid(p), vid(v) {}
 9 |     uint32_t pid;
10 |     uint32_t vid;
11 | 
12 |     bool operator<(const PidVid& o) const {
13 |         return memcmp(this, &o, sizeof(o)) < 0;
14 |     }
15 | };
16 | 
17 | void gen() {
18 |     sylar::ds::HashMap<int, PidVid> tmp;
19 |     for(int i = 0; i < 500000; ++i) {
20 |         int32_t len = rand() % 10 + 5;
21 |         int k = rand();
22 |         for(int n = 0; n < len; ++n) {
23 |             tmp.set(k, PidVid(rand(), rand()));
24 |         }
25 |     }
26 | 
27 |     std::ofstream ofs("./hashmap.data");
28 |     tmp.writeTo(ofs);
29 | }
30 | 
31 | void test() {
32 |     for(int i = 0; i < 10000; ++i) {
33 |         SYLAR_LOG_INFO(g_logger) << "i=" << i;
34 |         std::ifstream ifs("./hashmap.data");
35 |         sylar::ds::HashMap<int, PidVid> tmp;
36 |         if(!tmp.readFrom(ifs)) {
37 |             SYLAR_LOG_INFO(g_logger) << "error";
38 |         }
39 |         if(i % 100 == 0) {
40 |             SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1);
41 |         }
42 |     }
43 | }
44 | 
45 | int main(int argc, char** argv) {
46 |     gen();
47 |     test();
48 |     return 0;
49 | }
50 | 


--------------------------------------------------------------------------------
/tests/test_hashmultimap.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include "sylar/ds/hash_multimap.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | struct PidVid {
 7 |     PidVid(uint32_t p = 0, uint32_t v = 0)
 8 |         :pid(p), vid(v) {}
 9 |     uint32_t pid;
10 |     uint32_t vid;
11 | 
12 |     bool operator<(const PidVid& o) const {
13 |         return memcmp(this, &o, sizeof(o)) < 0;
14 |     }
15 | };
16 | 
17 | void gen() {
18 |     sylar::ds::HashMultimap<int, PidVid> tmp;
19 |     for(int i = 0; i < 500000; ++i) {
20 |         int32_t len = rand() % 10 + 5;
21 |         int k = rand();
22 |         for(int n = 0; n < len; ++n) {
23 |             tmp.insert(k, PidVid(rand(), rand()));
24 |         }
25 |     }
26 | 
27 |     std::ofstream ofs("./hashmultimap.data");
28 |     tmp.writeTo(ofs);
29 | }
30 | 
31 | void test() {
32 |     for(int i = 0; i < 10000; ++i) {
33 |         SYLAR_LOG_INFO(g_logger) << "i=" << i;
34 |         std::ifstream ifs("./hashmultimap.data");
35 |         sylar::ds::HashMultimap<int, PidVid> tmp;
36 |         if(!tmp.readFrom(ifs)) {
37 |             SYLAR_LOG_INFO(g_logger) << "error";
38 |         }
39 |         if(i % 100 == 0) {
40 |             SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1);
41 |         }
42 |     }
43 | }
44 | 
45 | int main(int argc, char** argv) {
46 |     gen();
47 |     test();
48 |     return 0;
49 | }
50 | 


--------------------------------------------------------------------------------
/tests/test_hook.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/hook.h"
 2 | #include "sylar/log.h"
 3 | #include "sylar/iomanager.h"
 4 | #include <sys/types.h>
 5 | #include <sys/socket.h>
 6 | #include <arpa/inet.h>
 7 | #include <unistd.h>
 8 | #include <string.h>
 9 | 
10 | 
11 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
12 | 
13 | void test_sleep() {
14 |     sylar::IOManager iom(1);
15 |     iom.schedule([](){
16 |         sleep(2);
17 |         SYLAR_LOG_INFO(g_logger) << "sleep 2";
18 |     });
19 | 
20 |     iom.schedule([](){
21 |         sleep(3);
22 |         SYLAR_LOG_INFO(g_logger) << "sleep 3";
23 |     });
24 |     SYLAR_LOG_INFO(g_logger) << "test_sleep";
25 | }
26 | 
27 | void test_sock() {
28 |     int sock = socket(AF_INET, SOCK_STREAM, 0);
29 | 
30 |     sockaddr_in addr;
31 |     memset(&addr, 0, sizeof(addr));
32 |     addr.sin_family = AF_INET;
33 |     addr.sin_port = htons(80);
34 |     inet_pton(AF_INET, "115.239.210.27", &addr.sin_addr.s_addr);
35 | 
36 |     SYLAR_LOG_INFO(g_logger) << "begin connect";
37 |     int rt = connect(sock, (const sockaddr*)&addr, sizeof(addr));
38 |     SYLAR_LOG_INFO(g_logger) << "connect rt=" << rt << " errno=" << errno;
39 | 
40 |     if(rt) {
41 |         return;
42 |     }
43 | 
44 |     const char data[] = "GET / HTTP/1.0\r\n\r\n";
45 |     rt = send(sock, data, sizeof(data), 0);
46 |     SYLAR_LOG_INFO(g_logger) << "send rt=" << rt << " errno=" << errno;
47 | 
48 |     if(rt <= 0) {
49 |         return;
50 |     }
51 | 
52 |     std::string buff;
53 |     buff.resize(4096);
54 | 
55 |     rt = recv(sock, &buff[0], buff.size(), 0);
56 |     SYLAR_LOG_INFO(g_logger) << "recv rt=" << rt << " errno=" << errno;
57 | 
58 |     if(rt <= 0) {
59 |         return;
60 |     }
61 | 
62 |     buff.resize(rt);
63 |     SYLAR_LOG_INFO(g_logger) << buff;
64 | }
65 | 
66 | int main(int argc, char** argv) {
67 |     //test_sleep();
68 |     sylar::IOManager iom;
69 |     iom.schedule(test_sock);
70 |     return 0;
71 | }
72 | 


--------------------------------------------------------------------------------
/tests/test_http.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/http/http.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | void test_request() {
 5 |     sylar::http::HttpRequest::ptr req(new sylar::http::HttpRequest);
 6 |     req->setHeader("host" , "www.sylar.top");
 7 |     req->setBody("hello sylar");
 8 |     req->dump(std::cout) << std::endl;
 9 | }
10 | 
11 | void test_response() {
12 |     sylar::http::HttpResponse::ptr rsp(new sylar::http::HttpResponse);
13 |     rsp->setHeader("X-X", "sylar");
14 |     rsp->setBody("hello sylar");
15 |     rsp->setStatus((sylar::http::HttpStatus)400);
16 |     rsp->setClose(false);
17 | 
18 |     rsp->dump(std::cout) << std::endl;
19 | }
20 | 
21 | int main(int argc, char** argv) {
22 |     test_request();
23 |     test_response();
24 |     return 0;
25 | }
26 | 


--------------------------------------------------------------------------------
/tests/test_http_parser.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/http/http_parser.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | const char test_request_data[] = "POST / HTTP/1.1\r\n"
 7 |                                 "Host: www.sylar.top\r\n"
 8 |                                 "Content-Length: 10\r\n\r\n"
 9 |                                 "1234567890";
10 | 
11 | void test_request() {
12 |     sylar::http::HttpRequestParser parser;
13 |     std::string tmp = test_request_data;
14 |     size_t s = parser.execute(&tmp[0], tmp.size());
15 |     SYLAR_LOG_ERROR(g_logger) << "execute rt=" << s
16 |         << "has_error=" << parser.hasError()
17 |         << " is_finished=" << parser.isFinished()
18 |         << " total=" << tmp.size()
19 |         << " content_length=" << parser.getContentLength();
20 |     tmp.resize(tmp.size() - s);
21 |     SYLAR_LOG_INFO(g_logger) << parser.getData()->toString();
22 |     SYLAR_LOG_INFO(g_logger) << tmp;
23 | }
24 | 
25 | const char test_response_data[] = "HTTP/1.1 200 OK\r\n"
26 |         "Date: Tue, 04 Jun 2019 15:43:56 GMT\r\n"
27 |         "Server: Apache\r\n"
28 |         "Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\n"
29 |         "ETag: \"51-47cf7e6ee8400\"\r\n"
30 |         "Accept-Ranges: bytes\r\n"
31 |         "Content-Length: 81\r\n"
32 |         "Cache-Control: max-age=86400\r\n"
33 |         "Expires: Wed, 05 Jun 2019 15:43:56 GMT\r\n"
34 |         "Connection: Close\r\n"
35 |         "Content-Type: text/html\r\n\r\n"
36 |         "<html>\r\n"
37 |         "<meta http-equiv=\"refresh\" content=\"0;url=http://www.baidu.com/\">\r\n"
38 |         "</html>\r\n";
39 | 
40 | void test_response() {
41 |     sylar::http::HttpResponseParser parser;
42 |     std::string tmp = test_response_data;
43 |     size_t s = parser.execute(&tmp[0], tmp.size(), true);
44 |     SYLAR_LOG_ERROR(g_logger) << "execute rt=" << s
45 |         << " has_error=" << parser.hasError()
46 |         << " is_finished=" << parser.isFinished()
47 |         << " total=" << tmp.size()
48 |         << " content_length=" << parser.getContentLength()
49 |         << " tmp[s]=" << tmp[s];
50 | 
51 |     tmp.resize(tmp.size() - s);
52 | 
53 |     SYLAR_LOG_INFO(g_logger) << parser.getData()->toString();
54 |     SYLAR_LOG_INFO(g_logger) << tmp;
55 | }
56 | 
57 | int main(int argc, char** argv) {
58 |     test_request();
59 |     SYLAR_LOG_INFO(g_logger) << "--------------";
60 |     test_response();
61 |     return 0;
62 | }
63 | 


--------------------------------------------------------------------------------
/tests/test_http_server.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/http/http_server.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | #define XX(...) #__VA_ARGS__
 7 | 
 8 | 
 9 | sylar::IOManager::ptr worker;
10 | void run() {
11 |     g_logger->setLevel(sylar::LogLevel::INFO);
12 |     //sylar::http::HttpServer::ptr server(new sylar::http::HttpServer(true, worker.get(), sylar::IOManager::GetThis()));
13 |     sylar::http::HttpServer::ptr server(new sylar::http::HttpServer(true));
14 |     sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020");
15 |     while(!server->bind(addr)) {
16 |         sleep(2);
17 |     }
18 |     auto sd = server->getServletDispatch();
19 |     sd->addServlet("/sylar/xx", [](sylar::http::HttpRequest::ptr req
20 |                 ,sylar::http::HttpResponse::ptr rsp
21 |                 ,sylar::http::HttpSession::ptr session) {
22 |             rsp->setBody(req->toString());
23 |             return 0;
24 |     });
25 | 
26 |     sd->addGlobServlet("/sylar/*", [](sylar::http::HttpRequest::ptr req
27 |                 ,sylar::http::HttpResponse::ptr rsp
28 |                 ,sylar::http::HttpSession::ptr session) {
29 |             rsp->setBody("Glob:\r\n" + req->toString());
30 |             return 0;
31 |     });
32 | 
33 |     sd->addGlobServlet("/sylarx/*", [](sylar::http::HttpRequest::ptr req
34 |                 ,sylar::http::HttpResponse::ptr rsp
35 |                 ,sylar::http::HttpSession::ptr session) {
36 |             rsp->setBody(XX(<html>
37 | <head><title>404 Not Found</title></head>
38 | <body>
39 | <center><h1>404 Not Found</h1></center>
40 | <hr><center>nginx/1.16.0</center>
41 | </body>
42 | </html>
43 | <!-- a padding to disable MSIE and Chrome friendly error page -->
44 | <!-- a padding to disable MSIE and Chrome friendly error page -->
45 | <!-- a padding to disable MSIE and Chrome friendly error page -->
46 | <!-- a padding to disable MSIE and Chrome friendly error page -->
47 | <!-- a padding to disable MSIE and Chrome friendly error page -->
48 | <!-- a padding to disable MSIE and Chrome friendly error page -->
49 | ));
50 |             return 0;
51 |     });
52 | 
53 |     server->start();
54 | }
55 | 
56 | int main(int argc, char** argv) {
57 |     sylar::IOManager iom(1, true, "main");
58 |     worker.reset(new sylar::IOManager(3, false, "worker"));
59 |     iom.schedule(run);
60 |     return 0;
61 | }
62 | 


--------------------------------------------------------------------------------
/tests/test_iomanager.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include "sylar/iomanager.h"
 3 | #include <sys/types.h>
 4 | #include <sys/socket.h>
 5 | #include <arpa/inet.h>
 6 | #include <unistd.h>
 7 | #include <fcntl.h>
 8 | #include <iostream>
 9 | #include <sys/epoll.h>
10 | 
11 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
12 | 
13 | int sock = 0;
14 | 
15 | void test_fiber() {
16 |     SYLAR_LOG_INFO(g_logger) << "test_fiber sock=" << sock;
17 | 
18 |     //sleep(3);
19 | 
20 |     //close(sock);
21 |     //sylar::IOManager::GetThis()->cancelAll(sock);
22 | 
23 |     sock = socket(AF_INET, SOCK_STREAM, 0);
24 |     fcntl(sock, F_SETFL, O_NONBLOCK);
25 | 
26 |     sockaddr_in addr;
27 |     memset(&addr, 0, sizeof(addr));
28 |     addr.sin_family = AF_INET;
29 |     addr.sin_port = htons(80);
30 |     inet_pton(AF_INET, "115.239.210.27", &addr.sin_addr.s_addr);
31 | 
32 |     if(!connect(sock, (const sockaddr*)&addr, sizeof(addr))) {
33 |     } else if(errno == EINPROGRESS) {
34 |         SYLAR_LOG_INFO(g_logger) << "add event errno=" << errno << " " << strerror(errno);
35 |         sylar::IOManager::GetThis()->addEvent(sock, sylar::IOManager::READ, [](){
36 |             SYLAR_LOG_INFO(g_logger) << "read callback";
37 |         });
38 |         sylar::IOManager::GetThis()->addEvent(sock, sylar::IOManager::WRITE, [](){
39 |             SYLAR_LOG_INFO(g_logger) << "write callback";
40 |             //close(sock);
41 |             sylar::IOManager::GetThis()->cancelEvent(sock, sylar::IOManager::READ);
42 |             close(sock);
43 |         });
44 |     } else {
45 |         SYLAR_LOG_INFO(g_logger) << "else " << errno << " " << strerror(errno);
46 |     }
47 | 
48 | }
49 | 
50 | void test1() {
51 |     std::cout << "EPOLLIN=" << EPOLLIN
52 |               << " EPOLLOUT=" << EPOLLOUT << std::endl;
53 |     sylar::IOManager iom(2, false);
54 |     iom.schedule(&test_fiber);
55 | }
56 | 
57 | sylar::Timer::ptr s_timer;
58 | void test_timer() {
59 |     sylar::IOManager iom(2);
60 |     s_timer = iom.addTimer(1000, [](){
61 |         static int i = 0;
62 |         SYLAR_LOG_INFO(g_logger) << "hello timer i=" << i;
63 |         if(++i == 3) {
64 |             s_timer->reset(2000, true);
65 |             //s_timer->cancel();
66 |         }
67 |     }, true);
68 | }
69 | 
70 | int main(int argc, char** argv) {
71 |     //test1();
72 |     test_timer();
73 |     return 0;
74 | }
75 | 


--------------------------------------------------------------------------------
/tests/test_lru.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/ds/lru_cache.h"
 2 | 
 3 | void test_lru() {
 4 |     sylar::ds::LruCache<int, int> cache(30, 10);
 5 | 
 6 |     for(int i = 0; i < 105; ++i) {
 7 |         cache.set(i, i * 100);
 8 |     }
 9 | 
10 |     for(int i = 0; i < 105; ++i) {
11 |         int v;
12 |         if(cache.get(i, v)) {
13 |             std::cout << "get: " << i << " - " << v << std::endl;
14 |         }
15 |     }
16 | 
17 |     std::cout << cache.toStatusString() << std::endl;
18 | }
19 | 
20 | void test_hash_lru() {
21 |     sylar::ds::HashLruCache<int, int> cache(2, 30, 10);
22 | 
23 |     for(int i = 0; i < 105; ++i) {
24 |         cache.set(i, i * 100);
25 |     }
26 | 
27 |     for(int i = 0; i < 105; ++i) {
28 |         int v;
29 |         if(cache.get(i, v)) {
30 |             std::cout << "get: " << i << " - " << v << std::endl;
31 |         }
32 |     }
33 | 
34 |     std::cout << cache.toStatusString() << std::endl;
35 | }
36 | 
37 | int main(int argc, char** argv) {
38 |     test_lru();
39 |     test_hash_lru();
40 |     return 0;
41 | }
42 | 


--------------------------------------------------------------------------------
/tests/test_module.cc:
--------------------------------------------------------------------------------
  1 | #include "sylar/module.h"
  2 | #include "sylar/singleton.h"
  3 | #include <iostream>
  4 | #include "sylar/log.h"
  5 | #include "sylar/db/redis.h"
  6 | 
  7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
  8 | 
  9 | class A {
 10 | public:
 11 |     A() {
 12 |         std::cout << "A::A " << this << std::endl;
 13 |     }
 14 | 
 15 |     ~A() {
 16 |         std::cout << "A::~A " << this << std::endl;
 17 |     }
 18 | 
 19 | };
 20 | 
 21 | class MyModule : public sylar::RockModule {
 22 | public:
 23 |     MyModule()
 24 |         :RockModule("hello", "1.0", "") {
 25 |         //sylar::Singleton<A>::GetInstance();
 26 |     }
 27 | 
 28 |     bool onLoad() override {
 29 |         sylar::Singleton<A>::GetInstance();
 30 |         std::cout << "-----------onLoad------------" << std::endl;
 31 |         return true;
 32 |     }
 33 | 
 34 |     bool onUnload() override {
 35 |         sylar::Singleton<A>::GetInstance();
 36 |         std::cout << "-----------onUnload------------" << std::endl;
 37 |         return true;
 38 |     }
 39 | 
 40 |     bool onServerReady() {
 41 |         registerService("rock", "sylar.top", "blog");
 42 |         auto rpy = sylar::RedisUtil::Cmd("local", "get abc");
 43 |         if(!rpy) {
 44 |             SYLAR_LOG_ERROR(g_logger) << "redis cmd get abc error";
 45 |         } else {
 46 |             SYLAR_LOG_ERROR(g_logger) << "redis get abc: "
 47 |                 << (rpy->str ? rpy->str : "(null)");
 48 |         }
 49 |         return true;
 50 |     }
 51 | 
 52 |     bool handleRockRequest(sylar::RockRequest::ptr request
 53 |                         ,sylar::RockResponse::ptr response
 54 |                         ,sylar::RockStream::ptr stream) {
 55 |         //SYLAR_LOG_INFO(g_logger) << "handleRockRequest " << request->toString();
 56 |         //sleep(1);
 57 |         response->setResult(0);
 58 |         response->setResultStr("ok");
 59 |         response->setBody("echo: " + request->getBody());
 60 | 
 61 |         usleep(100 * 1000);
 62 |         auto addr = stream->getLocalAddressString();
 63 |         if(addr.find("8061") != std::string::npos) {
 64 |             if(rand() % 100 < 50) {
 65 |                 usleep(10 * 1000);
 66 |             } else if(rand() % 100 < 10) {
 67 |                 response->setResult(-1000);
 68 |             }
 69 |         } else {
 70 |             //if(rand() % 100 < 25) {
 71 |             //    usleep(10 * 1000);
 72 |             //} else if(rand() % 100 < 10) {
 73 |             //    response->setResult(-1000);
 74 |             //}
 75 |         }
 76 |         return true;
 77 |         //return rand() % 100 < 90;
 78 |     }
 79 | 
 80 |     bool handleRockNotify(sylar::RockNotify::ptr notify 
 81 |                         ,sylar::RockStream::ptr stream) {
 82 |         SYLAR_LOG_INFO(g_logger) << "handleRockNotify " << notify->toString();
 83 |         return true;
 84 |     }
 85 | 
 86 | };
 87 | 
 88 | extern "C" {
 89 | 
 90 | sylar::Module* CreateModule() {
 91 |     sylar::Singleton<A>::GetInstance();
 92 |     std::cout << "=============CreateModule=================" << std::endl;
 93 |     return new MyModule;
 94 | }
 95 | 
 96 | void DestoryModule(sylar::Module* ptr) {
 97 |     std::cout << "=============DestoryModule=================" << std::endl;
 98 |     delete ptr;
 99 | }
100 | 
101 | }
102 | 


--------------------------------------------------------------------------------
/tests/test_mysql.cc:
--------------------------------------------------------------------------------
 1 | #include <iostream>
 2 | #include "sylar/db/mysql.h"
 3 | #include "sylar/iomanager.h"
 4 | 
 5 | void run() {
 6 |     do {
 7 |         std::map<std::string, std::string> params;
 8 |         params["host"] = "127.0.0.1";
 9 |         params["user"] = "sylar";
10 |         params["passwd"] = "blog123";
11 |         params["dbname"] = "blog";
12 | 
13 |         sylar::MySQL::ptr mysql(new sylar::MySQL(params));
14 |         if(!mysql->connect()) {
15 |             std::cout << "connect fail" << std::endl;
16 |             return;
17 |         }
18 | 
19 |         //auto stmt = mysql_stmt_init(mysql->getRaw());
20 |         //std::string sql = "select * from sylar where status >= ?";
21 |         //mysql_stmt_prepare(stmt, sql.c_str(), sql.size());
22 |         //MYSQL_BIND b;
23 |         //int a = 0;
24 |         //b.buffer_type = MYSQL_TYPE_LONG;
25 |         //b.buffer = &a;
26 |         //mysql_stmt_bind_param(m_
27 | 
28 |         sylar::MySQLStmt::ptr stmt = sylar::MySQLStmt::Create(mysql, "update user set update_time = ? where id = 1");
29 |         stmt->bindString(1, "2018-01-01 10:10:10");
30 |         int rt = stmt->execute();
31 |         std::cout << "rt=" << rt << std::endl;
32 | 
33 |         //MYSQL_TIME mt;
34 |         //sylar::time_t_to_mysql_time(time(0), mt);
35 | 
36 |         //int a = 0;
37 |         ////auto stmt = mysql->prepare("select * from sylar where status >= ?");
38 |         ////stmt->bind(0, a);
39 |         ////auto res = std::dynamic_pointer_cast<sylar::MySQLStmtRes>(stmt->query());
40 | 
41 |         //auto res = std::dynamic_pointer_cast<sylar::MySQLStmtRes>
42 |         //    //(mysql->queryStmt("select * from sylar"));
43 |         //    (mysql->queryStmt("select *, 'hello' as xx from user where status >= ? and status <= ?"
44 |         //                      , a, a));
45 |         //    //(mysql->queryStmt("select id,name, keyword, creator as aa, last_update_time from sylar "
46 |         //    //                  " where last_update_time > ?", (time_t)0));
47 |         ////auto res = std::dynamic_pointer_cast<sylar::MySQLRes>
48 |         ////    (mysql->query("select * from search_brand"));
49 |         //if(!res) {
50 |         //    std::cout << "invalid" << std::endl;
51 |         //    return;
52 |         //}
53 |         //if(res->getErrno()) {
54 |         //    std::cout << "errno=" << res->getErrno()
55 |         //        << " errstr=" << res->getErrStr() << std::endl;
56 |         //    return;
57 |         //}
58 | 
59 |         //int i = 0;
60 |         //while(res->next()) {
61 |         //    ++i;
62 |         //    std::cout << res->getInt64(0)
63 |         //        << " - " << res->getInt64(1) << std::endl;
64 |         //}
65 |         //std::cout << "===" << i << std::endl;
66 |     } while(false);
67 |     std::cout << "over" << std::endl;
68 | }
69 | 
70 | int main(int argc, char** argv) {
71 |     sylar::IOManager iom(1);
72 |     //iom.schedule(run);
73 |     iom.addTimer(1000, run, true);
74 |     return 0;
75 | }
76 | 


--------------------------------------------------------------------------------
/tests/test_orm.cc:
--------------------------------------------------------------------------------
 1 | #include "orm_out/test/orm/user_info.h"
 2 | #include "sylar/db/sqlite3.h"
 3 | #include "sylar/db/mysql.h"
 4 | 
 5 | int main(int argc, char** argv) {
 6 |     sylar::IDB::ptr db;
 7 |     if(argc == 1) {
 8 |         db = sylar::SQLite3::Create("abc.db");
 9 |         std::cout << "create table: " << test::orm::UserInfoDao::CreateTableSQLite3(db) << std::endl;
10 |     } else {
11 |         std::map<std::string, std::string> params;
12 |         params["host"] = "127.0.0.1";
13 |         params["user"] = "sylar";
14 |         params["passwd"] = "123456";
15 |         params["dbname"] = "sylar";
16 | 
17 |         sylar::MySQL::ptr m(new sylar::MySQL(params));
18 |         m->connect();
19 |         db = m;
20 |         std::cout << "create table: " << test::orm::UserInfoDao::CreateTableMySQL(db) << std::endl;
21 |     }
22 |     for(int i = 0; i < 10; ++i) {
23 |         test::orm::UserInfo::ptr u(new test::orm::UserInfo);
24 |         u->setName("name_a" + std::to_string(i));
25 |         u->setEmail("mail_a" + std::to_string(i));
26 |         u->setPhone("phone_a" + std::to_string(i));
27 |         u->setStatus(i % 2);
28 | 
29 |         std::cout << "i= " << i << " - " << test::orm::UserInfoDao::Insert(u, db);
30 |         std::cout << " - " << u->toJsonString()
31 |                   << std::endl;
32 |     }
33 | 
34 |     std::vector<test::orm::UserInfo::ptr> us;
35 |     std::cout << "query_by_status: " << test::orm::UserInfoDao::QueryByStatus(us, 1, db) << std::endl;
36 |     for(size_t i = 0; i < us.size(); ++i) {
37 |         std::cout << "i=" << i << " - " << us[i]->toJsonString() << std::endl;
38 |         us[i]->setName(us[i]->getName() + "_new");
39 |         test::orm::UserInfoDao::Update(us[i], db);
40 |     }
41 | 
42 |     std::cout << "delete: " << test::orm::UserInfoDao::DeleteByStatus(1, db) << std::endl;
43 |     us.clear();
44 |     std::cout << "query_by_status: " << test::orm::UserInfoDao::QueryByStatus(us, 0, db) << std::endl;
45 |     for(size_t i = 0; i < us.size(); ++i) {
46 |         std::cout << "i=" << i << " - " << us[i]->toJsonString() << std::endl;
47 |     }
48 | 
49 |     us.clear();
50 |     std::cout << "query_all: " << test::orm::UserInfoDao::QueryAll(us, db) << std::endl;
51 |     for(size_t i = 0; i < us.size(); ++i) {
52 |         std::cout << "i=" << i << " - " << us[i]->toJsonString() << std::endl;
53 |     }
54 |     return 0;
55 | }
56 | 


--------------------------------------------------------------------------------
/tests/test_rock.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include "sylar/rock/rock_stream.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | sylar::RockConnection::ptr conn(new sylar::RockConnection);
 7 | void run() {
 8 |     conn->setAutoConnect(true);
 9 |     sylar::Address::ptr addr = sylar::Address::LookupAny("127.0.0.1:8061");
10 |     if(!conn->connect(addr)) {
11 |         SYLAR_LOG_INFO(g_logger) << "connect " << *addr << " false";
12 |     }
13 |     conn->start();
14 | 
15 |     sylar::IOManager::GetThis()->addTimer(1000, [](){
16 |         sylar::RockRequest::ptr req(new sylar::RockRequest);
17 |         static uint32_t s_sn = 0;
18 |         req->setSn(++s_sn);
19 |         req->setCmd(100);
20 |         req->setBody("hello world sn=" + std::to_string(s_sn));
21 | 
22 |         auto rsp = conn->request(req, 300);
23 |         if(rsp->response) {
24 |             SYLAR_LOG_INFO(g_logger) << rsp->response->toString();
25 |         } else {
26 |             SYLAR_LOG_INFO(g_logger) << "error result=" << rsp->result;
27 |         }
28 |     }, true);
29 | }
30 | 
31 | int main(int argc, char** argv) {
32 |     sylar::IOManager iom(1);
33 |     iom.schedule(run);
34 |     return 0;
35 | }
36 | 


--------------------------------------------------------------------------------
/tests/test_scheduler.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | 
 3 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 4 | 
 5 | void test_fiber() {
 6 |     static int s_count = 5;
 7 |     SYLAR_LOG_INFO(g_logger) << "test in fiber s_count=" << s_count;
 8 | 
 9 |     sleep(1);
10 |     if(--s_count >= 0) {
11 |         sylar::Scheduler::GetThis()->schedule(&test_fiber, sylar::GetThreadId());
12 |     }
13 | }
14 | 
15 | int main(int argc, char** argv) {
16 |     SYLAR_LOG_INFO(g_logger) << "main";
17 |     sylar::Scheduler sc(3, false, "test");
18 |     sc.start();
19 |     sleep(2);
20 |     SYLAR_LOG_INFO(g_logger) << "schedule";
21 |     sc.schedule(&test_fiber);
22 |     sc.stop();
23 |     SYLAR_LOG_INFO(g_logger) << "over";
24 |     return 0;
25 | }
26 | 


--------------------------------------------------------------------------------
/tests/test_service_discovery.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/streams/service_discovery.h"
 2 | #include "sylar/iomanager.h"
 3 | #include "sylar/rock/rock_stream.h"
 4 | #include "sylar/log.h"
 5 | #include "sylar/worker.h"
 6 | 
 7 | sylar::ZKServiceDiscovery::ptr zksd(new sylar::ZKServiceDiscovery("127.0.0.1:21812"));
 8 | sylar::RockSDLoadBalance::ptr rsdlb(new sylar::RockSDLoadBalance(zksd));
 9 | 
10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
11 | 
12 | std::atomic<uint32_t> s_id;
13 | void on_timer() {
14 |     g_logger->setLevel(sylar::LogLevel::INFO);
15 |     //SYLAR_LOG_INFO(g_logger) << "on_timer";
16 |     sylar::RockRequest::ptr req(new sylar::RockRequest);
17 |     req->setSn(++s_id);
18 |     req->setCmd(100);
19 |     req->setBody("hello");
20 | 
21 |     auto rt = rsdlb->request("sylar.top", "blog", req, 1000);
22 |     if(!rt->response) {
23 |         if(req->getSn() % 50 == 0) {
24 |             SYLAR_LOG_ERROR(g_logger) << "invalid response: " << rt->toString();
25 |         }
26 |     } else {
27 |         if(req->getSn() % 1000 == 0) {
28 |             SYLAR_LOG_INFO(g_logger) << rt->toString();
29 |         }
30 |     }
31 | }
32 | 
33 | void run() {
34 |     zksd->setSelfInfo("127.0.0.1:2222");
35 |     zksd->setSelfData("aaaa");
36 | 
37 |     std::unordered_map<std::string, std::unordered_map<std::string,std::string> > confs;
38 |     confs["sylar.top"]["blog"] = "fair";
39 |     rsdlb->start(confs);
40 |     //SYLAR_LOG_INFO(g_logger) << "on_timer---";
41 | 
42 |     sylar::IOManager::GetThis()->addTimer(1, on_timer, true);
43 | }
44 | 
45 | int main(int argc, char** argv) {
46 |     sylar::WorkerMgr::GetInstance()->init({
47 |         {"service_io", {
48 |             {"thread_num", "1"}
49 |         }}
50 |     });
51 |     sylar::IOManager iom(1);
52 |     iom.addTimer(1000, [](){
53 |             std::cout << rsdlb->statusString() << std::endl;
54 |     }, true);
55 |     iom.schedule(run);
56 |     return 0;
57 | }
58 | 


--------------------------------------------------------------------------------
/tests/test_socket.cc:
--------------------------------------------------------------------------------
  1 | #include "sylar/socket.h"
  2 | #include "sylar/sylar.h"
  3 | #include "sylar/iomanager.h"
  4 | 
  5 | static sylar::Logger::ptr g_looger = SYLAR_LOG_ROOT();
  6 | 
  7 | void test_socket() {
  8 |     //std::vector<sylar::Address::ptr> addrs;
  9 |     //sylar::Address::Lookup(addrs, "www.baidu.com", AF_INET);
 10 |     //sylar::IPAddress::ptr addr;
 11 |     //for(auto& i : addrs) {
 12 |     //    SYLAR_LOG_INFO(g_looger) << i->toString();
 13 |     //    addr = std::dynamic_pointer_cast<sylar::IPAddress>(i);
 14 |     //    if(addr) {
 15 |     //        break;
 16 |     //    }
 17 |     //}
 18 |     sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress("www.baidu.com");
 19 |     if(addr) {
 20 |         SYLAR_LOG_INFO(g_looger) << "get address: " << addr->toString();
 21 |     } else {
 22 |         SYLAR_LOG_ERROR(g_looger) << "get address fail";
 23 |         return;
 24 |     }
 25 | 
 26 |     sylar::Socket::ptr sock = sylar::Socket::CreateTCP(addr);
 27 |     addr->setPort(80);
 28 |     SYLAR_LOG_INFO(g_looger) << "addr=" << addr->toString();
 29 |     if(!sock->connect(addr)) {
 30 |         SYLAR_LOG_ERROR(g_looger) << "connect " << addr->toString() << " fail";
 31 |         return;
 32 |     } else {
 33 |         SYLAR_LOG_INFO(g_looger) << "connect " << addr->toString() << " connected";
 34 |     }
 35 | 
 36 |     const char buff[] = "GET / HTTP/1.0\r\n\r\n";
 37 |     int rt = sock->send(buff, sizeof(buff));
 38 |     if(rt <= 0) {
 39 |         SYLAR_LOG_INFO(g_looger) << "send fail rt=" << rt;
 40 |         return;
 41 |     }
 42 | 
 43 |     std::string buffs;
 44 |     buffs.resize(4096);
 45 |     rt = sock->recv(&buffs[0], buffs.size());
 46 | 
 47 |     if(rt <= 0) {
 48 |         SYLAR_LOG_INFO(g_looger) << "recv fail rt=" << rt;
 49 |         return;
 50 |     }
 51 | 
 52 |     buffs.resize(rt);
 53 |     SYLAR_LOG_INFO(g_looger) << buffs;
 54 | }
 55 | 
 56 | void test2() {
 57 |     sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress("www.baidu.com:80");
 58 |     if(addr) {
 59 |         SYLAR_LOG_INFO(g_looger) << "get address: " << addr->toString();
 60 |     } else {
 61 |         SYLAR_LOG_ERROR(g_looger) << "get address fail";
 62 |         return;
 63 |     }
 64 | 
 65 |     sylar::Socket::ptr sock = sylar::Socket::CreateTCP(addr);
 66 |     if(!sock->connect(addr)) {
 67 |         SYLAR_LOG_ERROR(g_looger) << "connect " << addr->toString() << " fail";
 68 |         return;
 69 |     } else {
 70 |         SYLAR_LOG_INFO(g_looger) << "connect " << addr->toString() << " connected";
 71 |     }
 72 | 
 73 |     uint64_t ts = sylar::GetCurrentUS();
 74 |     for(size_t i = 0; i < 10000000000ul; ++i) {
 75 |         if(int err = sock->getError()) {
 76 |             SYLAR_LOG_INFO(g_looger) << "err=" << err << " errstr=" << strerror(err);
 77 |             break;
 78 |         }
 79 | 
 80 |         //struct tcp_info tcp_info;
 81 |         //if(!sock->getOption(IPPROTO_TCP, TCP_INFO, tcp_info)) {
 82 |         //    SYLAR_LOG_INFO(g_looger) << "err";
 83 |         //    break;
 84 |         //}
 85 |         //if(tcp_info.tcpi_state != TCP_ESTABLISHED) {
 86 |         //    SYLAR_LOG_INFO(g_looger)
 87 |         //            << " state=" << (int)tcp_info.tcpi_state;
 88 |         //    break;
 89 |         //}
 90 |         static int batch = 10000000;
 91 |         if(i && (i % batch) == 0) {
 92 |             uint64_t ts2 = sylar::GetCurrentUS();
 93 |             SYLAR_LOG_INFO(g_looger) << "i=" << i << " used: " << ((ts2 - ts) * 1.0 / batch) << " us";
 94 |             ts = ts2;
 95 |         }
 96 |     }
 97 | }
 98 | 
 99 | int main(int argc, char** argv) {
100 |     sylar::IOManager iom;
101 |     //iom.schedule(&test_socket);
102 |     iom.schedule(&test2);
103 |     return 0;
104 | }
105 | 


--------------------------------------------------------------------------------
/tests/test_tcp_server.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/tcp_server.h"
 2 | #include "sylar/iomanager.h"
 3 | #include "sylar/log.h"
 4 | 
 5 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 6 | 
 7 | void run() {
 8 |     auto addr = sylar::Address::LookupAny("0.0.0.0:8033");
 9 |     //auto addr2 = sylar::UnixAddress::ptr(new sylar::UnixAddress("/tmp/unix_addr"));
10 |     std::vector<sylar::Address::ptr> addrs;
11 |     addrs.push_back(addr);
12 |     //addrs.push_back(addr2);
13 | 
14 |     sylar::TcpServer::ptr tcp_server(new sylar::TcpServer);
15 |     std::vector<sylar::Address::ptr> fails;
16 |     while(!tcp_server->bind(addrs, fails)) {
17 |         sleep(2);
18 |     }
19 |     tcp_server->start();
20 |     
21 | }
22 | int main(int argc, char** argv) {
23 |     sylar::IOManager iom(2);
24 |     iom.schedule(run);
25 |     return 0;
26 | }
27 | 


--------------------------------------------------------------------------------
/tests/test_thread.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include <unistd.h>
 3 | 
 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | int count = 0;
 7 | //sylar::RWMutex s_mutex;
 8 | sylar::Mutex s_mutex;
 9 | 
10 | void fun1() {
11 |     SYLAR_LOG_INFO(g_logger) << "name: " << sylar::Thread::GetName()
12 |                              << " this.name: " << sylar::Thread::GetThis()->getName()
13 |                              << " id: " << sylar::GetThreadId()
14 |                              << " this.id: " << sylar::Thread::GetThis()->getId();
15 | 
16 |     for(int i = 0; i < 100000; ++i) {
17 |         //sylar::RWMutex::WriteLock lock(s_mutex);
18 |         sylar::Mutex::Lock lock(s_mutex);
19 |         ++count;
20 |     }
21 | }
22 | 
23 | void fun2() {
24 |     while(true) {
25 |         SYLAR_LOG_INFO(g_logger) << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
26 |     }
27 | }
28 | 
29 | void fun3() {
30 |     while(true) {
31 |         SYLAR_LOG_INFO(g_logger) << "========================================";
32 |     }
33 | }
34 | 
35 | int main(int argc, char** argv) {
36 |     SYLAR_LOG_INFO(g_logger) << "thread test begin";
37 |     YAML::Node root = YAML::LoadFile("/home/sylar/test/sylar/bin/conf/log2.yml");
38 |     sylar::Config::LoadFromYaml(root);
39 | 
40 |     std::vector<sylar::Thread::ptr> thrs;
41 |     for(int i = 0; i < 1; ++i) {
42 |         sylar::Thread::ptr thr(new sylar::Thread(&fun2, "name_" + std::to_string(i * 2)));
43 |         //sylar::Thread::ptr thr2(new sylar::Thread(&fun3, "name_" + std::to_string(i * 2 + 1)));
44 |         thrs.push_back(thr);
45 |         //thrs.push_back(thr2);
46 |     }
47 | 
48 |     for(size_t i = 0; i < thrs.size(); ++i) {
49 |         thrs[i]->join();
50 |     }
51 |     SYLAR_LOG_INFO(g_logger) << "thread test end";
52 |     SYLAR_LOG_INFO(g_logger) << "count=" << count;
53 | 
54 |     return 0;
55 | }
56 | 


--------------------------------------------------------------------------------
/tests/test_timed_cache.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/ds/timed_cache.h"
 2 | 
 3 | void test_timed_cache() {
 4 |     sylar::ds::TimedCache<int, int> cache(30, 10);
 5 |     for(int i = 0; i < 105; ++i) {
 6 |         cache.set(i, i * 100, 1000);
 7 |     }
 8 | 
 9 |     for(int i = 0; i < 105; ++i) {
10 |         int v;
11 |         if(cache.get(i, v)) {
12 |             std::cout << "get: " << i << " - "
13 |                       << v
14 |                       << " - " << cache.get(i)
15 |                       << std::endl;
16 |         }
17 |     }
18 | 
19 |     cache.set(1000, 11, 1000 * 10);
20 |     //std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl;
21 |     std::cout << cache.toStatusString() << std::endl;
22 |     sleep(2);
23 |     std::cout << "check_timeout: " << cache.checkTimeout() << std::endl;
24 |     std::cout << cache.toStatusString() << std::endl;
25 | }
26 | 
27 | void test_hash_timed_cache() {
28 |     sylar::ds::HashTimedCache<int, int> cache(2, 30, 10);
29 | 
30 |     for(int i = 0; i < 105; ++i) {
31 |         cache.set(i, i * 100, -1000 * i);
32 |     }
33 | 
34 |     for(int i = 0; i < 105; ++i) {
35 |         int v;
36 |         if(cache.get(i, v)) {
37 |             std::cout << "get: " << i << " - " << v << std::endl;
38 |         }
39 |     }
40 | 
41 |     cache.expired(100, 1000 * 10);
42 | 
43 |     cache.set(1000, 11, 1000 * 10);
44 |     std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl;
45 |     std::cout << cache.toStatusString() << std::endl;
46 |     sleep(2);
47 |     std::cout << "check_timeout: " << cache.checkTimeout() << std::endl;
48 |     std::cout << cache.toStatusString() << std::endl;
49 | }
50 | 
51 | int main(int argc, char** argv) {
52 |     test_timed_cache();
53 |     test_hash_timed_cache();
54 |     return 0;
55 | }
56 | 


--------------------------------------------------------------------------------
/tests/test_timed_lru_cache.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/ds/timed_lru_cache.h"
 2 | 
 3 | void test_timed_lru_cache() {
 4 |     sylar::ds::TimedLruCache<int, int> cache(30, 10);
 5 |     for(int i = 0; i < 105; ++i) {
 6 |         cache.set(i, i * 100, 1000);
 7 |     }
 8 | 
 9 |     for(int i = 0; i < 105; ++i) {
10 |         int v;
11 |         if(cache.get(i, v)) {
12 |             std::cout << "get: " << i << " - "
13 |                       << v
14 |                       << " - " << cache.get(i)
15 |                       << std::endl;
16 |         }
17 |     }
18 | 
19 |     cache.set(1000, 11, 1000 * 10);
20 |     //std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl;
21 |     std::cout << cache.toStatusString() << std::endl;
22 |     sleep(2);
23 |     std::cout << "check_timeout: " << cache.checkTimeout() << std::endl;
24 |     std::cout << cache.toStatusString() << std::endl;
25 | }
26 | 
27 | void test_hash_timed_lru_cache() {
28 |     sylar::ds::HashTimedLruCache<int, int> cache(2, 30, 10);
29 |     for(int i = 0; i < 105; ++i) {
30 |         cache.set(i, i * 100, 1000);
31 |     }
32 | 
33 |     for(int i = 0; i < 105; ++i) {
34 |         int v;
35 |         if(cache.get(i, v)) {
36 |             std::cout << "get: " << i << " - "
37 |                       << v
38 |                       << " - " << cache.get(i)
39 |                       << std::endl;
40 |         }
41 |     }
42 | 
43 |     cache.set(1000, 11, 1000 * 10);
44 |     //std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl;
45 |     std::cout << cache.toStatusString() << std::endl;
46 |     sleep(2);
47 |     std::cout << "check_timeout: " << cache.checkTimeout() << std::endl;
48 |     std::cout << cache.toStatusString() << std::endl;
49 | }
50 | 
51 | int main(int argc, char** argv) {
52 |     test_timed_lru_cache();
53 |     test_hash_timed_lru_cache();
54 |     return 0;
55 | }
56 | 


--------------------------------------------------------------------------------
/tests/test_uri.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/uri.h"
 2 | #include <iostream>
 3 | 
 4 | int main(int argc, char** argv) {
 5 |     //sylar::Uri::ptr uri = sylar::Uri::Create("http://www.sylar.top/test/uri?id=100&name=sylar#frg");
 6 |     //sylar::Uri::ptr uri = sylar::Uri::Create("http://admin@www.sylar.top/test/中文/uri?id=100&name=sylar&vv=中文#frg中文");
 7 |     sylar::Uri::ptr uri = sylar::Uri::Create("http://admin@www.sylar.top");
 8 |     //sylar::Uri::ptr uri = sylar::Uri::Create("http://www.sylar.top/test/uri");
 9 |     std::cout << uri->toString() << std::endl;
10 |     auto addr = uri->createAddress();
11 |     std::cout << *addr << std::endl;
12 |     return 0;
13 | }
14 | 


--------------------------------------------------------------------------------
/tests/test_util.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/sylar.h"
 2 | #include <assert.h>
 3 | 
 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | void test_assert() {
 7 |     SYLAR_LOG_INFO(g_logger) << sylar::BacktraceToString(10);
 8 |     //SYLAR_ASSERT2(0 == 1, "abcdef xx");
 9 | }
10 | 
11 | int main(int argc, char** argv) {
12 |     test_assert();
13 | 
14 |     int arr[] = {1,3,5,7,9,11};
15 | 
16 |     SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 0);
17 |     SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 1);
18 |     SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 4);
19 |     SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 13);
20 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 0) == -1);
21 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 1) == 0);
22 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 2) == -2);
23 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 3) == 1);
24 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 4) == -3);
25 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 5) == 2);
26 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 6) == -4);
27 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 7) == 3);
28 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 8) == -5);
29 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 9) == 4);
30 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 10) == -6);
31 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 11) == 5);
32 |     SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 12) == -7);
33 |     return 0;
34 | }
35 | 


--------------------------------------------------------------------------------
/tests/test_ws_client.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/http/ws_connection.h"
 2 | #include "sylar/iomanager.h"
 3 | #include "sylar/util.h"
 4 | 
 5 | void run() {
 6 |     auto rt = sylar::http::WSConnection::Create("http://127.0.0.1:8020/sylar", 1000);
 7 |     if(!rt.second) {
 8 |         std::cout << rt.first->toString() << std::endl;
 9 |         return;
10 |     }
11 | 
12 |     auto conn = rt.second;
13 |     while(true) {
14 |         //for(int i = 0; i < 1100; ++i) {
15 |         for(int i = 0; i < 1; ++i) {
16 |             conn->sendMessage(sylar::random_string(60), sylar::http::WSFrameHead::TEXT_FRAME, false);
17 |         }
18 |         conn->sendMessage(sylar::random_string(65), sylar::http::WSFrameHead::TEXT_FRAME, true);
19 |         auto msg = conn->recvMessage();
20 |         if(!msg) {
21 |             break;
22 |         }
23 |         std::cout << "opcode=" << msg->getOpcode()
24 |                   << " data=" << msg->getData() << std::endl;
25 | 
26 |         sleep(10);
27 |     }
28 | }
29 | 
30 | int main(int argc, char** argv) {
31 |     srand(time(0));
32 |     sylar::IOManager iom(1);
33 |     iom.schedule(run);
34 |     return 0;
35 | }
36 | 


--------------------------------------------------------------------------------
/tests/test_ws_server.cc:
--------------------------------------------------------------------------------
 1 | #include "sylar/http/ws_server.h"
 2 | #include "sylar/log.h"
 3 | 
 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();
 5 | 
 6 | void run() {
 7 |     sylar::http::WSServer::ptr server(new sylar::http::WSServer);
 8 |     sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020");
 9 |     if(!addr) {
10 |         SYLAR_LOG_ERROR(g_logger) << "get address error";
11 |         return;
12 |     }
13 |     auto fun = [](sylar::http::HttpRequest::ptr header
14 |                   ,sylar::http::WSFrameMessage::ptr msg
15 |                   ,sylar::http::WSSession::ptr session) {
16 |         session->sendMessage(msg);
17 |         return 0;
18 |     };
19 | 
20 |     server->getWSServletDispatch()->addServlet("/sylar", fun);
21 |     while(!server->bind(addr)) {
22 |         SYLAR_LOG_ERROR(g_logger) << "bind " << *addr << " fail";
23 |         sleep(1);
24 |     }
25 |     server->start();
26 | }
27 | 
28 | int main(int argc, char** argv) {
29 |     sylar::IOManager iom(2);
30 |     iom.schedule(run);
31 |     return 0;
32 | }
33 | 


--------------------------------------------------------------------------------