Skip to content

Commit

Permalink
make fiber module more safety
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengshuxin committed Apr 14, 2017
1 parent 41b89b7 commit 9e7ad2a
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 24 deletions.
39 changes: 21 additions & 18 deletions lib_acl_cpp/include/acl_cpp/connpool/connect_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ACL_CPP_API connect_manager
virtual ~connect_manager(void);

/**
* 初始化所有服务器的连接池,该函数内部调用 set 过程添加每个服务的连接池
* 初始化所有服务器的连接池,该函数调用 set 过程添加每个服务的连接池
* @param default_addr {const char*} 缺省的服务器地址,如果非空,
* 则在查询时优先使用此服务器
* @param addr_list {const char*} 所有服务器列表,可以为空
Expand All @@ -40,7 +40,8 @@ class ACL_CPP_API connect_manager

/**
* 添加服务器的客户端连接池,该函数可以在程序运行时被调用,内部自动加锁
* @param addr {const char*} 服务器地址(ip:port)
* @param addr {const char*} 服务器地址,格式:ip:port
* 注意:调用本函数时每次仅能添加一个服务器地址,可以循环调用本方法
* @param count {size_t} 连接池数量限制, 如果该值设为 0,则不设置
* 连接池的连接上限
* @param conn_timeout {int} 网络连接时间(秒)
Expand All @@ -51,15 +52,16 @@ class ACL_CPP_API connect_manager
int conn_timeout = 30, int rw_timeout = 30);

/**
* 设置连接池失败后重试的时间时间隔(秒),该函数可以在程序运行时被调用,内部自动加锁
* 设置连接池失败后重试的时间时间隔(秒),该函数可以在程序运行时被
* 调用,内部自动加锁
* @param n {int} 当该值 <= 0 时,若连接池出现问题则会立即被重试
*/
void set_retry_inter(int n);

/**
* 设置连接池中空闲连接的空闲生存周期
* @param ttl {time_t} 空闲连接的生存周期,当该值 < 0 则表示空闲连接不过期,
* == 0 时表示立刻过期,> 0 表示空闲该时间段后将被释放
* @param ttl {time_t} 空闲连接的生存周期,当该值 < 0 则表示空闲连接
* 不过期,== 0 时表示立刻过期,> 0 表示空闲该时间段后将被释放
*/
void set_idle_ttl(time_t ttl);

Expand All @@ -81,17 +83,17 @@ class ACL_CPP_API connect_manager
* @param addr {const char*} redis 服务器地址(ip:port)
* @param exclusive {bool} 是否需要互斥访问连接池数组,当需要动态
* 管理连接池集群时,该值应为 true
* @param restore {bool} 当该服务结点被置为不可用时,该参数决定是否自动
* 将之恢复为可用状态
* @param restore {bool} 当该服务结点被置为不可用时,该参数决定是否
* 自动将之恢复为可用状态
* @return {connect_pool*} 返回空表示没有此服务
*/
connect_pool* get(const char* addr, bool exclusive = true,
bool restore = false);

/**
* 从连接池集群中获得一个连接池,该函数采用轮循方式从连接池集合中获取一个
* 后端服务器的连接池,从而保证了完全的均匀性;该函数内部会自动对连接池管理
* 队列加锁
* 从连接池集群中获得一个连接池,该函数采用轮循方式从连接池集合中获取
* 一个后端服务器的连接池,从而保证了完全的均匀性;该函数内部会自动对
* 连接池管理队列加锁
* 此外,该函数为虚接口,允许子类实现自己的轮循方式
* @return {connect_pool*} 返回一个连接池,返回指针永远非空
*/
Expand Down Expand Up @@ -155,18 +157,19 @@ class ACL_CPP_API connect_manager
/**
* 启动后台非阻塞检测线程检测所有连接池连接状态
* @param monitor {connect_monitor*} 连接检测对象
* @return {bool} 是否正常启动了连接检测器,当返回 false 说明当前还有正在
* 运行的连接检测器,当想再次启动检测器时需要先调用 stop_monitor
* @return {bool} 是否正常启动了连接检测器,当返回 false 说明当前还有
* 正在运行的连接检测器,当想再次启动检测器时需要先调用 stop_monitor
*/
bool start_monitor(connect_monitor* monitor);

/**
* 停止后台检测线程
* @param graceful {bool} 是否在关闭检测线程时需要等待所有的检测连接关闭后
* 才返回,当连接池集群对象为进程空间内不会多次分配与释放时,则该值可以设为 false
* 从而使检测线程快速退出,否则应该等待所有检测连接关闭后再使检测线程退出
* @return {connect_monitor*} 返回 start_monitor 设置的检测器,同时内部
* 的 monitor_ 成员自动置 NULL
* @param graceful {bool} 是否在关闭检测线程时需要等待所有的检测连接
* 关闭后才返回,当连接池集群对象为进程空间内不会多次分配与释放时,
* 则该值可以设为 false 从而使检测线程快速退出,否则应该等待所有检测
* 连接关闭后再使检测线程退出
* @return {connect_monitor*} 返回 start_monitor 设置的检测器,同时
* 内部的 monitor_ 成员自动置 NULL
*/
connect_monitor* stop_monitor(bool graceful = true);

Expand All @@ -181,7 +184,7 @@ class ACL_CPP_API connect_manager
/**
* 纯虚函数,子类必须实现此函数用来创建连接池对象
* @param addr {const char*} 服务器监听地址,格式:ip:port
* @param count {size_t} 连接池的大小限制,当该值为 0 时,则连接池没有限制
* @param count {size_t} 连接池的大小限制, 0 时,则连接池没有限制
* @param idx {size_t} 该连接池对象在集合中的下标位置(从 0 开始)
* @return {connect_pool*} 返回创建的连接池对象
*/
Expand Down
8 changes: 8 additions & 0 deletions lib_acl_cpp/include/acl_cpp/db/db_mysql.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ class ACL_CPP_API db_mysql : public db_handle
return conn_;
}

