From dfeef3a6bfa9a8cccf6c322f56e7d574a057e4a6 Mon Sep 17 00:00:00 2001 From: zhengshuxin Date: Tue, 16 May 2017 23:22:07 +0800 Subject: [PATCH] fiber service can exit until all the clients are closed, specified by configure. --- app/wizard/tmpl/http/master_fiber.cf | 4 + app/wizard/tmpl/master/master_fiber.cf | 4 + app/wizard_demo/qrserver/Makefile | 5 + app/wizard_demo/qrserver/Makefile.in | 137 ++++++ app/wizard_demo/qrserver/http_servlet.cpp | 108 +++++ app/wizard_demo/qrserver/http_servlet.h | 23 + app/wizard_demo/qrserver/main.cpp | 77 ++++ app/wizard_demo/qrserver/master_service.cpp | 134 ++++++ app/wizard_demo/qrserver/master_service.h | 114 +++++ app/wizard_demo/qrserver/qrserver.cf | 136 ++++++ app/wizard_demo/qrserver/qrserver.sln | 27 ++ app/wizard_demo/qrserver/qrserver.vcproj | 289 ++++++++++++ app/wizard_demo/qrserver/qrserver_vc2008.sln | 25 ++ .../qrserver/qrserver_vc2008.vcproj | 425 ++++++++++++++++++ app/wizard_demo/qrserver/qrserver_vc2010.sln | 25 ++ .../qrserver/qrserver_vc2010.vcxproj | 202 +++++++++ .../qrserver/qrserver_vc2010.vcxproj.filters | 45 ++ app/wizard_demo/qrserver/qrserver_vc2012.sln | 37 ++ .../qrserver/qrserver_vc2012.vcxproj | 365 +++++++++++++++ .../qrserver/qrserver_vc2012.vcxproj.filters | 45 ++ app/wizard_demo/qrserver/stdafx.cpp | 8 + app/wizard_demo/qrserver/stdafx.h | 19 + app/wizard_demo/qrserver/valgrind.sh | 3 + lib_fiber/c/src/master/fiber_server.c | 45 +- lib_fiber/changes.txt | 4 + 25 files changed, 2298 insertions(+), 8 deletions(-) create mode 100644 app/wizard_demo/qrserver/Makefile create mode 100644 app/wizard_demo/qrserver/Makefile.in create mode 100644 app/wizard_demo/qrserver/http_servlet.cpp create mode 100644 app/wizard_demo/qrserver/http_servlet.h create mode 100644 app/wizard_demo/qrserver/main.cpp create mode 100644 app/wizard_demo/qrserver/master_service.cpp create mode 100644 app/wizard_demo/qrserver/master_service.h create mode 100644 app/wizard_demo/qrserver/qrserver.cf create mode 100644 app/wizard_demo/qrserver/qrserver.sln create mode 100644 app/wizard_demo/qrserver/qrserver.vcproj create mode 100644 app/wizard_demo/qrserver/qrserver_vc2008.sln create mode 100644 app/wizard_demo/qrserver/qrserver_vc2008.vcproj create mode 100644 app/wizard_demo/qrserver/qrserver_vc2010.sln create mode 100644 app/wizard_demo/qrserver/qrserver_vc2010.vcxproj create mode 100644 app/wizard_demo/qrserver/qrserver_vc2010.vcxproj.filters create mode 100644 app/wizard_demo/qrserver/qrserver_vc2012.sln create mode 100644 app/wizard_demo/qrserver/qrserver_vc2012.vcxproj create mode 100644 app/wizard_demo/qrserver/qrserver_vc2012.vcxproj.filters create mode 100644 app/wizard_demo/qrserver/stdafx.cpp create mode 100644 app/wizard_demo/qrserver/stdafx.h create mode 100644 app/wizard_demo/qrserver/valgrind.sh diff --git a/app/wizard/tmpl/http/master_fiber.cf b/app/wizard/tmpl/http/master_fiber.cf index ebedd1b43..a28eda36d 100644 --- a/app/wizard/tmpl/http/master_fiber.cf +++ b/app/wizard/tmpl/http/master_fiber.cf @@ -80,6 +80,10 @@ service $ # 当 acl_master 退出时,如果该值置1则该程序不等所有连接处理完毕便立即退出 fiber_quick_abort = 1 +# 当 fiber_quick_abort 为 0 且本配置项大于 0 时,该配置项才有效,指定了 +# 本进程在所有连接退出前的最大等待时间(秒) + fiber_wait_limit = 0 + ############################################################################ # 应用自己的配置选项 diff --git a/app/wizard/tmpl/master/master_fiber.cf b/app/wizard/tmpl/master/master_fiber.cf index ebedd1b43..a28eda36d 100644 --- a/app/wizard/tmpl/master/master_fiber.cf +++ b/app/wizard/tmpl/master/master_fiber.cf @@ -80,6 +80,10 @@ service $ # 当 acl_master 退出时,如果该值置1则该程序不等所有连接处理完毕便立即退出 fiber_quick_abort = 1 +# 当 fiber_quick_abort 为 0 且本配置项大于 0 时,该配置项才有效,指定了 +# 本进程在所有连接退出前的最大等待时间(秒) + fiber_wait_limit = 0 + ############################################################################ # 应用自己的配置选项 diff --git a/app/wizard_demo/qrserver/Makefile b/app/wizard_demo/qrserver/Makefile new file mode 100644 index 000000000..74b54718e --- /dev/null +++ b/app/wizard_demo/qrserver/Makefile @@ -0,0 +1,5 @@ +include ./Makefile.in +ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD) + EXTLIBS += -L/usr/local/lib -liconv +endif +PROG = qrserver diff --git a/app/wizard_demo/qrserver/Makefile.in b/app/wizard_demo/qrserver/Makefile.in new file mode 100644 index 000000000..5ef6c41ce --- /dev/null +++ b/app/wizard_demo/qrserver/Makefile.in @@ -0,0 +1,137 @@ +CC = g++ + +CFLAGS = -c -g -W -Wall -Wcast-qual -Wcast-align \ +-Waggregate-return -Wno-long-long \ +-Wpointer-arith -Werror -Wshadow -O3 \ +-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_USE_FAST_MACRO + +########################################################### +#Check system: +# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX +SYSLIB = -lpthread -lz +CHECKSYSRES = @echo "Unknow system type!";exit 1 +UNIXNAME = $(shell uname -s) +OSTYPE = $(shell uname -m) +RPATH = linux64 + +ifeq ($(CC),) + CC = gcc +endif + +# For FreeBSD +ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD) + ifeq ($(findstring gcc, $(CC)), gcc) + CFLAGS += -Wstrict-prototypes + endif + CFLAGS += -DFREEBSD -D_REENTRANT + SYSLIB = -lcrypt -lpthread -lz + RPATH = freebsd +endif + +# For Darwin +ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin) + CFLAGS += -DMACOSX -Wno-invalid-source-encoding \ + -Wno-extended-offsetof + UNIXTYPE = MACOSX + SYSLIB += -liconv -rdynamic + RPATH = macos +endif + +#Path for Linux +ifeq ($(findstring Linux, $(UNIXNAME)), Linux) + ifeq ($CC, "gcc") + CFLAGS += -Wstrict-prototypes + endif + ifeq ($(findstring i686, $(OSTYPE)), i686) + RPATH = linux32 + endif + ifeq ($(findstring x86_64, $(OSTYPE)), x86_64) + RPATH = linux64 + endif + CFLAGS += -DLINUX2 -D_REENTRANT + SYSLIB += -lcrypt +endif + +# For MINGW +ifeq ($(findstring MINGW, $(UNIXNAME)), MINGW) + SYSLIB = -lpthread-2 -liconv + CFLAGS += -DLINUX2 -DMINGW + UNIXTYPE = LINUX +endif + +# For MSYS +ifeq ($(findstring MSYS, $(UNIXNAME)), MSYS) + SYSLIB = -lpthread-2 -liconv + CFLAGS += -DLINUX2 -DMINGW + UNIXTYPE = LINUX +endif + +#Path for SunOS +ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS) + ifeq ($(findstring 86, $(UNIXNAME)), 86) + SYSLIB += -lsocket -lnsl -lrt + endif + ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u) + SYSLIB += -lsocket -lnsl -lrt + endif + ifeq ($CC, "gcc") + CFLAGS += -Wstrict-prototypes + endif + CFLAGS += -DSUNOS5 -D_REENTRANT + RPATH = sunos_x86 +endif + +#Path for HP-UX +ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX) + ifeq ($CC, "gcc") + CFLAGS += -Wstrict-prototypes + endif + CFLAGS += -DHP_UX -DHPUX11 + PLAT_NAME=hp-ux +endif + +#Find system type. +ifneq ($(SYSPATH),) + CHECKSYSRES = @echo "System is $(shell uname -sm)" +endif +########################################################### + +ACL_PATH = ../../.. +CFLAGS += -I$(ACL_PATH)/lib_acl/include \ + -I$(ACL_PATH)/lib_protocol/include \ + -I$(ACL_PATH)/lib_acl_cpp/include \ + -I/home/zsx/download/qr/qrcode/libqr +EXTLIBS = +LDFLAGS = -L$(ACL_PATH)/lib_acl_cpp/lib -l_acl_cpp \ + -L$(ACL_PATH)/lib_protocol/lib -l_protocol \ + -L$(ACL_PATH)/lib_acl/lib -l_acl \ + /home/zsx/download/qr/qrcode/libqr/libqr.a \ + $(EXTLIBS) $(SYSLIB) + +COMPILE = $(CC) $(CFLAGS) +LINK = $(CC) $(OBJ) $(LDFLAGS) +########################################################### +OBJ_PATH = . + +#Project's objs +SRC = $(wildcard *.cpp) +OBJ = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(notdir $(SRC))) + +$(OBJ_PATH)/%.o: %.cpp + $(COMPILE) $< -o $@ + +.PHONY = all clean +all: RM $(OBJ) + $(LINK) -o $(PROG) + @echo "" + @echo "All ok! Output:$(PROG)" + @echo "" +RM: + rm -f $(PROG) +clean: + rm -f $(PROG) + rm -f $(OBJ) +install: + cp $(PROG) ../../../dist/master/libexec/$(RPATH)/ + cp $(PROG).cf ../../../dist/master/conf/service/ +########################################################### diff --git a/app/wizard_demo/qrserver/http_servlet.cpp b/app/wizard_demo/qrserver/http_servlet.cpp new file mode 100644 index 000000000..52350f41f --- /dev/null +++ b/app/wizard_demo/qrserver/http_servlet.cpp @@ -0,0 +1,108 @@ +#include "stdafx.h" +#include "qr.h" +#include "http_servlet.h" + +http_servlet::http_servlet(acl::socket_stream* stream, acl::session* session) +: acl::HttpServlet(stream, session) +{ + +} + +http_servlet::~http_servlet(void) +{ + +} + +bool http_servlet::doError(acl::HttpServletRequest&, + acl::HttpServletResponse& res) +{ + res.setStatus(400); + res.setContentType("text/xml; charset=utf-8"); + + // 发送 http 响应体 + acl::string buf; + buf.format("\r\n"); + res.write(buf); + res.write(NULL, 0); + return false; +} + +bool http_servlet::doOther(acl::HttpServletRequest&, + acl::HttpServletResponse& res, const char* method) +{ + res.setStatus(400); + res.setContentType("text/xml; charset=utf-8"); + // 发送 http 响应体 + acl::string buf; + buf.format("\r\n", method); + res.write(buf); + res.write(NULL, 0); + return false; +} + +bool http_servlet::doGet(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + return doPost(req, res); +} + +bool http_servlet::doPost(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + int errcode = QR_ERR_NONE; + QRCode* qr = qrInit(10, QR_EM_8BIT, 2, -1, &errcode); + if (qr == NULL) + { + logger_error("qrInit error!"); + return replyf(req, res, "qrInit error"); + } + + const char* url = req.getParameter("url"); + if (url == NULL || *url == 0) + url = "http://www.qq.com"; + + qrAddData(qr, (const qr_byte_t*) url, strlen(url)); + if (!qrFinalize(qr)) + { + logger_error("qrFinalize error!"); + qrDestroy(qr); + return replyf(req, res, "qrFinalize error"); + } + + int size = 0; + qr_byte_t *buffer = qrSymbolToPNG(qr, 5, 5, &size); + if (buffer == NULL) + { + logger_error("qrSymbolToPNG error"); + qrDestroy(qr); + return replyf(req, res, "qrSymbolToPNG error"); + } + + res.setContentType("image/png") // 设置响应字符集 + .setKeepAlive(req.isKeepAlive()) // 设置是否保持长连接 + .setContentEncoding(true) // 自动支持压缩传输 + .setContentLength(size); + bool ret = res.write(buffer, size) && res.write(NULL, 0); + + qrDestroy(qr); + + return ret; +} + +bool http_servlet::replyf(acl::HttpServletRequest& req, + acl::HttpServletResponse& res, + const char* fmt, ...) +{ + acl::string buf; + va_list ap; + va_start(ap, fmt); + buf.vformat(fmt, ap); + va_end(ap); + + res.setContentType("text/plain; charset=utf-8") // 设置响应字符集 + .setKeepAlive(req.isKeepAlive()) // 设置是否保持长连接 + .setContentEncoding(true) // 自动支持压缩传输 + .setContentLength(buf.size()); + + return res.write(buf) && res.write(NULL, 0); +} diff --git a/app/wizard_demo/qrserver/http_servlet.h b/app/wizard_demo/qrserver/http_servlet.h new file mode 100644 index 000000000..20ec2fca4 --- /dev/null +++ b/app/wizard_demo/qrserver/http_servlet.h @@ -0,0 +1,23 @@ +#pragma once + +class http_servlet : public acl::HttpServlet +{ +public: + http_servlet(acl::socket_stream* stream, acl::session* session); + ~http_servlet(); + +protected: + virtual bool doError(acl::HttpServletRequest&, + acl::HttpServletResponse& res); + virtual bool doOther(acl::HttpServletRequest&, + acl::HttpServletResponse& res, const char* method); + virtual bool doGet(acl::HttpServletRequest& req, + acl::HttpServletResponse& res); + virtual bool doPost(acl::HttpServletRequest& req, + acl::HttpServletResponse& res); + +private: + bool replyf(acl::HttpServletRequest& req, + acl::HttpServletResponse& res, + const char* fmt, ...); +}; diff --git a/app/wizard_demo/qrserver/main.cpp b/app/wizard_demo/qrserver/main.cpp new file mode 100644 index 000000000..ff41c9a44 --- /dev/null +++ b/app/wizard_demo/qrserver/main.cpp @@ -0,0 +1,77 @@ +#include "stdafx.h" +#include "master_service.h" + +int main(int argc, char* argv[]) +{ + // 初始化 acl 库 + acl::acl_cpp_init(); + + master_service& ms = acl::singleton2::get_instance(); + + // 设置配置参数表 + ms.set_cfg_int(var_conf_int_tab); + ms.set_cfg_int64(var_conf_int64_tab); + ms.set_cfg_str(var_conf_str_tab); + ms.set_cfg_bool(var_conf_bool_tab); + + // 开始运行 + + if (argc >= 2 && strcmp(argv[1], "alone") == 0) + { + // 日志输出至标准输出 + acl::log::stdout_open(true); + + // 监听的地址列表,格式:ip:port1,ip:port2,... + const char* addrs = ":8886"; + printf("listen on: %s\r\n", addrs); + + // 测试时设置该值 > 0 则指定服务器处理客户端连接过程的 + // 会话总数(一个连接从接收到关闭称之为一个会话),当 + // 处理的连接会话数超过此值,测试过程结束;如果该值设 + // 为 0,则测试过程永远不结束 + unsigned int count = 0; + + // 测试过程中指定线程池最大线程个数 + unsigned int max_threads = 100; + + // 单独运行方式 + + if (argc >= 3) + ms.run_alone(addrs, argv[2], count, max_threads); + else + ms.run_alone(addrs, NULL, count, max_threads); + + printf("Enter any key to exit now\r\n"); + getchar(); + } + else + { +#ifdef WIN32 + // 日志输出至标准输出 + acl::log::stdout_open(true); + + // 监听的地址列表,格式:ip:port1,ip:port2,... + const char* addrs = "127.0.0.1:8888"; + printf("listen on: %s\r\n", addrs); + + // 测试时设置该值 > 0 则指定服务器处理客户端连接过程的 + // 会话总数(一个连接从接收到关闭称之为一个会话),当 + // 处理的连接会话数超过此值,测试过程结束;如果该值设 + // 为 0,则测试过程永远不结束 + unsigned int count = 0; + + // 测试过程中指定线程池最大线程个数 + unsigned int max_threads = 100; + + // 单独运行方式 + ms.run_alone(addrs, NULL, count, max_threads); + printf("Enter any key to exit now\r\n"); + getchar(); +#else + // acl_master 控制模式运行 + ms.run_daemon(argc, argv); +#endif + } + + return 0; +} diff --git a/app/wizard_demo/qrserver/master_service.cpp b/app/wizard_demo/qrserver/master_service.cpp new file mode 100644 index 000000000..ebb3c744a --- /dev/null +++ b/app/wizard_demo/qrserver/master_service.cpp @@ -0,0 +1,134 @@ +#include "stdafx.h" +#include "http_servlet.h" +#include "master_service.h" + +////////////////////////////////////////////////////////////////////////////// +// 配置内容项 + +char *var_cfg_redis_addrs; +acl::master_str_tbl var_conf_str_tab[] = { + { "redis_addrs", "127.0.0.1:6379", &var_cfg_redis_addrs }, + + { 0, 0, 0 } +}; + +int var_cfg_use_redis_session; +acl::master_bool_tbl var_conf_bool_tab[] = { + { "use_redis_session", 1, &var_cfg_use_redis_session }, + + { 0, 0, 0 } +}; + +int var_cfg_conn_timeout; +int var_cfg_rw_timeout; +int var_cfg_max_threads; +acl::master_int_tbl var_conf_int_tab[] = { + { "rw_timeout", 120, &var_cfg_rw_timeout, 0, 0 }, + { "ioctl_max_threads", 128, &var_cfg_max_threads, 0, 0 }, + + { 0, 0 , 0 , 0, 0 } +}; + +long long int var_cfg_int64; +acl::master_int64_tbl var_conf_int64_tab[] = { + { "int64", 120, &var_cfg_int64, 0, 0 }, + + { 0, 0 , 0 , 0, 0 } +}; + +////////////////////////////////////////////////////////////////////////////// + +master_service::master_service() +{ + redis_ = NULL; +} + +master_service::~master_service() +{ +} + +bool master_service::thread_on_read(acl::socket_stream* conn) +{ + http_servlet* servlet = (http_servlet*) conn->get_ctx(); + if (servlet == NULL) + logger_fatal("servlet null!"); + + return servlet->doRun(); +} + +bool master_service::thread_on_accept(acl::socket_stream* conn) +{ + logger("connect from %s, fd: %d", conn->get_peer(true), + conn->sock_handle()); + + conn->set_rw_timeout(var_cfg_rw_timeout); + if (var_cfg_rw_timeout > 0) + conn->set_tcp_non_blocking(true); + + acl::session* session; + if (var_cfg_use_redis_session) + session = new acl::redis_session(*redis_, var_cfg_max_threads); + else + session = new acl::memcache_session("127.0.0.1:11211"); + + http_servlet* servlet = new http_servlet(conn, session); + conn->set_ctx(servlet); + + return true; +} + +bool master_service::thread_on_timeout(acl::socket_stream* conn) +{ + logger("read timeout from %s, fd: %d", conn->get_peer(), + conn->sock_handle()); + return false; +} + +void master_service::thread_on_close(acl::socket_stream* conn) +{ + logger("disconnect from %s, fd: %d", conn->get_peer(), + conn->sock_handle()); + + http_servlet* servlet = (http_servlet*) conn->get_ctx(); + acl::session* session = &servlet->getSession(); + delete session; + delete servlet; +} + +void master_service::thread_on_init() +{ +} + +void master_service::thread_on_exit() +{ +} + +void master_service::proc_on_listen(acl::server_socket& ss) +{ + logger(">>>listen %s ok<<<", ss.get_addr()); +} + +void master_service::proc_on_init() +{ + // create redis cluster for session cluster + redis_ = new acl::redis_client_cluster; + redis_->init(NULL, var_cfg_redis_addrs, var_cfg_max_threads, + var_cfg_conn_timeout, var_cfg_rw_timeout); +} + +void master_service::proc_on_exit() +{ + delete redis_; +} + +bool master_service::proc_exit_timer(size_t nclients, size_t nthreads) +{ + if (nclients == 0) + { + logger("clients count: %d, threads count: %d", + (int) nclients, (int) nthreads); + return true; + } + + return false; +} diff --git a/app/wizard_demo/qrserver/master_service.h b/app/wizard_demo/qrserver/master_service.h new file mode 100644 index 000000000..6d6d1b7eb --- /dev/null +++ b/app/wizard_demo/qrserver/master_service.h @@ -0,0 +1,114 @@ +#pragma once + +//////////////////////////////////////////////////////////////////////////////// +// 配置内容项 + +extern char *var_cfg_str; +extern acl::master_str_tbl var_conf_str_tab[]; + +extern int var_cfg_bool; +extern acl::master_bool_tbl var_conf_bool_tab[]; + +extern acl::master_int_tbl var_conf_int_tab[]; + +extern long long int var_cfg_int64; +extern acl::master_int64_tbl var_conf_int64_tab[]; + +//////////////////////////////////////////////////////////////////////////////// + +//class acl::socket_stream; + +class master_service : public acl::master_threads +{ +public: + master_service(); + ~master_service(); + +protected: + /** + * @override + * 虚函数:当某个客户端连接有数据可读或关闭或出错时调用此函数 + * @param stream {socket_stream*} + * @return {bool} 返回 false 则表示当函数返回后需要关闭连接, + * 否则表示需要保持长连接,如果该流出错,则应用应该返回 false + */ + bool thread_on_read(acl::socket_stream* stream); + + /** + * @override + * 当线程池中的某个线程获得一个连接时的回调函数, + * 子类可以做一些初始化工作 + * @param stream {socket_stream*} + * @return {bool} 如果返回 false 则表示子类要求关闭连接,而不 + * 必将该连接再传递至 thread_main 过程 + */ + bool thread_on_accept(acl::socket_stream* stream); + + /** + * @override + * 当某个网络连接的 IO 读写超时时的回调函数,如果该函数返回 true 则 + * 表示继续等待下一次读写,否则则希望关闭该连接 + * @param stream {socket_stream*} + * @return {bool} 如果返回 false 则表示子类要求关闭连接,而不 + * 必将该连接再传递至 thread_main 过程 + */ + bool thread_on_timeout(acl::socket_stream* stream); + + /** + * @override + * 当与某个线程绑定的连接关闭时的回调函数 + * @param stream {socket_stream*} + */ + void thread_on_close(acl::socket_stream* stream); + + /** + * @override + * 当线程池中一个新线程被创建时的回调函数 + */ + void thread_on_init(); + + /** + * @override + * 当线程池中一个线程退出时的回调函数 + */ + void thread_on_exit(); + + /** + * @override + * 在进程启动时,服务进程每成功监听一个本地地址,便调用本函数 + * @param ss {acl::server_socket&} 监听对象 + */ + void proc_on_listen(acl::server_socket& ss); + + /** + * @override + * 当进程切换用户身份后调用的回调函数,此函数被调用时,进程 + * 的权限为普通受限级别 + */ + void proc_on_init(); + + /** + * @override + * 当子进程需要退出时框架将回调此函数,框架决定子进程是否退出取决于: + * 1) 如果此函数返回 true 则子进程立即退出,否则: + * 2) 如果该子进程所有客户端连接都已关闭,则子进程立即退出,否则: + * 3) 查看配置文件中的配置项(ioctl_quick_abort),如果该配置项非 0 则 + * 子进程立即退出,否则: + * 4) 等所有客户端连接关闭后才退出 + * @param ncleints {size_t} 当前连接的客户端个数 + * @param nthreads {size_t} 当前线程池中繁忙的工作线程个数 + * @return {bool} 返回 false 表示当前子进程还不能退出,否则表示当前 + * 子进程可以退出了 + */ + bool proc_exit_timer(size_t nclients, size_t nthreads); + + /** + * @override + * 当进程退出前调用的回调函数 + */ + void proc_on_exit(); + +private: + // redis 集群对象 + acl::redis_client_cluster* redis_; +}; diff --git a/app/wizard_demo/qrserver/qrserver.cf b/app/wizard_demo/qrserver/qrserver.cf new file mode 100644 index 000000000..b572890ef --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver.cf @@ -0,0 +1,136 @@ + +service qrserver { +# 进程是否禁止运行 + master_disable = no +# 服务地址及端口号 +# for master_type = inet +# master_service = 127.0.0.1:5001 +# for master_type = unix +# master_service = echo.sock +# for master_type = sock + master_service = 127.0.0.1:5001, 5002, :5003, echo.sock, echo2.sock + +# 服务监听为域套接口 +# master_service = aio_echo.sock +# 服务类型 +# master_type = inet +# master_type = unix + master_type = sock + +# 当子进程异常退出时,如果该值非空,则将子进程异常退出的消息通知该服务 +# master_notify_addr = 127.0.0.1:5801 +# 邮件通知接收者 +# master_notify_recipients = zhengshuxin@hotmail.com + +# 是否允许延迟接受客户端连接,如果为0则表示关闭该功能,如果大于0则表示打开此功能 +# 并且此值代表延迟接受连接的超时值,超过此值时如果客户端依然没有发来数据,则操作 +# 系统会在系统层直接关闭该连接 +# master_defer_accept = 0 +# 是否只允许私有访问, 如果为 y, 则域套接口创建在 {install_path}/var/log/private/ 目录下, +# 如果为 n, 则域套接口创建在 {install_path}/var/log/public/ 目录下, + master_private = n + master_unpriv = n +# 是否需要 chroot: n -- no, y -- yes + master_chroot = n +# 每隔多长时间触发一次,单位为秒(仅对 trigger 模式有效) + master_wakeup = - +# 最大进程数 + master_maxproc = 1 +# 预启动进程数,该值不得大于 master_maxproc +# master_prefork = 0 +# 进程程序名 + master_command = qrserver +# 进程日志记录文件 + master_log = {install_path}/var/log/qrserver +# 调试日志方式,格式:tag:level; tag:level; tab:level, 如:all:1; 101:2 +# master_debug = +# 进程启动参数,只能为: -u [是否允许以某普通用户的身份运行] +# master_args = +# 传递给服务子进程的环境变量, 可以通过 getenv("SERVICE_ENV") 获得此值 +# master_env = mempool_limit:512000000 +# master_env = logme:FALSE, priority:E_LOG_INFO, action:E_LOG_PER_DAY, flush:sync_flush, imit_size:512,\ +# sync_action:E_LOG_SEM, sem_name:/tmp/ioctl_echo.sem + +# 当启动多个子进程实例时,该开关控制多个子进程在接收连接时是否向 acl_master 发送消息报告自己的状态 +# master_status_notify = 1 +# 是否允许产生 core 文件 +# ioctl_enable_core = 1 +# 每个进程实例处理连接数的最大次数,超过此值后进程实例主动退出 + ioctl_use_limit = 0 +# 每个进程实例的空闲超时时间,超过此值后进程实例主动退出 + ioctl_idle_limit = 0 +# 记录进程PID的位置(对于多进程实例来说没有意义) + ioctl_pid_dir = {install_path}/var/pid +# 进程运行时所在的路径 + ioctl_queue_dir = {install_path}/var +# 读写超时时间, 单位为秒 + ioctl_rw_timeout = 120 +# 读缓冲区的缓冲区大小 + ioctl_buf_size = 8192 +# 每次 accept 时的循环接收的最大次数 + ioctl_max_accept = 25 +# 在并发访问量非常低的情况下,如访问量在 10 次/秒 以下时,可以找开此值(即赋为1), +# 以加速事件循环过程, 从而防止服务进程阻塞在 select 上的时间过长而影响访问速度 +# ioctl_enable_dog = 1 +# 进程运行时的用户身份 + ioctl_owner = root + +# 用 select 进行循环时的时间间隔 +# 单位为秒 + ioctl_delay_sec = 1 +# 单位为微秒 + ioctl_delay_usec = 500 + +# 采用事件循环的方式: select(default), poll, kernel(epoll/devpoll/kqueue) + ioctl_event_mode = kernel +# 事件引擎检查所有空闲描述符的时间间隔(毫秒) +# ioctl_check_inter = 100 +# 当启用 master_dispatch 连接分开服务后,该配置指定 master_dispatch 所监听的 +# 域套接口的全路径,这样本子进程就可以从 master_dispatch 获得客户端连接 +# ioctl_dispatch_addr = {install_path}/var/private/dispatch.sock +# 当 ioctl_dispatch_addr 开启后,下面参数控制本服务进程发给前端 master_dispatch 的服务标识信息 +# ioctl_dispatch_type = default + +# 线程池的最大线程数 + ioctl_max_threads = 250 +# 线程池中工作线程等待任务时间间隔(毫秒) +# ioctl_schedule_wait = 50 +# 线程任务调度的时间间隔大于此值(毫秒)后记警告日志 +# ioctl_schedule_warn = 100 +# 线程处理任务拥堵数超过此阀值后记警告日志,设为 0 则内部只有当拥堵任务数超过总线程数的 10 倍时才报警 +# ioctl_qlen_warn = 0 +# 线程的堆栈空间大小,单位为字节,0表示使用系统缺省值 + ioctl_stacksize = 0 +# 允许访问 udserver 的客户端IP地址范围 +# ioctl_access_allow = 127.0.0.1:255.255.255.255, 127.0.0.1:127.0.0.1 + ioctl_access_allow = all + +# 当 acl_master 退出时,如果该值置1则该程序不等所有连接处理完毕便立即退出 + ioctl_quick_abort = 1 + +############################################################################ +# 应用自己的配置选项 + +# mysql 服务地址 +# mysql_dbaddr = /tmp/mysql.sock +# mysql_dbaddr = 10.0.250.199:3306 +# 连接 mysql 数据库的连接池的最大值 +# mysql_dbmax = 200 +# ping mysql 连接的间隔时间, 以秒为单位 +# mysql_dbping = 10 +# mysql 连接空闲的时间间隔, 以秒为单位 +# mysql_dbtimeout = 30 + +# 数据库名称 +# mysql_dbname = ioctl_db +# 数据库访问用户 +# mysql_dbuser = ioctl_user +# 数据库用户访问密码 +# mysql_dbpass = 111111 + +# 是否输出当前内存的状态信息 +# debug_mem = 1 +# 是否在一个线程中连接读 +# loop_read = 1 +} + diff --git a/app/wizard_demo/qrserver/qrserver.sln b/app/wizard_demo/qrserver/qrserver.sln new file mode 100644 index 000000000..6f1444101 --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qrserver", "qrserver.vcproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + DebugDll = DebugDll + Release = Release + ReleaseDll = ReleaseDll + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll.Build.0 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/qrserver/qrserver.vcproj b/app/wizard_demo/qrserver/qrserver.vcproj new file mode 100644 index 000000000..5eab8f61d --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver.vcproj @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/wizard_demo/qrserver/qrserver_vc2008.sln b/app/wizard_demo/qrserver/qrserver_vc2008.sln new file mode 100644 index 000000000..1c1396f58 --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2008.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qrserver", "qrserver_vc2008.vcproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugDll|Win32 = DebugDll|Win32 + Release|Win32 = Release|Win32 + ReleaseDll|Win32 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/qrserver/qrserver_vc2008.vcproj b/app/wizard_demo/qrserver/qrserver_vc2008.vcproj new file mode 100644 index 000000000..cb1fb5cab --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2008.vcproj @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/wizard_demo/qrserver/qrserver_vc2010.sln b/app/wizard_demo/qrserver/qrserver_vc2010.sln new file mode 100644 index 000000000..e5a3fca7a --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2010.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qrserver", "qrserver_vc2010.vcxproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugDll|Win32 = DebugDll|Win32 + Release|Win32 = Release|Win32 + ReleaseDll|Win32 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/qrserver/qrserver_vc2010.vcxproj b/app/wizard_demo/qrserver/qrserver_vc2010.vcxproj new file mode 100644 index 000000000..1ead7babc --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2010.vcxproj @@ -0,0 +1,202 @@ +锘 + + + + DebugDll + Win32 + + + Debug + Win32 + + + ReleaseDll + Win32 + + + Release + Win32 + + + + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C} + Win32Proj + qrserver + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + $(Configuration)\ + $(Configuration)\ + false + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + Level3 + EditAndContinue + + + lib_acl_cpp_vc2010d.lib;lib_acl_vc2010d.lib;lib_protocol_vc2010d.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)qrserver.pdb + Console + MachineX86 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2010.lib;lib_acl_vc2010.lib;lib_protocol_vc2010.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol.dll $(OutDir) /Y + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)qrserver.pdb + Console + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl_d.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol_d.dll $(OutDir) /Y + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + diff --git a/app/wizard_demo/qrserver/qrserver_vc2010.vcxproj.filters b/app/wizard_demo/qrserver/qrserver_vc2010.vcxproj.filters new file mode 100644 index 000000000..043c20e3b --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2010.vcxproj.filters @@ -0,0 +1,45 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + + + + \ No newline at end of file diff --git a/app/wizard_demo/qrserver/qrserver_vc2012.sln b/app/wizard_demo/qrserver/qrserver_vc2012.sln new file mode 100644 index 000000000..817e8f04e --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2012.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qrserver", "qrserver_vc2012.vcxproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DebugDll|Win32 = DebugDll|Win32 + DebugDll|x64 = DebugDll|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseDll|Win32 = ReleaseDll|Win32 + ReleaseDll|x64 = ReleaseDll|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|x64.ActiveCfg = Debug|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|x64.Build.0 = Debug|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|x64.ActiveCfg = DebugDll|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|x64.Build.0 = DebugDll|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|x64.ActiveCfg = Release|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|x64.Build.0 = Release|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|x64.ActiveCfg = ReleaseDll|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|x64.Build.0 = ReleaseDll|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/qrserver/qrserver_vc2012.vcxproj b/app/wizard_demo/qrserver/qrserver_vc2012.vcxproj new file mode 100644 index 000000000..41ba0d65f --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2012.vcxproj @@ -0,0 +1,365 @@ +锘 + + + + DebugDll + Win32 + + + DebugDll + x64 + + + Debug + Win32 + + + Debug + x64 + + + ReleaseDll + Win32 + + + ReleaseDll + x64 + + + Release + Win32 + + + Release + x64 + + + + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C} + Win32Proj + qrserver + + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.50727.1 + + + .\ + Debug\ + true + + + true + .\ + Debug\ + + + Release\ + Release\ + false + + + false + .\ + Release\ + + + .\ + ReleaseDll\ + false + + + false + .\ + ReleaseDll\ + + + .\ + DebugDll\ + true + + + true + .\ + DebugDll\ + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + Level3 + EditAndContinue + + + lib_acl_cpp_vc2012d.lib;lib_acl_vc2012d.lib;lib_protocol_vc2012d.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)qrserver.pdb + Console + MachineX86 + false + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2012d.lib;lib_acl_vc2012d.lib;lib_protocol_vc2012d.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + $(OutDir)qrserver.pdb + Console + false + 20240000 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2012.lib;lib_acl_vc2012.lib;lib_protocol_vc2012.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2012.lib;lib_protocol_vc2012.lib;lib_acl_vc2012.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + Console + true + true + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol.dll $(OutDir) /Y + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + Console + true + true + + + copy ..\..\..\dist\lib\win64\lib_acl.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_protocol.dll $(OutDir) /Y + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)qrserver.pdb + Console + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl_d.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol_d.dll $(OutDir) /Y + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies) + $(OutDir)qrserver.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + $(OutDir)qrserver.pdb + Console + + + copy ..\..\..\dist\lib\win64\lib_acl_d.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_protocol_d.dll $(OutDir) /Y + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + + + + + + + + + diff --git a/app/wizard_demo/qrserver/qrserver_vc2012.vcxproj.filters b/app/wizard_demo/qrserver/qrserver_vc2012.vcxproj.filters new file mode 100644 index 000000000..ba027f281 --- /dev/null +++ b/app/wizard_demo/qrserver/qrserver_vc2012.vcxproj.filters @@ -0,0 +1,45 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + + + + diff --git a/app/wizard_demo/qrserver/stdafx.cpp b/app/wizard_demo/qrserver/stdafx.cpp new file mode 100644 index 000000000..f01a2ff42 --- /dev/null +++ b/app/wizard_demo/qrserver/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 只包括标准包含文件的源文件 +// master_threads.pch 将成为预编译头 +// stdafx.obj 将包含预编译类型信息 + +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +//引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/app/wizard_demo/qrserver/stdafx.h b/app/wizard_demo/qrserver/stdafx.h new file mode 100644 index 000000000..88376f8ad --- /dev/null +++ b/app/wizard_demo/qrserver/stdafx.h @@ -0,0 +1,19 @@ +// stdafx.h : 标准系统包含文件的包含文件, +// 或是常用但不常更改的项目特定的包含文件 +// + +#pragma once + + +//#include +//#include + +// TODO: 在此处引用程序要求的附加头文件 + +#include "acl_cpp/lib_acl.hpp" +#include "lib_acl.h" + +#ifdef WIN32 +#define snprintf _snprintf +#endif + diff --git a/app/wizard_demo/qrserver/valgrind.sh b/app/wizard_demo/qrserver/valgrind.sh new file mode 100644 index 000000000..6a69d56b0 --- /dev/null +++ b/app/wizard_demo/qrserver/valgrind.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind --tool=memcheck --leak-check=yes -v ./qrserver alone qrserver.cf diff --git a/lib_fiber/c/src/master/fiber_server.c b/lib_fiber/c/src/master/fiber_server.c index 8231acdc5..85b4cd60e 100644 --- a/lib_fiber/c/src/master/fiber_server.c +++ b/lib_fiber/c/src/master/fiber_server.c @@ -22,7 +22,8 @@ static int acl_var_fiber_rw_timeout; static int acl_var_fiber_max_debug; static int acl_var_fiber_enable_core; static int acl_var_fiber_use_limit; -static int acl_var_acl_fiber_idle_limit; +static int acl_var_fiber_idle_limit; +static int acl_var_fiber_wait_limit; static ACL_CONFIG_INT_TABLE __conf_int_tab[] = { { "fiber_stack_size", STACK_SIZE, &acl_var_fiber_stack_size, 0, 0 }, { "fiber_buf_size", 8192, &acl_var_fiber_buf_size, 0, 0 }, @@ -30,7 +31,8 @@ static ACL_CONFIG_INT_TABLE __conf_int_tab[] = { { "fiber_max_debug", 1000, &acl_var_fiber_max_debug, 0, 0 }, { "fiber_enable_core", 1, &acl_var_fiber_enable_core, 0, 0 }, { "fiber_use_limit", 0, &acl_var_fiber_use_limit, 0, 0 }, - { "acl_fiber_idle_limit", 0, &acl_var_acl_fiber_idle_limit, 0 , 0 }, + { "fiber_idle_limit", 0, &acl_var_fiber_idle_limit, 0 , 0 }, + { "fiber_wait_limit", 0, &acl_var_fiber_wait_limit, 0, 0 }, { 0, 0, 0, 0, 0 }, }; @@ -54,6 +56,13 @@ static ACL_CONFIG_STR_TABLE __conf_str_tab[] = { { 0, 0, 0 }, }; +static int acl_var_fiber_quick_abort; +static ACL_CONFIG_BOOL_TABLE __conf_bool_tab[] = { + { "fiber_quick_abort", 1, &acl_var_fiber_quick_abort }, + + { 0, 0, 0 }, +}; + static int __argc; static char **__argv; static int __daemon_mode = 0; @@ -100,12 +109,31 @@ static void fiber_monitor_master(ACL_FIBER *fiber, void *ctx) { ACL_VSTREAM *stat_stream = (ACL_VSTREAM *) ctx; char buf[8192]; - int ret; + int ret, n = 0; stat_stream->rw_timeout = 0; ret = acl_vstream_read(stat_stream, buf, sizeof(buf)); - acl_msg_info("%s(%d), %s: disconnect(%d) from acl_master", - __FILE__, __LINE__, __FUNCTION__, ret); + acl_msg_info("%s(%d), %s: disconnect(%d) from acl_master, clients %d", + __FILE__, __LINE__, __FUNCTION__, ret, __nclients); + + while (!acl_var_fiber_quick_abort) { + if (__nclients <= 0) { + acl_msg_warn("%s(%d), %s: all clients closed!", + __FILE__, __LINE__, __FUNCTION__); + break; + } + + acl_fiber_sleep(1); + n++; + if (acl_var_fiber_wait_limit > 0 && n >= acl_var_fiber_wait_limit) + { + acl_msg_warn("%s(%d), %s: too long, clients: %d", + __FILE__, __LINE__, __FUNCTION__, __nclients); + break; + } + acl_msg_info("%s(%d), %s: waiting %d, clients %d", + __FILE__, __LINE__, __FUNCTION__, n, __nclients); + } server_exit(fiber, 0); } @@ -148,10 +176,10 @@ static void fiber_monitor_idle(ACL_FIBER *fiber, void *ctx acl_unused) continue; } - if (time(NULL) - last >= acl_var_acl_fiber_idle_limit) { + if (time(NULL) - last >= acl_var_fiber_idle_limit) { acl_msg_info("%s(%d), %s: idle_limit reached %d", __FILE__, __LINE__, __FUNCTION__, - acl_var_acl_fiber_idle_limit); + acl_var_fiber_idle_limit); server_stop(fiber); break; } @@ -491,6 +519,7 @@ static void server_init(const char *procname) acl_get_app_conf_int_table(__conf_int_tab); acl_get_app_conf_str_table(__conf_str_tab); + acl_get_app_conf_bool_table(__conf_bool_tab); #ifdef ACL_UNIX acl_master_vars_init(acl_var_fiber_buf_size, acl_var_fiber_rw_timeout); @@ -695,7 +724,7 @@ static void fiber_main(ACL_FIBER *fiber acl_unused, void *ctx acl_unused) if (acl_var_fiber_use_limit > 0) acl_fiber_create(fiber_monitor_used, NULL, STACK_SIZE); - if (acl_var_acl_fiber_idle_limit > 0) + if (acl_var_fiber_idle_limit > 0) acl_fiber_create(fiber_monitor_idle, NULL, STACK_SIZE); if (pre_jail) diff --git a/lib_fiber/changes.txt b/lib_fiber/changes.txt index fe960040d..0694084ca 100644 --- a/lib_fiber/changes.txt +++ b/lib_fiber/changes.txt @@ -1,3 +1,7 @@ + +50) 2017.5.16 +50.1) feature: fiber_server.c 协程服务器模板增加了平滑退出机制 + 49) 2017.5.1 49.1) samples/pgsql: 添加测试 postgresql 的客户端例子