bool beanstalk::beanstalk_open() { if (conn_.opened()) return true; if (conn_.open(addr_, timeout_, 0) == false) { logger_error("connect server: %s error: %s", addr_, last_serror()); errbuf_.format("connect"); return false; } if (tube_used_ && beanstalk_use() == false) { logger_error("use %s error: %s", tube_used_, last_serror()); conn_.close(); return false; } if (tubes_watched_.empty()) return true; std::vector<char*>::iterator it = tubes_watched_.begin(); for (; it != tubes_watched_.end(); ++it) { if (beanstalk_watch(*it) == false) { logger_error("watch %s failed", *it); conn_.close(); return false; } } return true; }
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 }
int open_limit(int limit) { int rlim_cur = -1; #ifdef RLIMIT_NOFILE struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { rlim_cur = getdtablesize(); msg_warn("%s(%d): getrlimit error: %s, use: %d", __FUNCTION__, __LINE__, last_serror(), rlim_cur); return rlim_cur; } if (rl.rlim_max <= 0) { rl.rlim_max = 204800; } rlim_cur = (int) rl.rlim_cur; if (limit > 0) { if (limit > (int) rl.rlim_max) { rl.rlim_cur = rl.rlim_max; } else { rl.rlim_cur = limit; } if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { msg_warn("%s(%d): setrlimit error: %s, limit: %d," " curr: %d", __FUNCTION__, __LINE__, last_serror(), limit, rlim_cur); return rlim_cur; } else { return (int) rl.rlim_cur; } } else if (rl.rlim_max > rl.rlim_cur) { rlim_cur = (int) rl.rlim_cur; rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { msg_warn("%s(%d): setrlimit error: %s," " cur: %d, max: %d", __FUNCTION__, __LINE__, last_serror(), (int) rl.rlim_cur, (int) rl.rlim_max); return rlim_cur; } return (int) rl.rlim_cur; } else { return (int) rl.rlim_cur; } #else rlim_cur = getdtablesize(); if (rlim_cur < 0) { msg_error("%s(%d): getdtablesize(%d) < 0, limit: %d", __FUNCTION__, __LINE__, rlim_cur, limit); } return rlim_cur; #endif }
const redis_result* redis_client::run(dbuf_pool* pool, const redis_request& req, size_t nchildren) { // 重置协议处理状态 bool retried = false; redis_result* result; struct iovec* iov = req.get_iovec(); size_t size = req.get_size(); while (true) { if (!conn_.opened() && conn_.open(addr_, conn_timeout_, rw_timeout_) == false) { logger_error("connect server: %s error: %s", addr_, last_serror()); return NULL; } if (size > 0 && conn_.writev(iov, (int) size) == -1) { conn_.close(); if (retry_ && !retried) { retried = true; continue; } logger_error("write to redis(%s) error: %s", addr_, last_serror()); return NULL; } if (nchildren >= 1) result = get_redis_objects(pool, nchildren); else result = get_redis_object(pool); if (result != NULL) return result; conn_.close(); if (!retry_ || retried) break; retried = true; } return NULL; }
bool file_tmpl::copy_and_replace(const char* from, const char* to, bool exec /* = false */) { tpl_t* tpl = open_tpl(from); if (tpl == NULL) return false; tpl_set_field_fmt_global(tpl, "PROGRAM", "%s", project_name_.c_str()); string filepath; filepath << path_to_ << '/' << to; if (tpl_save_as(tpl, filepath.c_str()) != TPL_OK) { printf("save to %s error: %s\r\n", filepath.c_str(), last_serror()); tpl_free(tpl); return false; } printf("create %s ok.\r\n", filepath.c_str()); tpl_free(tpl); if (exec) { #ifndef WIN32 chmod(filepath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP); #endif } return true; }
redis_result* redis_client::get_redis_object(dbuf_pool* pool) { char ch; if (conn_.read(ch) == false) { logger_warn("read char error: %s, server: %s, fd: %u", last_serror(), addr_, (unsigned) conn_.sock_handle()); return NULL; } switch (ch) { case '-': // ERROR return get_redis_error(pool); case '+': // STATUS return get_redis_status(pool); case ':': // INTEGER return get_redis_integer(pool); case '$': // STRING return get_redis_string(pool); case '*': // ARRAY return get_redis_array(pool); default: // INVALID logger_error("invalid first char: %c, %d", ch, ch); return NULL; } }
bool mail_attach::save_to(mime_code* coder, string& out) { if (coder) build_header(coder->get_encoding_type(), out); else build_header(NULL, out); string buf; if (ifstream::load(filepath_.c_str(), &buf) == false) { logger_error("load %s error %s", filepath_.c_str(), last_serror()); return false; } if (coder) { coder->reset(); coder->encode_update(buf.c_str(), (int) buf.size(), &out); coder->encode_finish(&out); } else out.append(buf); return true; }
static bool create_http_servlet(file_tmpl& tmpl) { tpl_t* tpl = tmpl.open_tpl("http_servlet.cpp"); if (tpl == NULL) return false; printf("Do you want add cookie? y[y/n]: "); fflush(stdout); int ch = getchar(); if (ch != 'n') set_cookies(tpl); string filepath; filepath.format("%s/http_servlet.cpp", tmpl.get_project_name()); if (tpl_save_as(tpl, filepath.c_str()) != TPL_OK) { printf("save to %s error: %s\r\n", filepath.c_str(), last_serror()); tpl_free(tpl); return false; } printf("create %s ok.\r\n", filepath.c_str()); tpl_free(tpl); // 设置服务器模板类型 return create_service(tmpl); }
static int checkfd(EVENT *ev, FILE_EVENT *fe) { struct stat s; if (fstat(fe->fd, &s) < 0) { msg_info("%s(%d), %s: fd: %d fstat error %s", __FILE__, __LINE__, __FUNCTION__, fe->fd, last_serror()); return -1; } if (S_ISSOCK(s.st_mode)) { return 0; } if (S_ISFIFO(s.st_mode)) { return 0; } if (S_ISCHR(s.st_mode)) { return 0; } if (isatty(fe->fd)) { return 0; } return ev->checkfd(ev, fe); }
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; }
static void thread_init(void) { if (pthread_key_create(&__fiber_key, thread_free) != 0) { msg_fatal("%s(%d), %s: pthread_key_create error %s", __FILE__, __LINE__, __FUNCTION__, last_serror()); } }
bool server_socket::open(const char* addr) { #ifndef ACL_WINDOWS if (strchr(addr, '/') != NULL) { fd_ = acl_unix_listen(addr, backlog_, block_ ? ACL_BLOCKING : ACL_NON_BLOCKING); unix_sock_ = true; ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_)); } else #endif fd_ = acl_inet_listen(addr, backlog_, block_ ? ACL_BLOCKING : ACL_NON_BLOCKING); if (fd_ == ACL_SOCKET_INVALID) { logger_error("listen %s error %s", addr, last_serror()); unix_sock_ = false; ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_)); return false; } if (unix_sock_) return true; // 之所以再用 getsockname 重新获得一些监听地址,主要是为了应对当输入的 addr // 为 ip:0 的情形,即当给定的地址中的端口为 0 时要求操作系统自动分配一个端口号 if (acl_getsockname(fd_, addr_, sizeof(addr_)) < 0) { logger_error("getsockname error: %s", acl_last_serror()); ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_)); } return true; }
bool redis_client::open() { if (conn_.opened()) return true; if (conn_.open(addr_, conn_timeout_, rw_timeout_) == false) { logger_error("connect redis %s error: %s", addr_, last_serror()); return false; } // 如果连接密码非空,则尝试用该密码向 redis-server 认证合法性 if (pass_ && *pass_) { redis_connection connection(this); if (connection.auth(pass_) == false) { logger_error("auth error, addr: %s, passwd: %s", addr_, pass_); // 此处返回 true,以便于上层使用该连接访问时 // 由 redis-server 直接给命令报未认证的错训, // 从而免得在 redis_command 类中不断地重试连接 return true; } } return true; }
bool scan_dir::get_cwd(string& out) { #ifndef MAX_PATH #define MAX_PATH 1024 #endif char buf[MAX_PATH]; #ifdef ACL_WINDOWS if (::GetCurrentDirectory(MAX_PATH, buf) == 0) { logger_error("can't get process path: %s", last_serror()); return false; } #else if (::getcwd(buf, sizeof(buf)) == NULL) { logger_error("can't get process path: %s", last_serror()); return false; } #endif // ACL_WINDOWS // xxx: can this happen ? if (buf[0] == 0) return false; // 去掉尾部的 '/' char* end = buf + strlen(buf) - 1; while (end > buf) { #ifdef ACL_WINDOWS if (*end == '/' || *end == '\\') end--; #else if (*end == '/') end--; #endif else break; } out = buf; return true; }
bool master_aio::run_alone(const char* addrs, const char* path /* = NULL */, aio_handle_type ht /* = ENGINE_SELECT */) { acl_assert(__handle == NULL); daemon_mode_ = false; #ifdef WIN32 acl_init(); #endif std::vector<aio_listen_stream*> sstreams; ACL_ARGV* tokens = acl_argv_split(addrs, ";,| \t"); ACL_ITER iter; // 初始化配置参数 conf_.load(path); __handle = NEW aio_handle(ht); ACL_AIO* aio = __handle->get_handle(); acl_assert(aio); ACL_EVENT* eventp = acl_aio_event(aio); set_event(eventp); // 设置基类的事件句柄 acl_foreach(iter, tokens) { const char* addr = (const char*) iter.data; aio_listen_stream* sstream = NEW aio_listen_stream(__handle); // 监听指定的地址 if (sstream->open(addr) == false) { logger_error("listen %s error: %s", addr, last_serror()); close_all_listener(sstreams); // XXX: 为了保证能关闭监听流,应在此处再 check 一下 __handle->check(); acl_argv_free(tokens); return (false); } sstream->add_accept_callback(this); } acl_argv_free(tokens); service_pre_jail(NULL); service_init(NULL); while (true) { // 如果返回 false 则表示不再继续,需要退出 if (__handle->check() == false) { logger("aio_server stop now ..."); break; } } close_all_listener(sstreams); __handle->check(); service_exit(NULL); return true; }
bool tcp_client::open(void) { if (conn_->open(addr_, conn_timeout_, rw_timeout_) == false) { logger_error("connnect %s error %s", addr_, last_serror()); return false; } return true; }
bool file_tmpl::file_copy(const char* from, const char* to_in) { string to_buf; to_buf.format("%s/%s", path_to_.c_str(), to_in); const char* to = to_buf.c_str(); if (strcasecmp(from, to) == 0) { printf("from(%s) == to(%s)\r\n", from, to); return false; } ifstream in; if (in.open_read(from) == false) { printf("open %s error: %s\r\n", from, last_serror()); return false; } ofstream out; if (out.open_write(to) == false) { printf("open %s error: %s\r\n", from, last_serror()); return false; } string buf; while (!in.eof()) { if (in.gets(buf, false) == false) break; if (out.write(buf) < 0) { printf("write to %s error: %s\r\n", to, last_serror()); return false; } } printf("create %s ok\r\n", to); return true; }
unsigned beanstalk::beanstalk_watch(const char* tube) { if (conn_.format("watch %s\r\n", tube) == -1) { logger_error("'watch %s' failed: %s", tube, last_serror()); errbuf_ = "watch"; return 0; } string line(128); if (conn_.gets(line) == false) { logger_error("'watch %s' error(%s): reply ailed", last_serror(), tube); errbuf_ = "watch"; return 0; } ACL_ARGV* tokens = acl_argv_split(line.c_str(), "\t "); if (tokens->argc < 2 || strcasecmp(tokens->argv[0], "WATCHING")) { logger_error("'watch %s' error: %s", tube, line.c_str()); errbuf_ = tokens->argv[0]; acl_argv_free(tokens); close(); return 0; } unsigned n = (unsigned) atoi(tokens->argv[1]); acl_argv_free(tokens); // 如果服务器返回所关注的队列数为 0,肯定是出错了,因为至少还有一个 // 缺省队列:default,所以此时需要关闭连接,以尽量消除与本连接相关 // 的错误,下一个命令会自动进行重连操作以恢复操作过程 if (n == 0) { logger_error("'watch %s' error(%s), tube watched is 0", line.c_str(), tube); errbuf_ = line.c_str(); close(); } return n; }
bool master_proc::run_alone(const char* addrs, const char* path /* = NULL */, 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_cpp_init(); #endif ACL_EVENT* eventp = acl_event_new_select(1, 0); set_event(eventp); // 调用基类方法设置事件引擎句柄 std::vector<ACL_VSTREAM*> sstreams; 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_listen(addr, 128); if (sstream == NULL) { logger_error("listen %s error %s", addr, last_serror()); close_all_listener(sstreams); acl_argv_free(tokens); return false; } service_on_listen(sstream); acl_event_enable_listen(eventp, sstream, 0, listen_callback, sstream); sstreams.push_back(sstream); } acl_argv_free(tokens); // 初始化配置参数 conf_.load(path); service_pre_jail(NULL, NULL); service_init(NULL, NULL); while (!__stop) acl_event_loop(eventp); close_all_listener(sstreams); acl_event_free(eventp); service_exit(NULL, NULL); return true; }
int queue_file::vformat(const char* fmt, va_list ap) { int ret = m_fp->vformat(fmt, ap); if (ret == -1) { logger_error("write to file error(%s)", last_serror()); return -1; } nwriten_ += ret; return ret; }
bool redis_client::open() { if (conn_.opened()) return true; if (conn_.open(addr_, conn_timeout_, rw_timeout_) == false) { logger_error("connect redis %s error: %s", addr_, last_serror()); return false; } return true; }
socket_stream* server_socket::accept(int timeout /* = 0 */) { if (fd_ == ACL_SOCKET_INVALID) { logger_error("server socket not opened!"); return NULL; } if (block_ && timeout > 0) { if (acl_read_wait(fd_, timeout) == -1) return NULL; } ACL_SOCKET fd = acl_accept(fd_, NULL, 0, NULL); if (fd == ACL_SOCKET_INVALID) { if (block_) logger_error("accept error %s", last_serror()); else if (last_error() != ACL_EAGAIN && last_error() != ACL_EWOULDBLOCK) { logger_error("accept error %s", last_serror()); } return NULL; } socket_stream* client = new socket_stream(); if (client->open(fd) == false) { logger_error("create socket_stream error!"); return NULL; } if (!unix_sock_) acl_tcp_set_nodelay(fd); return client; }
void stack_free(void *ptr) { int ret; size_t pgsz = page_size(); ptr = (char *) ptr - pgsz; ret = mprotect(ptr, page_size(), PROT_READ|PROT_WRITE); if (ret != 0) { msg_fatal("%s(%d), %s: mprotect error=%s", __FILE__, __LINE__, __FUNCTION__, last_serror()); } free(ptr); }
bool thread_mutex::unlock(void) { int ret = acl_pthread_mutex_unlock(mutex_); if (ret) { #ifdef ACL_UNIX acl_set_error(ret); logger_error("pthread_mutex_unlock error %s", last_serror()); #endif return false; } return true; }
void open_dos(void) { if (dos_fp_) return; // ´ò¿ª DOS ´°¿Ú AllocConsole(); dos_fp_ = freopen("CONOUT$","w+t",stdout); if (dos_fp_ == NULL) { printf("open DOS error %s\r\n", last_serror()); FreeConsole(); } }
tpl_t* file_tmpl::open_tpl(const char* filename) { tpl_t* tpl = tpl_alloc(); string filepath; filepath.format("%s/%s", path_from_.c_str(), filename); if (tpl_load(tpl, filepath.c_str()) != TPL_OK) { printf("load file %s error: %s\r\n", filepath.c_str(), last_serror()); tpl_free(tpl); return NULL; } return tpl; }
bool beanstalk::open() { if (conn_.opened()) return true; if (conn_.open(addr_, timeout_, 0) == false) { logger_error("connect beanstalkd %s error: %s", addr_, last_serror()); errbuf_= "connect"; return false; } return true; }
queue_manager::queue_manager(const char* home, const char* queueName, unsigned sub_width) : m_scanDir(NULL) , m_home(home) , m_queueName(queueName) { if (sub_width == 0) sub_width_ = 2; else sub_width_ = sub_width; string buf = home; buf << PATH_SEP << queueName; // 先创建根目录 if (acl_make_dirs(buf.c_str(), 0700) == -1) logger_error("create dir: %s error %s", buf.c_str(), last_serror()); else logger("create dir: %s ok", buf.c_str()); char node[32]; for (unsigned i = 0; i < sub_width_; i++) { buf.clear(); safe_snprintf(node, sizeof(node), "%d", i); buf << home << PATH_SEP << queueName << PATH_SEP << node; // 创建队列下子目录 if (acl_make_dirs(buf.c_str(), 0700) == -1) logger_error("create dir: %s error %s", buf.c_str(), last_serror()); else logger("create dir: %s ok", buf.c_str()); } }
void *stack_alloc(size_t size) { int ret; char *ptr = NULL; size_t pgsz = page_size(); size = stack_size(size); size += pgsz; ret = posix_memalign((void *) &ptr, pgsz, size); if (ret != 0) { msg_fatal("%s(%d), %s: posix_memalign error %s", __FILE__, __LINE__, __FUNCTION__, last_serror()); } ret = mprotect(ptr, pgsz, PROT_NONE); if (ret != 0) { msg_fatal("%s(%d), %s: mprotect error=%s", __FILE__, __LINE__, __FUNCTION__, last_serror()); } ptr += pgsz; return ptr; }
bool beanstalk::beanstalk_use() { if (tube_used_ == NULL) return true; if (conn_.format("use %s\r\n", tube_used_) == -1) { logger_error("use %s error: %s", tube_used_, last_serror()); conn_.close(); errbuf_.format("use"); return false; } string line(128); if (conn_.gets(line) == false || line.empty()) { conn_.close(); logger_error("gets from beanstalkd(%s) error: %s", addr_, last_serror()); errbuf_.format("gets"); return false; } ACL_ARGV* tokens = acl_argv_split(line.c_str(), "\t "); if (tokens->argc < 2 || strcasecmp(tokens->argv[0], "USING") || strcasecmp(tokens->argv[1], tube_used_)) { logger_error("'use %s' error %s", tube_used_, tokens->argv[0]); errbuf_ = tokens->argv[0]; acl_argv_free(tokens); close(); return false; } acl_argv_free(tokens); return true; }