void http_hdr_req_free(HTTP_HDR_REQ *hh) { ACL_ARRAY *pool; if (hh == NULL) return; if (var_http_tls_cache <= 0 || cache_pool == NULL) { __hdr_free_member(hh); http_hdr_free((HTTP_HDR *) hh); return; } #ifdef USE_TLS_EX pool = (ACL_ARRAY*) acl_pthread_tls_get(&cache_key); if (pool != NULL) { pool->push_back(pool, hh); return; } #else pool = (ACL_ARRAY*) acl_pthread_getspecific(cache_key); if (pool != NULL && acl_array_size(pool) < var_http_tls_cache) { pool->push_back(pool, hh); return; } #endif __hdr_free_member(hh); http_hdr_free((HTTP_HDR *) hh); }
int acl_mem_slice_gc(void) { ACL_MEM_SLICE *mem_slice = acl_pthread_getspecific(__mem_slice_key); if (!mem_slice) return -1; return mem_slice_gc(mem_slice); }
int acl_read_wait(ACL_SOCKET fd, int timeout) { const char *myname = "acl_read_wait"; int op = EPOLL_CTL_ADD, delay = timeout * 1000, *epoll_fd; struct epoll_event ee, events[1]; acl_assert(acl_pthread_once(&epoll_once, thread_epoll_init) == 0); epoll_fd = (int*) acl_pthread_getspecific(epoll_key); if (epoll_fd == NULL) { epoll_fd = (int*) acl_mymalloc(sizeof(int)); acl_assert(acl_pthread_setspecific(epoll_key, epoll_fd) == 0); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { main_epoll_read_fd = epoll_fd; atexit(main_epoll_end); } *epoll_fd = epoll_create(1); } ee.events = EPOLLIN | EPOLLHUP | EPOLLERR; ee.data.u64 = 0; ee.data.fd = fd; if (epoll_ctl(*epoll_fd, op, fd, &ee) == -1) { acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d", myname, __LINE__, acl_last_serror(), fd); return -1; } if (epoll_wait(*epoll_fd, events, 1, delay) == -1) { acl_msg_error("%s(%d): epoll_wait error: %s, fd: %d", myname, __LINE__, acl_last_serror(), fd); return -1; } if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0) return -1; if ((events[0].events & EPOLLIN) == 0) { acl_set_error(ACL_ETIMEDOUT); return -1; } ee.events = 0; ee.data.u64 = 0; ee.data.fd = fd; if (epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, fd, &ee) == -1) { acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d", myname, __LINE__, acl_last_serror(), fd); return -1; } return 0; }
void acl_mem_slice_destroy(void) { ACL_MEM_SLICE *mem_slice = acl_pthread_getspecific(__mem_slice_key); if (mem_slice == NULL) return; /* 释放该线程所拥有的内存切片池对象 */ mem_slice_free(mem_slice); acl_pthread_setspecific(__mem_slice_key, NULL); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) __main_mem_slice = NULL; }
virtual void* run() { // 回写需要先设置远程连接地址 acl::socket_stream* conn = (acl::socket_stream*) acl_pthread_getspecific(stream_key); acl_assert(conn); conn->set_peer(peer_addr_); conn->write(buf_, len_); // 因为该对象是动态分配的,所以需要释放掉 delete this; return NULL; }
static void *tls_calloc(size_t len) { void *ptr; (void) acl_pthread_once(&once_control, once_init); ptr = (void*) acl_pthread_getspecific(once_key); if (ptr == NULL) { ptr = acl_mycalloc(1, len); acl_pthread_setspecific(once_key, ptr); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) __tls = ptr; } return ptr; }
HTTP_HDR_REQ *http_hdr_req_new(void) { HTTP_HDR_REQ *hh; ACL_ARRAY *pool; if (var_http_tls_cache <= 0) { hh = (HTTP_HDR_REQ *) http_hdr_new(sizeof(HTTP_HDR_REQ)); __hdr_init(hh); return hh; } #ifdef USE_TLS_EX pool = (ACL_ARRAY*) acl_pthread_tls_get(&cache_key); if (pool == NULL) { pool = acl_array_create(100); acl_pthread_tls_set(cache_key, pool, (void (*)(void*)) thread_cache_free); } pool = (ACL_ARRAY*) acl_pthread_tls_get(&cache_key); hh = (HTTP_HDR_REQ*) pool->pop_back(pool); if (hh) { __hdr_reset(hh, 1); http_hdr_reset((HTTP_HDR *) hh); return hh; } #else acl_pthread_once(&once_control, cache_init); pool = (ACL_ARRAY*) acl_pthread_getspecific(cache_key); if (pool == NULL) { pool = acl_array_create(100); acl_pthread_setspecific(cache_key, pool); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { cache_pool = pool; atexit(main_cache_free); } } hh = (HTTP_HDR_REQ*) pool->pop_back(pool); if (hh) { __hdr_reset(hh, 1); http_hdr_reset((HTTP_HDR *) hh); return hh; } #endif hh = (HTTP_HDR_REQ *) http_hdr_new(sizeof(HTTP_HDR_REQ)); __hdr_init(hh); return hh; }
const char *acl_last_serror(void) { char *buf; int error = acl_last_error(); static int __buf_size = 4096; (void) acl_pthread_once(&once_control, thread_buf_init); buf = acl_pthread_getspecific(__errbuf_key); if (buf == NULL) { buf = acl_mymalloc(__buf_size); acl_pthread_setspecific(__errbuf_key, buf); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { __main_buf = buf; atexit(main_free_buf); } } return acl_strerror(error, buf, __buf_size); }
virtual bool thread_on_init() { acl_pthread_once(&stream_once, thread_init_once); acl::socket_stream* conn = (acl::socket_stream*) acl_pthread_getspecific(stream_key); if (conn != NULL) return true; conn = new acl::socket_stream; if (conn->bind_udp(var_cfg_local_addr) == false) { logger_error("bind %s error %s", var_cfg_local_addr, acl::last_serror()); delete conn; return false; } acl_pthread_setspecific(stream_key, conn); return true; }
static ACL_MEM_SLICE *mem_slice_create(void) { const char *myname = "mem_slice_create"; ACL_MEM_SLICE *mem_slice; acl_pthread_once(&once_control, slice_key_init); if (__mem_slice_key == (acl_pthread_key_t) -1) acl_msg_fatal("%s(%d): __mem_slice_key(%d) invalid," " call acl_mem_slice_init or acl_mem_slice_set first", myname, __LINE__, (int) __mem_slice_key); mem_slice = acl_pthread_getspecific(__mem_slice_key); if (mem_slice != NULL) return mem_slice; mem_slice = (ACL_MEM_SLICE*) acl_default_calloc(__FILE__, __LINE__, 1, sizeof(ACL_MEM_SLICE)); if (mem_slice == NULL) acl_msg_fatal("%s(%d): can't alloc for mem_slice(%s)", myname, __LINE__, acl_last_serror()); mem_slice->slice_pool = acl_slice_pool_create(__mem_base, __mem_nslice, __mem_slice_flag); mem_slice->tid = (unsigned long) acl_pthread_self(); mem_slice->list = private_array_create(__mem_list_init_size); MUTEX_INIT(mem_slice); mem_slice->tls_key = __mem_slice_key; mem_slice->nalloc_gc = __mem_nalloc_gc; mem_slice->slice_flag = __mem_slice_flag; acl_pthread_setspecific(__mem_slice_key, mem_slice); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) __main_mem_slice = mem_slice; acl_msg_info("%s(%d): thread(%ld) set myown mem_slice(%p)", myname, __LINE__, (long) mem_slice->tid, mem_slice); return mem_slice; }
int acl_read_wait(ACL_SOCKET fd, int timeout) { const char *myname = "acl_read_wait"; int delay = timeout * 1000, ret; EPOLL_CTX *epoll_ctx; struct epoll_event ee, events[1]; time_t begin; acl_assert(acl_pthread_once(&epoll_once, thread_epoll_once) == 0); epoll_ctx = (EPOLL_CTX*) acl_pthread_getspecific(epoll_key); if (epoll_ctx == NULL) epoll_ctx = thread_epoll_init(); ee.events = EPOLLIN | EPOLLHUP | EPOLLERR; ee.data.u64 = 0; ee.data.fd = fd; if (epoll_ctl(epoll_ctx->epfd, EPOLL_CTL_ADD, fd, &ee) == -1 && acl_last_error() != EEXIST) { acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d, epfd: %d," " tid: %lu, %lu", myname, __LINE__, acl_last_serror(), fd, epoll_ctx->epfd, epoll_ctx->tid, acl_pthread_self()); return -1; } for (;;) { time(&begin); ret = epoll_wait(epoll_ctx->epfd, events, 1, delay); if (ret == -1) { if (acl_last_error() == ACL_EINTR) { acl_msg_warn(">>>>catch EINTR, try again<<<"); continue; } acl_msg_error("%s(%d): epoll_wait error: %s, fd: %d," " epfd: %d, tid: %lu, %lu", myname, __LINE__, acl_last_serror(), fd, epoll_ctx->epfd, epoll_ctx->tid, acl_pthread_self()); ret = -1; break; } else if (ret == 0) { acl_msg_warn("%s(%d), %s: poll timeout: %s, fd: %d, " "delay: %d, spent: %ld", __FILE__, __LINE__, myname, acl_last_serror(), fd, delay, (long) (time(NULL) - begin)); acl_set_error(ACL_ETIMEDOUT); ret = -1; break; } else if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0) { acl_msg_warn("%s(%d), %s: poll error: %s, fd: %d, " "delay: %d, spent: %ld", __FILE__, __LINE__, myname, acl_last_serror(), fd, delay, (long) (time(NULL) - begin)); ret = -1; } else if ((events[0].events & EPOLLIN) == 0) { acl_msg_warn("%s(%d), %s: poll error: %s, fd: %d, " "delay: %d, spent: %ld", __FILE__, __LINE__, myname, acl_last_serror(), fd, delay, (long) (time(NULL) - begin)); acl_set_error(ACL_ETIMEDOUT); ret = -1; } else ret = 0; break; } ee.events = 0; ee.data.u64 = 0; ee.data.fd = fd; if (epoll_ctl(epoll_ctx->epfd, EPOLL_CTL_DEL, fd, &ee) == -1) { acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d, epfd: %d," " tid: %lu, %lu", myname, __LINE__, acl_last_serror(), fd, epoll_ctx->epfd, epoll_ctx->tid, acl_pthread_self()); return -1; } return ret; }
bool db_pgsql::dbopen(const char* /* charset = NULL */) { if (conn_) return true; char tmpbuf[256]; char *db_host, *db_unix; int db_port; char* ptr = strchr(dbaddr_, '/'); if (ptr == NULL) { ACL_SAFE_STRNCPY(tmpbuf, dbaddr_, sizeof(tmpbuf)); ptr = strchr(tmpbuf, ':'); if (ptr == NULL || *(ptr + 1) == 0) { logger_error("invalid db_addr=%s", dbaddr_); return false; } else *ptr++ = 0; db_host = tmpbuf; db_port = atoi(ptr); if (db_port <= 0) { logger_error("invalid port=%d", db_port); return false; } db_unix = NULL; } else { db_unix = dbaddr_; db_host = db_unix; db_port = 0; } int* dummy; if (acl_pthread_once(&__thread_once_control, thread_once) != 0) logger_error("call thread_once error: %s", acl_last_serror()); else if (!(dummy = (int*) acl_pthread_getspecific(__thread_key))) { dummy = (int*) acl_mymalloc(sizeof(int)); *dummy = 1; acl_assert(!acl_pthread_setspecific(__thread_key, dummy)); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { __main_dummy = dummy; atexit(main_free_dummy); } } string info; info.format("host=%s dbname=%s", db_host, dbname_); if (db_unix == NULL) info.format_append(" port=%d", db_port); if (dbuser_) info.format_append(" user=%s", dbuser_); if (dbpass_) info.format_append(" password=%s", dbpass_); conn_ = __dbconnect(info.c_str()); if (conn_ == NULL || __dbstatus(conn_) != CONNECTION_OK) { logger_error("connect pgsql error(%s), db_host=%s, db_port=%d," " db_unix=%s, db_name=%s, db_user=%s, db_pass=%s", conn_ ? __dberror_message(conn_) : "connect error", db_host ? db_host : "null", db_port, db_unix ? db_unix : "null", dbname_ ? dbname_ : "null", dbuser_ ? dbuser_ : "null", dbpass_ ? dbpass_ : "null"); if (conn_) { __dbfinish(conn_); conn_ = NULL; } return false; } return true; }
static void tls_mem_free(const char *filename, int line, void *ptr) { MBLOCK *real_ptr; size_t len; CHECK_IN_PTR2(ptr, real_ptr, len, filename, line); #if 1 if (real_ptr->mem_slice->tid != (unsigned long) acl_pthread_self()) { #else if (real_ptr->mem_slice->tid != mem_slice->tid) { #endif MUTEX_LOCK(real_ptr->mem_slice); PRIVATE_ARRAY_PUSH(real_ptr->mem_slice->list, real_ptr); MUTEX_UNLOCK(real_ptr->mem_slice); } else acl_slice_pool_free(filename, line, real_ptr); } static void *tls_mem_alloc(const char *filename, int line, size_t len) { const char *myname = "tls_mem_alloc"; ACL_MEM_SLICE *mem_slice = acl_pthread_getspecific(__mem_slice_key); char *ptr; MBLOCK *real_ptr; if (mem_slice == NULL) { /* 每个子线程获得自己的线程局部存储内存池 */ mem_slice = mem_slice_create(); mem_slice->slice_list = __mem_slice_list; /* 将子线程的线程局部存储内存池置入全局内存池句柄集合中 */ if (__mem_slice_list_lock) thread_mutex_lock(__mem_slice_list_lock); private_array_push(__mem_slice_list, mem_slice); if (__mem_slice_list_lock) thread_mutex_unlock(__mem_slice_list_lock); } real_ptr = (MBLOCK *) acl_slice_pool_alloc(filename, line, mem_slice->slice_pool, SPACE_FOR(len)); if (real_ptr == 0) { acl_msg_error("%s(%d): malloc: insufficient memory", myname, __LINE__); return 0; } mem_slice->nalloc++; if (mem_slice->nalloc == mem_slice->nalloc_gc) { mem_slice->nalloc = 0; mem_slice_gc(mem_slice); } CHECK_OUT_PTR(ptr, real_ptr, mem_slice, len); return ptr; } static void *tls_mem_calloc(const char *filename, int line, size_t nmemb, size_t size) { void *ptr = tls_mem_alloc(filename, line, nmemb * size); memset(ptr, 0, nmemb * size); return ptr; }
bool db_mysql::dbopen(const char* charset /* = NULL */) { if (conn_) return true; char tmpbuf[256]; char *db_host, *db_unix; int db_port; char* ptr = strchr(dbaddr_, '/'); if (ptr == NULL) { ACL_SAFE_STRNCPY(tmpbuf, dbaddr_, sizeof(tmpbuf)); ptr = strchr(tmpbuf, ':'); if (ptr == NULL || *(ptr + 1) == 0) { logger_error("invalid db_addr=%s", dbaddr_); return false; } else *ptr++ = 0; db_host = tmpbuf; db_port = atoi(ptr); if (db_port <= 0) { logger_error("invalid port=%d", db_port); return false; } db_unix = NULL; } else { db_unix = dbaddr_; db_host = NULL; db_port = 0; } int* dummy; if (acl_pthread_once(&__thread_once_control, thread_once) != 0) logger_error("call thread_once error: %s", acl_last_serror()); else if (!(dummy = (int*) acl_pthread_getspecific(__thread_key))) { dummy = (int*) acl_mymalloc(sizeof(int)); *dummy = 1; acl_assert(!acl_pthread_setspecific(__thread_key, dummy)); // 调用下面函数可能会造成内存越界 //if (__mysql_thread_init != NULL) // __mysql_thread_init(); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { __main_dummy = dummy; atexit(main_free_dummy); } } conn_ = __mysql_init(NULL); if (conn_ == NULL) { logger_error("mysql init error"); return false; } if (conn_timeout_ > 0) #if MYSQL_VERSION_ID >= 50500 __mysql_options(conn_, MYSQL_OPT_CONNECT_TIMEOUT, (const void*) &conn_timeout_); #else __mysql_options(conn_, MYSQL_OPT_CONNECT_TIMEOUT, (const char*) &conn_timeout_); #endif if (rw_timeout_ > 0) { #if MYSQL_VERSION_ID >= 50500 __mysql_options(conn_, MYSQL_OPT_READ_TIMEOUT, (const void*) &rw_timeout_); __mysql_options(conn_, MYSQL_OPT_WRITE_TIMEOUT, (const void*) &rw_timeout_); #else __mysql_options(conn_, MYSQL_OPT_READ_TIMEOUT, (const char*) &rw_timeout_); __mysql_options(conn_, MYSQL_OPT_WRITE_TIMEOUT, (const char*) &rw_timeout_); #endif } my_bool reconnect = 1; #if MYSQL_VERSION_ID >= 50500 __mysql_options(conn_, MYSQL_OPT_RECONNECT, (const void*) &reconnect); #else __mysql_options(conn_, MYSQL_OPT_RECONNECT, (const char*) &reconnect); #endif if (__mysql_open(conn_, db_host, dbuser_ ? dbuser_ : "", dbpass_ ? dbpass_ : "", dbname_, db_port, db_unix, dbflags_) == NULL) { logger_error("connect mysql error(%s), db_host=%s, db_port=%d," " db_unix=%s, db_name=%s, db_user=%s, db_pass=%s," " dbflags=%ld", __mysql_error(conn_), db_host ? db_host : "null", db_port, db_unix ? db_unix : "null", dbname_ ? dbname_ : "null", dbuser_ ? dbuser_ : "null", dbpass_ ? dbpass_ : "null", dbflags_); __mysql_close(conn_); conn_ = NULL; return false; } #if 0 logger("connect mysql ok(%s), db_host=%s, db_port=%d, " "db_unix=%s, db_name=%s, db_user=%s, db_pass=%s, dbflags=%ld", __mysql_error(conn_), db_host ? db_host : "null", db_port, db_unix ? db_unix : "null", dbname_ ? dbname_ : "null", dbuser_ ? dbuser_ : "null", dbpass_ ? dbpass_ : "null", dbflags_); #endif if (charset != NULL && *charset != 0) charset_ = charset; if (!charset_.empty()) { if (!__mysql_set_character_set(conn_, charset_.c_str())) logger("set mysql charset to %s, %s", charset_.c_str(), __mysql_character_set_name(conn_)); else logger_error("set mysql to %s error %s", charset_.c_str(), __mysql_error(conn_)); } #if MYSQL_VERSION_ID >= 50000 if (__mysql_autocommit(conn_, auto_commit_ ? 1 : 0) != 0) { logger_error("mysql_autocommit error"); __mysql_close(conn_); conn_ = NULL; return (false); } #else auto_commit_ = false; #endif return true; }