thread_mutex::thread_mutex(bool recursive /* = true */) { mutex_ = (acl_pthread_mutex_t*) acl_mycalloc(1, sizeof(acl_pthread_mutex_t)); #ifdef ACL_UNIX int ret = pthread_mutexattr_init(&mutex_attr_); if (ret) { SET_ERRNO(ret); logger_fatal("pthread_mutexattr_init error=%s", last_serror()); } if (recursive && (ret = pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE))) { SET_ERRNO(ret); logger_fatal("pthread_mutexattr_settype error=%s", last_serror()); } ret = acl_pthread_mutex_init(mutex_, &mutex_attr_); if (ret) { SET_ERRNO(ret); logger_fatal("pthread_mutex_init error=%s", last_serror()); } #else (void) recursive; int ret = acl_pthread_mutex_init(mutex_, NULL); if (ret) { SET_ERRNO(ret); logger_fatal("pthread_mutex_init error=%s", last_serror()); } #endif }
static gpointer _mmap(gsize len) { gpointer area = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); if (area == MAP_FAILED) { logger_fatal("secret storage: cannot mmap buffer", "len: %"G_GSIZE_FORMAT", errno: %d\n", len, errno); return MAP_FAILED; } if (!_exclude_memory_from_core_dump(area, len)) goto err_munmap; if (mlock(area, len) < 0) { gchar *hint = (errno == ENOMEM) ? ". Maybe RLIMIT_MEMLOCK is too small?" : ""; logger_fatal("secret storage: cannot lock buffer", "len: %"G_GSIZE_FORMAT", errno: %d%s\n", len, errno, hint); goto err_munmap; } return area; err_munmap: munmap(area, len); return MAP_FAILED; }
int dbuf_guard::push_back(dbuf_obj* obj) { if (obj->nrefer_ < 1) { if (obj->guard_ == NULL) obj->guard_ = this; else if (obj->guard_ != this) { logger_fatal("obj->guard_(%p) != me(%p), nrefer: %d", obj->guard_, this, obj->nrefer_); } if (size_ >= capacity_) extend_objs(); objs_[size_] = obj; obj->nrefer_++; obj->pos_ = (int) size_; size_++; } else if (obj->guard_ != this) { logger_fatal("obj->guard_(%p) != me(%p), nrefer: %d", obj->guard_, this, obj->nrefer_); } return obj->pos_; }
// 动态加载 zlib.dll 库 static void __zlib_dll_load(void) { if (__zlib_dll != NULL) logger_fatal("__zlib_dll not null"); #ifdef WIN32 __zlib_dll = acl_dlopen("zlib.dll"); #else __zlib_dll = acl_dlopen("libz.so"); #endif if (__zlib_dll == NULL) logger_fatal("load zlib.dll error: %s", acl_last_serror()); __deflateInit = (deflateInit_fn) acl_dlsym(__zlib_dll, "deflateInit_"); if (__deflateInit == NULL) logger_fatal("load deflateInit from zlib.dll error: %s", acl_last_serror()); __deflate = (deflate_fn) acl_dlsym(__zlib_dll, "deflate"); if (__deflate == NULL) logger_fatal("load deflate from zlib.dll error: %s", acl_last_serror()); __deflateReset = (deflateReset_fn) acl_dlsym(__zlib_dll, "deflateReset"); if (__deflateReset == NULL) logger_fatal("load deflateReset from zlib.dll error: %s", acl_last_serror()); __deflateEnd = (deflateEnd_fn) acl_dlsym(__zlib_dll, "deflateEnd"); if (__deflateEnd == NULL) logger_fatal("load deflateEnd from zlib.dll error: %s", acl_last_serror()); __inflateInit = (inflateInit_fn) acl_dlsym(__zlib_dll, "inflateInit2_"); if (__inflateInit == NULL) logger_fatal("load inflateInit from zlib.dll error: %s", acl_last_serror()); __inflate = (inflate_fn) acl_dlsym(__zlib_dll, "inflate"); if (__inflate == NULL) logger_fatal("load inflate from zlib.dll error: %s", acl_last_serror()); __inflateReset = (inflateReset_fn) acl_dlsym(__zlib_dll, "inflateReset"); if (__inflateReset == NULL) logger_fatal("load inflateReset from zlib.dll error: %s", acl_last_serror()); __inflateEnd = (inflateEnd_fn) acl_dlsym(__zlib_dll, "inflateEnd"); if (__inflateEnd == NULL) logger_fatal("load inflateEnd from zlib.dll error: %s", acl_last_serror()); logger("zlib.dll loaded"); atexit(__zlib_dll_unload); }
mem_cache::mem_cache(const char* key_pre /* = NULL */, const char* addr /* = "127.0.0.1:11211" */, bool retry /* = true */, int conn_timeout /* = 180 */, int rw_timeout /* = 300 */, bool encode_key /* = true */) : m_coder(false, false) , m_conn_timeout(conn_timeout) , m_rw_timeout(rw_timeout) , m_encode_key(encode_key) , m_opened(false) , m_retry(retry) , m_conn(NULL) { if (key_pre && *key_pre) { bool beCoding = false; m_key_pre = NEW acl::string(strlen(key_pre)); while (*key_pre) { if (SPECIAL_CHAR(*key_pre) || !ACL_ISPRINT(*key_pre)) { m_coder.encode_update(key_pre, 1, m_key_pre); beCoding = true; } else if (beCoding) { m_coder.encode_finish(m_key_pre); m_coder.reset(); beCoding = false; *m_key_pre << (char) *key_pre; } else *m_key_pre << (char) *key_pre; key_pre++; } if (beCoding) m_coder.encode_finish(m_key_pre); } else m_key_pre = NULL; acl_assert(addr && *addr); m_addr = acl_mystrdup(addr); char* ptr = strchr(m_addr, ':'); if (ptr == NULL) logger_fatal("addr(%s) invalid", addr); *ptr++ = 0; if (*ptr == 0) logger_fatal("addr(%s) invalid", addr); m_ip = m_addr; m_port = atoi(ptr); if (m_port <= 0) logger_fatal("addr(%s) invalid", addr); }
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!"); if (conf_ == NULL) return servlet->doRun("127.0.0.1:11211", conn); acl::polarssl_io* ssl = setup_ssl(*conn, *conf_); if (ssl == NULL) return false; if (ssl->handshake() == false) { logger_error("ssl handshake failed"); return false; } if (ssl->handshake_ok() == false) { logger("handshake trying ..."); return true; } return servlet->doRun("127.0.0.1:11211", conn); }
void master_service::proc_on_init() { if (var_cfg_request_file && *var_cfg_request_file) { __req_fp = new acl::ofstream; if (__req_fp->open_trunc(var_cfg_request_file) == false) { logger_error("open file %s error %s", var_cfg_request_file, acl::last_serror()); delete __req_fp; __req_fp = NULL; } } if (var_cfg_respond_file && *var_cfg_respond_file) { __res_fp = new acl::ofstream; if (__res_fp->open_trunc(var_cfg_respond_file) == false) { logger_fatal("open file %s error %s", var_cfg_respond_file, acl::last_serror()); delete __res_fp; __res_fp = NULL; } } }
void master_service::proc_on_init() { // 取得需要探测的 URL 列表 acl::string buf(var_cfg_http_url_list); const std::list<acl::string>& tokens = buf.split(",; \t"); std::list<acl::string>::const_iterator cit = tokens.begin(); for (; cit != tokens.end(); ++cit) { url_list_.push_back(*cit); logger("add url: %s", (*cit).c_str()); } // 创建数据库连接池 var_dbpool = new acl::sqlite_pool(var_cfg_dbpath, var_cfg_http_cocurrent * url_list_.size()); // 创建或打开数据库 db_store store; if (store.db_create() == false) logger_fatal("create db failed!"); // 创建线程池并设置参数 var_thrpool = new acl::thread_pool; var_thrpool->set_limit(var_cfg_http_cocurrent); var_thrpool->set_idle(300); // 启动线程池过程 var_thrpool->start(); }
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!"); if (conf_ == NULL) return servlet->doRun("127.0.0.1:11211", conn); acl::stream_hook* hook = conn->get_hook(); if (hook != NULL) return servlet->doRun("127.0.0.1:11211", conn); // 对于使用 SSL 方式的流对象,需要将 SSL IO 流对象注册至网络 // 连接流对象中,即用 ssl io 替换 stream 中默认的底层 IO 过程 logger("begin setup ssl hook..."); acl::polarssl_io* ssl = new acl::polarssl_io(*conf_, true); if (conn->setup_hook(ssl) == ssl) { logger_error("setup_hook error!"); ssl->destroy(); return false; } logger("setup hook ok, tid: %lu", (unsigned long) acl_pthread_self()); return servlet->doRun("127.0.0.1:11211", conn); }
unsigned beanstalk::ignore_all() { if (tubes_watched_.size() <= 1) { // first tube watched must be "default" if (strcmp(tubes_watched_[0], "default") != 0) logger_fatal("first tube(%s) is not default", tubes_watched_[0]); return 1; } unsigned ret = 1; // at least one default tube is watched std::vector<char*>::iterator it = tubes_watched_.begin(); ++it; // skip first default tube for (; it != tubes_watched_.end();) { ret = ignore_one(*it); if (ret == 0) { logger_error("ignore tube %s failed", *it); errbuf_ = "ignore"; acl_myfree(*it); return 0; } acl_myfree(*it); it = tubes_watched_.erase(it); ret++; } return ret; }
void master_threads2::run_daemon(int argc, char** argv) { #ifndef ACL_WINDOWS // 每个进程只能有一个实例在运行 acl_assert(has_called == false); has_called = true; daemon_mode_ = true; // 调用 acl 服务器框架的多线程模板 acl_threads_server_main(argc, argv, service_main, NULL, ACL_MASTER_SERVER_ON_ACCEPT, service_on_accept, ACL_MASTER_SERVER_ON_HANDSHAKE, service_on_handshake, ACL_MASTER_SERVER_ON_TIMEOUT, service_on_timeout, ACL_MASTER_SERVER_ON_CLOSE, service_on_close, ACL_MASTER_SERVER_PRE_INIT, service_pre_jail, ACL_MASTER_SERVER_POST_INIT, service_init, ACL_MASTER_SERVER_EXIT_TIMER, service_exit_timer, ACL_MASTER_SERVER_EXIT, service_exit, ACL_MASTER_SERVER_THREAD_INIT, thread_init, ACL_MASTER_SERVER_THREAD_EXIT, thread_exit, ACL_MASTER_SERVER_BOOL_TABLE, conf_.get_bool_cfg(), ACL_MASTER_SERVER_INT64_TABLE, conf_.get_int64_cfg(), ACL_MASTER_SERVER_INT_TABLE, conf_.get_int_cfg(), ACL_MASTER_SERVER_STR_TABLE, conf_.get_str_cfg(), ACL_MASTER_SERVER_END); #else logger_fatal("no support win32 yet!"); #endif }
void master_threads::run_daemon(int argc, char** argv) { #ifndef WIN32 // 每个进程只能有一个实例在运行 acl_assert(has_called == false); has_called = true; daemon_mode_ = true; // 调用 acl 服务器框架的多线程模板 acl_ioctl_app_main(argc, argv, service_main, NULL, ACL_APP_CTL_ON_ACCEPT, service_on_accept, ACL_APP_CTL_ON_TIMEOUT, service_on_timeout, ACL_APP_CTL_ON_CLOSE, service_on_close, ACL_APP_CTL_PRE_JAIL, service_pre_jail, ACL_APP_CTL_INIT_FN, service_init, ACL_APP_CTL_EXIT_FN, service_exit, ACL_APP_CTL_THREAD_INIT, thread_init, ACL_APP_CTL_THREAD_EXIT, thread_exit, ACL_APP_CTL_CFG_BOOL, conf_.get_bool_cfg(), ACL_APP_CTL_CFG_INT64, conf_.get_int64_cfg(), ACL_APP_CTL_CFG_INT, conf_.get_int_cfg(), ACL_APP_CTL_CFG_STR, conf_.get_str_cfg(), ACL_APP_CTL_END); #else logger_fatal("no support win32 yet!"); #endif }
int master_threads::service_on_accept(ACL_VSTREAM* client) { // client->context 不应被占用 if (client->context != NULL) logger_fatal("client->context not null!"); socket_stream* stream = NEW socket_stream(); if (stream->open(client) == false) { logger_error("open stream error(%s)", acl_last_serror()); delete stream; return -1; } // 设置 client->context 为流对象 client->context = stream; acl_assert(__mt != NULL); if (__mt->thread_on_accept(stream) == false) { client->context = NULL; // 解释与连接流的绑定关系,这样可以防止在删除流对象时 // 真正关闭了连接流,因为该流连接需要在本函数返回后由 // 框架自动关闭 (void) stream->unbind(); // 删除流对象 delete stream; // 让框架关闭连接流 return -1; } return 0; }
bool master_udp::run_alone(const char* addrs, const char* path /* = NULL */, unsigned int count /* = 1 */) { // 每个进程只能有一个实例在运行 acl_assert(has_called == false); has_called = true; daemon_mode_ = false; __count_limit = count; acl_assert(addrs && *addrs); #ifdef ACL_WINDOWS acl_init(); #endif ACL_EVENT* eventp = acl_event_new_select(1, 0); set_event(eventp); // 设置基类的事件句柄 ACL_ARGV* tokens = acl_argv_split(addrs, ";,| \t"); ACL_ITER iter; acl_foreach(iter, tokens) { const char* addr = (const char*) iter.data; ACL_VSTREAM* sstream = acl_vstream_bind(addr, 0); if (sstream == NULL) { logger_error("bind %s error %s", addr, last_serror()); close_sstreams(); acl_event_free(eventp); acl_argv_free(tokens); return false; } acl_event_enable_read(eventp, sstream, 0, read_callback, sstream); socket_stream* ss = NEW socket_stream(); if (ss->open(sstream) == false) logger_fatal("open stream error!"); sstream->context = ss; sstreams_.push_back(ss); } acl_argv_free(tokens); // 初始化配置参数 conf_.load(path); service_pre_jail(NULL, NULL); service_init(NULL, NULL); while (!__stop) acl_event_loop(eventp); service_exit(NULL, NULL); // 必须在调用 acl_event_free 前调用 close_sstreams,因为在关闭 // 网络流对象时依然有对 ACL_EVENT 引擎的使用 close_sstreams(); acl_event_free(eventp); return true; }
void connect_manager::init(const char* default_addr, const char* addr_list, size_t count, int conn_timeout /* = 30 */, int rw_timeout /* = 30 */) { if (addr_list != NULL && *addr_list != 0) set_service_list(addr_list, (int) count, conn_timeout, rw_timeout); // 创建缺省服务连接池对象,该对象一同放入总的连接池集群中 if (default_addr != NULL && *default_addr != 0) { logger("default_pool: %s", default_addr); int max = check_addr(default_addr, default_addr_, count); if (max < 0) logger("no default connection set"); else default_pool_ = &set(default_addr_.c_str(), max, conn_timeout, rw_timeout); } else logger("no default connection set"); // 必须保证至少有一个服务可用 if (pools_.empty()) logger_fatal("no connection available!"); }
bool http_download::save_range(const char* body, size_t len, acl_int64 range_from, acl_int64 range_to) { if (range_from < 0) { logger_error("invalid range_from: %lld", range_from); return false; } else if (range_to >= 0 && range_to < range_from) { logger_error("invalid, 0 <= range_to: %lld < range_from: %lld", range_to, range_from); return false; } http_method_t method = body && len > 0 ? HTTP_METHOD_POST : HTTP_METHOD_GET; // 发送带 range 字段的下载请求 // 设置 HTTP 请求头信息 req_->request_header().set_method(method) .set_range(range_from, range_to); // 发送 HTTP 请求数据 if (req_->request(NULL, 0) == false) { logger_error("send request error, url: %s", url_); return false; } // 获得文件长度 acl_int64 length = req_->get_range_max(); if (length <= 0) { // 可能是服务器不支持 range 功能,所以还得从头下载 return false; } http_client* conn = req_->get_client(); if (conn == NULL) logger_fatal("no connect to server"); // 回调子类虚接口实现 if (on_response(conn) == false) { logger_error("deny url(%s)'s download", url_); return false; } // 回调子类虚接口实现 if (on_length(length) == false) { logger_error("deny url(%s)'s download", url_); return false; } return save(req_); }
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("127.0.0.1:11211", conn); }
void ipc_client::on_message(int nMsg, void* data, int dlen) { (void) nMsg; (void) data; (void) dlen; // 子类必须实现该接口 logger_fatal("ipc_client be called here"); }
int master_threads::service_on_timeout(ACL_VSTREAM* client, void*) { socket_stream* stream = (socket_stream*) client->context; if (stream == NULL) logger_fatal("client->context is null!"); acl_assert(__mt != NULL); return __mt->thread_on_timeout(stream) == true ? 0 : -1; }
void master_threads::service_on_close(ACL_VSTREAM* client, void*) { socket_stream* stream = (socket_stream*) client->context; if (stream == NULL) logger_fatal("client->context is null!"); acl_assert(__mt != NULL); __mt->thread_on_close(stream); }
void db_mysql::sane_mysql_init(const char* dbaddr, const char* dbname, const char* dbuser, const char* dbpass, unsigned long dbflags, bool auto_commit, int conn_timeout, int rw_timeout, const char* charset) { if (dbaddr == NULL || *dbaddr == 0) logger_fatal("dbaddr null"); if (dbname == NULL || *dbname == 0) logger_fatal("dbname null"); // 地址格式:[dbname@]dbaddr const char* ptr = strchr(dbaddr, '@'); if (ptr) ptr++; else ptr = dbaddr; acl_assert(*ptr); dbaddr_ = acl_mystrdup(ptr); dbname_ = acl_mystrdup(dbname); if (dbuser && *dbuser) dbuser_ = acl_mystrdup(dbuser); else dbuser_ = NULL; if (dbpass && *dbpass) dbpass_ = acl_mystrdup(dbpass); else dbpass_ = NULL; if (charset && *charset) charset_ = charset; dbflags_ = dbflags; auto_commit_ = auto_commit; conn_timeout_ = conn_timeout; rw_timeout_ = rw_timeout; #ifdef HAS_MYSQL_DLL acl_pthread_once(&__mysql_once, __mysql_dll_load); #endif conn_ = NULL; }
queue_file* queue_manager::scan_next() { if (m_scanDir == NULL) logger_fatal("call scan_open first!"); queue_file* fp = NULL; string filePath; while (1) { // 扫描下一个磁盘文件 const char* fileName = acl_scan_dir_next_file(m_scanDir); if (fileName == NULL) return NULL; string partName, extName; if (parse_fileName(fileName, &partName, &extName) == false) continue; // 如果该队列文件已经存在于内存队列中则跳过 if (busy(partName.c_str())) continue; const char* path = acl_scan_dir_path(m_scanDir); if (path == NULL) { logger_error("acl_scan_dir_path error for %s", fileName); continue; } filePath.clear(); filePath << path << PATH_SEP << fileName; fp = NEW queue_file; // 从磁盘打开已经存在的队列文件 if (fp->open(filePath.c_str()) == false) { logger_error("open %s error(%s)", filePath.c_str(), acl_last_serror()); delete fp; fp = NULL; continue; } if (cache_add(fp) == false) { logger_error("file(%s) locked", filePath.c_str()); delete fp; fp = NULL; continue; } else break; } return fp; }
void db_pgsql::sane_pgsql_init(const char* dbaddr, const char* dbname, const char* dbuser, const char* dbpass, int conn_timeout, int rw_timeout, const char* charset) { affect_count_ = 0; if (dbaddr == NULL || *dbaddr == 0) logger_fatal("dbaddr null"); if (dbname == NULL || *dbname == 0) logger_fatal("dbname null"); // 地址格式:[dbname@]dbaddr const char* ptr = strchr(dbaddr, '@'); if (ptr) ptr++; else ptr = dbaddr; acl_assert(*ptr); dbaddr_ = acl_mystrdup(ptr); dbname_ = acl_mystrdup(dbname); if (dbuser && *dbuser) dbuser_ = acl_mystrdup(dbuser); else dbuser_ = NULL; if (dbpass && *dbpass) dbpass_ = acl_mystrdup(dbpass); else dbpass_ = NULL; if (charset && *charset) charset_ = charset; conn_timeout_ = conn_timeout; rw_timeout_ = rw_timeout; #ifdef HAS_PGSQL_DLL acl_pthread_once(&__pgsql_once, __pgsql_dll_load); #endif conn_ = NULL; }
void rpc_manager::init(acl::aio_handle* handle, int max_threads /* = 10 */, const char* rpc_addr /* = NULL */) { handle_ = handle; // 创建 rpc 服务对象 service_ = new acl::rpc_service(max_threads); // 打开消息服务 if (service_->open(handle_, rpc_addr) == false) logger_fatal("open service error: %s", acl::last_serror()); }
rpc_manager::rpc_manager(int max_threads /* = 10 */) { // 因为本类实例是单例,会在程序 main 之前被调用, // 所以需要在此类中打开日志 // 创建非阻塞框架句柄,并采用 WIN32 消息模式:acl::ENGINE_WINMSG handle_ = new acl::aio_handle(acl::ENGINE_WINMSG); // 创建 rpc 服务对象 service_ = new acl::rpc_service(max_threads); // 打开消息服务 if (service_->open(handle_) == false) logger_fatal("open service error: %s", acl::last_serror()); }
// 动态加载 iconv.dll 库 static void __iconv_dll_load(void) { if (__iconv_dll != NULL) logger_fatal("__iconv_dll not null"); __iconv_dll = acl_dlopen("iconv.dll"); if (__iconv_dll == NULL) logger_fatal("load iconv.dll error: %s", acl_last_serror()); __iconv_open = (iconv_open_fn) acl_dlsym(__iconv_dll, "libiconv_open"); if (__iconv_open == NULL) logger_fatal("load iconv_open from iconv.dll error: %s", acl_last_serror()); __iconv_close = (iconv_close_fn) acl_dlsym(__iconv_dll, "libiconv_close"); if (__iconv_close == NULL) logger_fatal("load iconv_close from iconv.dll error: %s", acl_last_serror()); __iconv = (iconv_fn) acl_dlsym(__iconv_dll, "libiconv"); if (__iconv == NULL) logger_fatal("load iconv from iconv.dll error: %s", acl_last_serror()); __iconvctl = (iconvctl_fn) acl_dlsym(__iconv_dll, "libiconvctl"); if (__iconvctl == NULL) logger_fatal("load iconvctl from iconv.dll error: %s", acl_last_serror()); logger("iconv.dll loaded"); atexit(__iconv_dll_unload); }
int master_threads2::service_on_handshake(ACL_VSTREAM *client) { acl_assert(__mt != NULL); // client->context 在 service_on_accept 中被设置 socket_stream* stream = (socket_stream*) client->context; if (stream == NULL) logger_fatal("client->context is null!"); if (__mt->thread_on_handshake(stream) == true) return 0; return -1; }
void master_proc::service_main(ACL_VSTREAM *stream, char*, char**) { socket_stream* client = NEW socket_stream(); if (client->open(stream) == false) logger_fatal("open stream error!"); acl_assert(__mp != NULL); #ifndef ACL_WINDOWS if (__mp->daemon_mode_) acl_watchdog_pat(); // 必须通知 acl_master 框架一下 #endif __mp->on_accept(client); client->unbind(); delete client; }
queue_file* queue_manager::create_file(const char* extName) { queue_file* fp = NEW queue_file; if (fp->create(m_home.c_str(), m_queueName.c_str(), extName, sub_width_) == false) { delete fp; return NULL; } if (cache_add(fp) == false) logger_fatal("%s already exist in table", fp->key()); return fp; }
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!"); if (conf_ == NULL) return servlet->doRun("127.0.0.1:11211", conn); acl::polarssl_io* ssl = setup_ssl(*conn, *conf_); if (ssl == NULL) return false; return servlet->doRun("127.0.0.1:11211", conn); }