/** * Process manager */ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request) { bzero(pool, sizeof(swProcessPool)); pool->workers = sw_calloc(worker_num, sizeof(swWorker)); pool->worker_num = worker_num; pool->max_request = max_request; if (pool->workers == NULL) { swWarn("[swProcessPool_create] malloc fail."); return SW_ERR; } int i; swPipe pipe; for (i = 0; i < worker_num; i++) { if (swPipeUnsock_create(&pipe, 1, SOCK_DGRAM) < 0) { return SW_ERR; } swProcessPool_worker(pool, i).pipe_master = pipe.getFd(&pipe, 1); swProcessPool_worker(pool, i).pipe_worker = pipe.getFd(&pipe, 0); swProcessPool_worker(pool, i).id = i; swProcessPool_worker(pool, i).pool = pool; } pool->onStart = swProcessPool_worker_start; return SW_OK; }
/** * Process manager */ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key) { bzero(pool, sizeof(swProcessPool)); pool->workers = sw_calloc(worker_num, sizeof(swWorker)); pool->worker_num = worker_num; pool->max_request = max_request; if (pool->workers == NULL) { swWarn("malloc[1] failed."); return SW_ERR; } pool->pipes = sw_calloc(worker_num, sizeof(swPipe)); if (pool->pipes == NULL) { swWarn("malloc[2] failed."); sw_free(pool->workers); return SW_ERR; } int i; if (msgqueue_key > 0) { if (swQueueMsg_create(&pool->queue, 1, msgqueue_key, 1) < 0) { return SW_ERR; } pool->use_msgqueue = 1; pool->msgqueue_key = msgqueue_key; } else { swPipe *pipe; for (i = 0; i < worker_num; i++) { pipe = &pool->pipes[i]; if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0) { return SW_ERR; } swProcessPool_worker(pool, i).pipe_master = pipe->getFd(pipe, 1); swProcessPool_worker(pool, i).pipe_worker = pipe->getFd(pipe, 0); } } for (i = 0; i < worker_num; i++) { swProcessPool_worker(pool, i).id = i; swProcessPool_worker(pool, i).pool = pool; } pool->main_loop = swProcessPool_worker_start; return SW_OK; }
/** * dispatch data to worker */ int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int worker_id) { int ret; //no worker_id, will round if (worker_id < 0) { worker_id = (pool->round_id++)%pool->worker_num; } struct { long mtype; swEventData buf; } in; if (pool->use_msgqueue) { in.mtype = worker_id + 1; memcpy(&in.buf, data, sizeof(data->info) + data->info.len); ret = pool->queue.in(&pool->queue, (swQueue_data *) &in, sizeof(data->info) + data->info.len); if (ret < 0) { swWarn("msgsnd failed. Error: %s[%d]", strerror(errno), errno); } } else { swWorker *worker = &swProcessPool_worker(pool, worker_id); while(1) { ret = write(worker->pipe_master, data, sizeof(data->info) + data->info.len); if (ret < 0) { /** * Wait pipe can be written. */ if (errno == EAGAIN && swSocket_wait(worker->pipe_master, SW_WORKER_WAIT_TIMEOUT, SW_EVENT_WRITE) == SW_OK) { continue; } else if (errno == EINTR) { continue; } else { break; } } break; } if (ret < 0) { swWarn("sendto unix socket failed. Error: %s[%d]", strerror(errno), errno); } } return ret; }
/** * dispatch */ int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int worker_id) { //no worker_id, will round if(worker_id < 0) { worker_id = (pool->round_id++)%pool->worker_num; } swWorker *worker = &swProcessPool_worker(pool, worker_id); return swWrite(worker->pipe_master, data, sizeof(data->info) + data->info.len); }
int swProcessPool_add_worker(swProcessPool *ma, swWorkerCall cb) { swPipe pipe; if (ma->worker_num >= ma->max_num) { swWarn("[swProcessPool_create] too many worker[max_num=%d]", ma->max_num); return SW_ERR; } int cur_id = ma->worker_num++; swProcessPool_worker(ma, cur_id).call = cb; if (swPipeUnsock_create(&pipe, 1, SOCK_STREAM) < 0) { return SW_ERR; } swProcessPool_worker(ma, cur_id).pipe_master = pipe.getFd(&pipe, 1); swProcessPool_worker(ma, cur_id).pipe_worker = pipe.getFd(&pipe, 0); swProcessPool_worker(ma, cur_id).id = cur_id; return cur_id; }
/** * dispatch */ int swProcessPool_dispatch(swProcessPool *pool, swEventData *data) { int id = (pool->round_id++)%pool->worker_num; swWorker *worker = &swProcessPool_worker(pool, id); return swWrite(worker->pipe_master, data, sizeof(data->info) + data->info.len); }