static void cpManagerReload(int sig) { zval *group_conf = NULL; group_conf = cpGetConfig(CPGC.ini_file); if (!Z_BVAL_P(group_conf)) { cpLog("parse ini file[%s] error,%s reload error!", CPGC.ini_file, CPGC.title); } else { zval **v, **conf; if (zend_hash_find(Z_ARRVAL_P(group_conf), CPGC.title, strlen(CPGC.title) + 1, (void **) &conf) == SUCCESS) { if (pthread_mutex_lock(CPGS->mutex_lock) == 0) { if (zend_hash_find(Z_ARRVAL_PP(conf), ZEND_STRS("pool_max"), (void **) &v) == SUCCESS) { convert_to_long(*v); CPGS->worker_max = (int) Z_LVAL_PP(v); } if (zend_hash_find(Z_ARRVAL_PP(conf), ZEND_STRS("pool_min"), (void **) &v) == SUCCESS) { convert_to_long(*v); int new_min = (int) Z_LVAL_PP(v); if (new_min > CPGC.worker_min) {//增加最小 while (CPGS->worker_num < new_min) { cpCreate_worker_mem(CPGS->worker_num); CPGS->workers_status[CPGS->worker_num] = CP_WORKER_IDLE; CPGS->worker_num++; //先加 线程安全 int new_pid = cpFork_one_worker(CPGS->worker_num - 1); if (new_pid < 0) { cpLog("Fork worker process failed. Error: %s [%d]", strerror(errno), errno); } else { CPGS->workers[CPGS->worker_num - 1].pid = new_pid; } } } CPGC.worker_min = new_min; } if (zend_hash_find(Z_ARRVAL_PP(conf), ZEND_STRS("recycle_num"), (void **) &v) == SUCCESS) { convert_to_long(*v); CPGC.recycle_num = (int) Z_LVAL_PP(v); } if (zend_hash_find(Z_ARRVAL_PP(conf), ZEND_STRS("idel_time"), (void **) &v) == SUCCESS) { convert_to_long(*v); CPGC.idel_time = (int) Z_LVAL_PP(v); } if (pthread_mutex_unlock(CPGS->mutex_lock) != 0) { cpLog("pthread_mutex_unlock. Error: %s [%d]", strerror(errno), errno); } } } else { cpLog("find %s failed,The reload can only modify 'pool_min','pool_max','recycle_num' and 'idel_time',if you want modify other options please restart pool", CPGC.title); } zval_ptr_dtor(&group_conf); } }
static void cpManagerReload(int sig) { zval *group_conf = NULL, **v; group_conf = cpGetConfig(CPGC.ini_file); int gid = 0; zval **gid_ptr = NULL; cpGroup *G = NULL; if (!Z_BVAL_P(group_conf)) { cpLog("parse ini file[%s] reload error!", CPGC.ini_file); } else { for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(group_conf)); zend_hash_has_more_elements(Z_ARRVAL_P(group_conf)) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(group_conf))) { zval **config; zend_hash_get_current_data(Z_ARRVAL_P(group_conf), (void**) &config); char *name; uint keylen; zend_hash_get_current_key_ex(Z_ARRVAL_P(group_conf), &name, &keylen, NULL, 0, NULL); if (strcmp(name, "common") != 0) { if (zend_hash_find(Z_ARRVAL_P(CPGS->group), name, strlen(name) + 1, (void **) &gid_ptr) == SUCCESS) { gid = Z_LVAL_PP(gid_ptr); G = &CPGS->G[gid]; } else { cpLog("can not add datasource when the server runing,if you want add it please restart"); return; } if (pthread_mutex_lock(G->mutex_lock) == 0) { if (zend_hash_find(Z_ARRVAL_PP(config), ZEND_STRS("pool_max"), (void **) &v) == SUCCESS) { convert_to_long(*v); G->worker_max = (int) Z_LVAL_PP(v); } if (zend_hash_find(Z_ARRVAL_PP(config), ZEND_STRS("pool_min"), (void **) &v) == SUCCESS) { convert_to_long(*v); int new_min = (int) Z_LVAL_PP(v); if (new_min > G->worker_min) {//增加最小 while (G->worker_num < new_min) { cpCreate_worker_mem(G->worker_num, gid); G->workers_status[G->worker_num] = CP_WORKER_IDLE; G->worker_num++; //先加 线程安全 int new_pid = cpFork_one_worker(G->worker_num - 1, gid); if (new_pid < 0) { cpLog("Fork worker process failed. Error: %s [%d]", strerror(errno), errno); } else { G->workers[G->worker_num - 1].pid = new_pid; } } } G->worker_min = new_min; } if (pthread_mutex_unlock(G->mutex_lock) != 0) { cpLog("pthread_mutex_unlock. Error: %s [%d]", strerror(errno), errno); } } } else { if (zend_hash_find(Z_ARRVAL_PP(config), ZEND_STRS("recycle_num"), (void **) &v) == SUCCESS) { convert_to_long(*v); CPGC.recycle_num = (int) Z_LVAL_PP(v); } if (zend_hash_find(Z_ARRVAL_PP(config), ZEND_STRS("idel_time"), (void **) &v) == SUCCESS) { convert_to_long(*v); CPGC.idel_time = (int) Z_LVAL_PP(v); } } } zval_ptr_dtor(&group_conf); } }
CPINLINE cpGroup * cpGet_worker(cpClient *cli, zval **data_source) { cpGroup *G = NULL; int group_id, worker_index; for (group_id = 0; group_id < CPGS->group_num; group_id++) { if (strcmp(Z_STRVAL_PP(data_source), CPGS->G[group_id].name) == 0) { G = &CPGS->G[group_id]; cpConnection *conn = CONN(cli); if (cli->lock(G) == 0) { for (worker_index = 0; worker_index < G->worker_num; worker_index++) { if (G->workers_status[worker_index] == CP_WORKER_IDLE && worker_index < G->worker_max) { G->workers_status[worker_index] = CP_WORKER_BUSY; G->workers[worker_index].CPid = cpPid; //worker for this pid conn->release = CP_FD_NRELEASED; conn->worker_id = group_id * CP_GROUP_LEN + worker_index; conn->group_id = group_id; conn->worker_index = worker_index; break; } } if (conn->release == CP_FD_RELEASED) { if (G->worker_num < G->worker_max) {//add conn->worker_index = G->worker_num; conn->release = CP_FD_NRELEASED; conn->worker_id = group_id * CP_GROUP_LEN + conn->worker_index; conn->group_id = group_id; G->workers_status[conn->worker_index] = CP_WORKER_BUSY; G->workers[conn->worker_index].CPid = cpPid; //worker for this pid cpCreate_worker_mem(conn->worker_index, group_id); cpTcpEvent event = {0}; event.type = CP_TCPEVENT_ADD; event.data = conn->worker_index; // event.ClientPid = cpPid; G->worker_num++; //add first, for thread safe int ret = cpClient_send(cli->sock, (char *) &event, sizeof (event), 0); if (ret < 0) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "send to server errro %s [%d]", strerror(errno), errno); } } else {// in queue conn->wait_fpm_pid = cpPid; conn->next_wait_id = 0; if (G->last_wait_id) { CPGS->conlist[G->last_wait_id].next_wait_id = cli->server_fd; G->last_wait_id = cli->server_fd; } else { G->first_wait_id = G->last_wait_id = cli->server_fd; } conn->release = CP_FD_WAITING; conn->group_id = group_id; } } cli->unLock(G); } break; } } return G; }
static void cpTryGetWorkerId(cpConnection *conn, char * data, int fd, int len) { if (pthread_mutex_lock(CPGS->mutex_lock) == 0) { int i; for (i = 0; i < CPGS->worker_num; i++) { if (CPGS->workers_status[i] == CP_WORKER_IDLE && i < CPGS->worker_max) { CPGS->workers_status[i] = CP_WORKER_BUSY; conn->worker_id = i; conn->release = CP_FD_NRELEASED; if (pthread_mutex_unlock(CPGS->mutex_lock) != 0) { cpLog("pthread_mutex_unlock. Error: %s [%d]", strerror(errno), errno); } return; } } if (CPGS->worker_num < CPGS->worker_max) {//争抢失败增加一个worker conn->release = CP_FD_NRELEASED; conn->worker_id = CPGS->worker_num; cpCreate_worker_mem(CPGS->worker_num); CPGS->workers_status[CPGS->worker_num] = CP_WORKER_BUSY; //创建后立马分配,防止第一次too many connections CPGS->worker_num++; //先加 线程安全 int ret = kill(CPGS->manager_pid, SIGRTMIN); if (ret < 0) { CPGS->worker_num--; //todo cpLog("send sig error. Error: %s [%d]", strerror(errno), errno); } } else if (CPGC.use_wait_queue) { cpWaitList *node = (cpWaitList*) emalloc(sizeof (cpWaitList) + len); node->fd = fd; node->len = len; node->next = NULL; if (CPGS->WaitList) { CPGS->WaitTail->next = node; node->pre = CPGS->WaitTail; CPGS->WaitTail = node; } else { node->pre = NULL; CPGS->WaitList = CPGS->WaitTail = node; } memcpy(node->data, data, len); conn->release = CP_FD_WAITING; } if (pthread_mutex_unlock(CPGS->mutex_lock) != 0) { cpLog("pthread_mutex_unlock. Error: %s [%d]", strerror(errno), errno); } } else { cpLog("pthread_spin_lock. Error: %s [%d]", strerror(errno), errno); } }
int cpServer_start() { int i, pid, ret, ping_pid, sock; if (CPGC.daemonize > 0) { if (daemon(0, 0) < 0) { return FAILURE; } } if ((sock = cpListen()) < 0) { cpLog("listen[1] fail"); return FAILURE; } CPGS->master_pid = getpid(); CPGL.process_type = CP_PROCESS_MASTER; cpList_create(); pid = fork(); switch (pid) { //创建manager进程 case 0: for (i = 0; i < CPGC.worker_min; i++) { //alloc了max个 但是只启动min个 ret = cpCreate_worker_mem(i); pid = cpFork_one_worker(i); if (pid < 0 || ret < 0) { cpLog("Fork worker process fail"); return FAILURE; } else { CPGS->workers[i].pid = pid; CPGS->workers_status[i] = CP_WORKER_IDLE; } } //数据库坏连接检测恢复进程 ret = cpCreate_ping_worker_mem(); ping_pid = cpFork_ping_worker(); if (ping_pid < 0 || ret < 0) { cpLog("Fork ping process fail"); return FAILURE; } CPGS->ping_workers->pid = ping_pid; //标识为管理进程 CPGL.process_type = CP_PROCESS_MANAGER; CPGS->worker_num = CPGC.worker_min; //初始为min个worker ret = cpWorker_manager_loop(); exit(ret); break; //主进程 default: CPGS->manager_pid = pid; break; case -1: { cpLog("fork manager process fail"); return FAILURE; } } cpSignalInit(); if (cpReactor_start(sock) < 0) { cpLog("Reactor_start[1] fail"); return FAILURE; } return SUCCESS; }
int cpServer_start() { int w, pid, ret, sock, g; if (CPGC.daemonize > 0) { if (daemon(0, 0) < 0) { return FAILURE; } } if ((sock = cpListen()) < 0) { cpLog("listen[1] fail"); return FAILURE; } CPGS->master_pid = getpid(); CPGL.process_type = CP_PROCESS_MASTER; pid = fork(); switch (pid) { //创建manager进程 case 0: for (g = 0; g < CPGS->group_num; g++) { for (w = 0; w < CPGS->G[g].worker_min; w++) { //alloc了max个 但是只启动min个 ret = cpCreate_worker_mem(w, g); pid = cpFork_one_worker(w, g); if (pid < 0 || ret < 0) { cpLog("Fork worker process fail"); return FAILURE; } else { CPGS->G[g].workers[w].pid = pid; CPGS->G[g].workers_status[w] = CP_WORKER_IDLE; } } } //数据库坏连接检测恢复进程 // ret = cpCreate_ping_worker_mem(); // ping_pid = cpFork_ping_worker(); // if (ping_pid < 0 || ret < 0) // { // cpLog("Fork ping process fail"); // return FAILURE; // } // CPGS->ping_workers->pid = ping_pid; //标识为管理进程 CPGL.process_type = CP_PROCESS_MANAGER; ret = cpWorker_manager_loop(); exit(ret); break; //主进程 default: CPGS->manager_pid = pid; break; case -1: { cpLog("fork manager process fail"); return FAILURE; } } cpSignalInit(); if (cpReactor_start(sock) < 0) { cpLog("Reactor_start[1] fail"); return FAILURE; } return SUCCESS; }