/**
* 当动态加载 libmysqlclient.so / libmysqlclient.dll 时,可以调用本
* 静态函数显式动态加载 mysql 客户端库,如果加载失败,内部会自动产生
* 断言,以免运行时出错,也可不调用本函数,使 db_mysql 类对象内部在
* 使用时隐式加载 mysql 动态库
*/
static void load(void);

/********************************************************************/
/* 以下为基类 db_handle 的虚接口 */
/********************************************************************/
Expand Down
14 changes: 14 additions & 0 deletions lib_acl_cpp/src/db/db_mysql.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,15 @@ void db_mysql::sane_mysql_init(const char* dbaddr, const char* dbname,
conn_ = NULL;
}

void db_mysql::load(void)
{
#ifdef HAS_MYSQL_DLL
acl_pthread_once(&__mysql_once, __mysql_dll_load);
#else
logger_warn("link mysql library in static way!");
#endif
}

db_mysql::db_mysql(const char* dbaddr, const char* dbname,
const char* dbuser, const char* dbpass,
unsigned long dbflags /* = 0 */, bool auto_commit /* = true */,
Expand Down Expand Up @@ -832,6 +841,11 @@ bool db_mysql::rollback()
namespace acl
{

void db_mysql::load(void)
{
logger_fatal("Please #define HAS_MYSQL_DLL first");
}

void db_mysql::sane_mysql_init(const char*, const char*,
const char*, const char*,
unsigned long, bool, int, int, const char*)
Expand Down
2 changes: 2 additions & 0 deletions lib_acl_cpp/src/serialize/gsoner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,8 @@ bool gsoner::check_member()
first == "signed" ||
first == "int" ||
first == "long" ||
first == "size_t" ||
first == "ssize_t" ||
first == "short" ||
first == "int16_t"||
first == "uint16_t" ||
Expand Down
9 changes: 8 additions & 1 deletion lib_fiber/c/src/event_epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ static epoll_ctl_fn __sys_epoll_ctl = NULL;

void hook_epoll(void)
{
static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;
static int __called = 0;

if (__called)
(void) acl_pthread_mutex_lock(&__lock);

if (__called) {
(void) acl_pthread_mutex_unlock(&__lock);
return;
}

__called++;

Expand All @@ -31,6 +36,8 @@ void hook_epoll(void)

__sys_epoll_ctl = (epoll_ctl_fn) dlsym(RTLD_NEXT, "epoll_ctl");
acl_assert(__sys_epoll_ctl);

(void) acl_pthread_mutex_unlock(&__lock);
}

typedef struct EVENT_EPOLL {
Expand Down
9 changes: 8 additions & 1 deletion lib_fiber/c/src/fiber.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,10 +669,15 @@ int acl_fiber_status(const ACL_FIBER *fiber)

static void fiber_init(void)
{
static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;
static int __called = 0;

if (__called != 0)
(void) acl_pthread_mutex_lock(&__lock);

if (__called != 0) {
(void) pthread_mutex_unlock(&__lock);
return;
}

__called++;

Expand All @@ -683,6 +688,8 @@ static void fiber_init(void)
#endif
__sys_fcntl = (fcntl_fn) dlsym(RTLD_NEXT, "fcntl");

(void) acl_pthread_mutex_unlock(&__lock);

hook_io();
hook_net();
hook_epoll();
Expand Down
9 changes: 8 additions & 1 deletion lib_fiber/c/src/hook_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,15 @@ static sendmsg_fn __sys_sendmsg = NULL;

void hook_io(void)
{
static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;
static int __called = 0;

if (__called)
(void) acl_pthread_mutex_lock(&__lock);

if (__called) {
(void) acl_pthread_mutex_unlock(&__lock);
return;
}

__called++;

Expand Down Expand Up @@ -111,6 +116,8 @@ void hook_io(void)

__sys_sendmsg = (sendmsg_fn) dlsym(RTLD_NEXT, "sendmsg");
acl_assert(__sys_sendmsg);

(void) acl_pthread_mutex_unlock(&__lock);
}

unsigned int sleep(unsigned int seconds)
Expand Down
12 changes: 9 additions & 3 deletions lib_fiber/c/src/hook_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,15 @@ static epoll_ctl_fn __sys_epoll_ctl = NULL;

void hook_net(void)
{
static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;
static int __called = 0;

if (__called)
(void) acl_pthread_mutex_lock(&__lock);

if (__called) {
(void) acl_pthread_mutex_unlock(&__lock);
return;
}

__called++;

Expand Down Expand Up @@ -107,6 +112,8 @@ void hook_net(void)

__sys_epoll_ctl = (epoll_ctl_fn) dlsym(RTLD_NEXT, "epoll_ctl");
acl_assert(__sys_epoll_ctl);

(void) acl_pthread_mutex_unlock(&__lock);
}

int socket(int domain, int type, int protocol)
Expand Down Expand Up @@ -992,14 +999,13 @@ void acl_fiber_set_dns(const char* ip, int port)

#define SKIP_WHILE(cond, cp) { while (*cp && (cond)) cp++; }

static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;

static void get_dns(char *ip, size_t size)
{
const char *filepath = "/etc/resolv.conf";
ACL_VSTREAM *fp;
char buf[4096], *ptr;
ACL_ARGV *tokens;
static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;

(void) acl_pthread_mutex_lock(&__lock);

Expand Down

0 comments on commit 9e7ad2a

Please sign in to comment.