/** * 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); }
/** * 主进程向worker进程发送数据 * @param worker_id 发到指定的worker进程 */ int swFactoryProcess_send2worker(swFactory *factory, swEventData *data, int worker_id) { swFactoryProcess *object = factory->object; swServer *serv = factory->ptr; int pti; int ret; int send_len = sizeof(data->info) + data->info.len; if (worker_id < 0) { //轮询 // data->info.from_id > serv->poll_thread_num, UDP必须使用轮询 if (serv->dispatch_mode == SW_DISPATCH_ROUND || data->info.from_id > serv->poll_thread_num) { pti = (object->worker_pti++) % object->worker_num; } //使用fd取摸来散列 else if (serv->dispatch_mode == SW_DISPATCH_FDMOD) { pti = data->info.fd % object->worker_num; } //使用抢占式队列(IPC消息队列)分配 else { #if SW_WORKER_IPC_MODE != 2 swError("SW_DISPATCH_QUEUE must use (SW_WORKER_IPC_MODE = 2)"); #endif //msgsnd参数必须>0 //worker进程中正确的mtype应该是pti + 1 pti = object->worker_num; } } //指定了worker_id else { pti = worker_id; } #if SW_WORKER_IPC_MODE == 2 //insert to msg queue swQueue_data *in_data = (swQueue_data *)((void *)data - sizeof(long)); //加1防止id为0的worker进程出错 in_data->mtype = pti + 1; swDataHead *info = (swDataHead *)in_data->mdata; ret = object->rd_queue.in(&object->rd_queue, in_data, send_len); swTrace("[Master]rd_queue[%ld]->in: fd=%d|type=%d|len=%d", in_data->mtype, info->fd, info->type, info->len); #else //send to unix sock ret = swWrite(object->workers[pti].pipe_master, (char *) data, send_len); #endif return ret; }
/** * 主进程向worker进程发送数据 * @param worker_id 发到指定的worker进程 */ int swFactoryProcess_send2worker(swFactory *factory, swEventData *data, int worker_id) { swFactoryProcess *object = factory->object; swServer *serv = factory->ptr; int pti = 0; int ret; int send_len = sizeof(data->info) + data->info.len; if (worker_id < 0) { if (SwooleTG.factory_lock_target) { if (SwooleTG.factory_target_worker < 0) { pti = swFactoryProcess_schedule(object, data); SwooleTG.factory_target_worker = pti; } else { pti = SwooleTG.factory_target_worker; } } else { pti = swFactoryProcess_schedule(object, data); } } //指定了worker_id else { pti = worker_id; } if (serv->ipc_mode == SW_IPC_MSGQUEUE) { //insert to msg queue swQueue_data *in_data = (swQueue_data *) ((void *) data - sizeof(long)); //加1防止id为0的worker进程出错 in_data->mtype = pti + 1; ret = object->rd_queue.in(&object->rd_queue, in_data, send_len); //swTrace("[Master]rd_queue[%ld]->in: fd=%d|type=%d|len=%d", in_data->mtype, info->fd, info->type, info->len); } else { //send to unix sock //swWarn("pti=%d|from_id=%d|data_len=%d|swDataHead_size=%ld", pti, data->info.from_id, send_len, sizeof(swDataHead)); ret = swWrite(object->workers[pti].pipe_master, (void *) data, send_len); } return ret; }
int swFactoryProcess_event(swFactory *factory, int controller_id, swEventData *data) { swFactoryProcess *object = factory->object; int pipe_fd, ret; int send_len = sizeof(data->info) + data->info.len; //这是一个controller if(controller_id > manager_controller_count) { swWarn("controller_id > manager_controller_count"); return SW_ERR; } pipe_fd = manager_controller_pipes[controller_id].pipes[0]; ret = swWrite(pipe_fd, (char *)data, send_len); return (ret < 0) ? SW_ERR : SW_OK; }
int swFactoryProcess_dispatch(swFactory *factory, swEventData *data) { swFactoryProcess *this = factory->object; int pti = this->worker_pti; int ret; if (this->worker_pti >= this->worker_num) { this->worker_pti = 0; pti = 0; } swTrace("[ReadThread]sendto: pipe=%d|worker=%d\n", this->workers[pti].pipe_fd, pti); //send to unix sock ret = swWrite(this->workers[pti].pipe_fd, (char *) data, data->len + (3 * sizeof(int))); if (ret < 0) { return SW_ERR; } this->worker_pti++; return SW_OK; }
/** * 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); }
/** * 主进程向worker进程发送数据 * @param worker_id 发到指定的worker进程 */ int swFactoryProcess_send2worker(swFactory *factory, swEventData *data, int worker_id) { swFactoryProcess *object = factory->object; swServer *serv = factory->ptr; int pti = 0; int ret; int send_len = sizeof(data->info) + data->info.len; if (worker_id < 0) { //轮询 if (serv->dispatch_mode == SW_DISPATCH_ROUND) { pti = (object->worker_pti++) % object->worker_num; } //使用fd取摸来散列 else if (serv->dispatch_mode == SW_DISPATCH_FDMOD) { //Fixed #48. 替换一下顺序 //udp use remote port if (data->info.type == SW_EVENT_UDP) { pti = ((uint16_t) data->info.from_id) % object->worker_num; } else { pti = data->info.fd % object->worker_num; } } //使用抢占式队列(IPC消息队列)分配 else { #if SW_WORKER_IPC_MODE == 2 //msgsnd参数必须>0 //worker进程中正确的mtype应该是pti + 1 pti = object->worker_num; #else int i; atomic_t *round = &SwooleWG.worker_pti; for(i=0; i< serv->worker_num; i++) { sw_atomic_fetch_add(round, 1); pti = (*round) % serv->worker_num; if (object->workers_status[pti] == SW_WORKER_IDLE) { break; } } #endif } } //指定了worker_id else { pti = worker_id; } #if SW_WORKER_IPC_MODE == 2 //insert to msg queue swQueue_data *in_data = (swQueue_data *)((void *)data - sizeof(long)); //加1防止id为0的worker进程出错 in_data->mtype = pti + 1; swDataHead *info = (swDataHead *)in_data->mdata; ret = object->rd_queue.in(&object->rd_queue, in_data, send_len); swTrace("[Master]rd_queue[%ld]->in: fd=%d|type=%d|len=%d", in_data->mtype, info->fd, info->type, info->len); #else //swWarn("pti=%d|from_id=%d", pti, data->info.from_id); //send to unix sock ret = swWrite(object->workers[pti].pipe_master, (char *) data, send_len); #endif return ret; }
/** * Send the task result to worker */ int swTaskWorker_finish(swServer *serv, char *data, int data_len) { swEventData buf; if (SwooleG.task_worker_num < 1) { swWarn("cannot use task/finish, because no set serv->task_worker_num."); return SW_ERR; } int ret; //for swoole_server_task if (current_task->info.type == SW_TASK_NONBLOCK) { buf.info.type = SW_EVENT_FINISH; buf.info.fd = current_task->info.fd; //write to file if (data_len >= sizeof(buf.data)) { if (swTaskWorker_large_pack(&buf, data, data_len) < 0 ) { swWarn("large task pack failed()"); return SW_ERR; } } else { memcpy(buf.data, data, data_len); buf.info.len = data_len; buf.info.from_fd = 0; } //tasking /** * TODO: 这里需要重构,改成统一的模式 */ if (serv->factory_mode == SW_MODE_PROCESS) { ret = swServer_send2worker_blocking(serv, &buf, sizeof(buf.info) + buf.info.len, current_task->info.from_id); } else { ret = swWrite(SwooleG.event_workers->workers[current_task->info.from_id].pipe_worker, &buf, sizeof(buf.info) + data_len); } } else { uint64_t flag = 1; uint16_t worker_id = current_task->info.from_id; /** * Use worker shm store the result */ swEventData *result = &(SwooleG.task_result[worker_id]); swPipe *task_notify_pipe = &(SwooleG.task_notify[worker_id]); result->info.type = SW_EVENT_FINISH; result->info.fd = current_task->info.fd; if (data_len >= sizeof(buf.data)) { if (swTaskWorker_large_pack(result, data, data_len) < 0) { swWarn("large task pack failed()"); return SW_ERR; } } else { memcpy(result->data, data, data_len); result->info.len = data_len; result->info.from_fd = 0; } while (1) { ret = task_notify_pipe->write(task_notify_pipe, &flag, sizeof(flag)); if (ret < 0 && errno == EAGAIN) { if (swSocket_wait(task_notify_pipe->getFd(task_notify_pipe, 1), -1, SW_EVENT_WRITE) == 0) { continue; } } break; } } if (ret < 0) { swWarn("TaskWorker: send result to worker failed. Error: %s[%d]", strerror(errno), errno); } return ret; }
int swServer_onFinish(swFactory *factory, swSendData *resp) { return swWrite(resp->fd, resp->data, resp->len); }
/** * send to client or append to out_buffer */ int swReactorThread_send(swEventData *resp) { int buf_size, copy_n; swServer *serv = SwooleG.serv; swSendData send_data; swEvent closeFd; swBuffer_trunk *trunk; swTask_sendfile *task; swConnection *conn = swServer_get_connection(serv, resp->info.fd); swReactor *reactor = &(serv->reactor_threads[conn->from_id].reactor); //recv length=0, will close connection if (resp->info.len == 0) { #ifdef SW_REACTOR_DIRECT_SEND close_fd: #endif { closeFd.fd = resp->info.fd; closeFd.from_id = resp->info.from_id; closeFd.type = SW_EVENT_CLOSE; //printf("closeFd.fd=%d|from_id=%d\n", closeFd.fd, closeFd.from_id); swReactorThread_onClose(reactor, &closeFd); } return SW_OK; } //sendfile to client else if(resp->info.type == SW_EVENT_SENDFILE) { trunk = swConnection_get_out_buffer(conn, SW_TRUNK_SENDFILE); if (trunk == NULL) { swWarn("get out_buffer trunk failed."); return SW_ERR; } task = sw_malloc(sizeof(swTask_sendfile)); if (task == NULL) { swWarn("malloc for swTask_sendfile failed."); //TODO: 回收这里的内存 return SW_ERR; } bzero(task, sizeof(swTask_sendfile)); int file_fd = open(resp->data, O_RDONLY); if (file_fd < 0) { swWarn("open file[%s] failed. Error: %s[%d]", task->filename, strerror(errno), errno); return SW_ERR; } struct stat file_stat; if (fstat(file_fd, &file_stat) < 0) { swWarn("swoole_async_readfile: fstat failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } task->filesize = file_stat.st_size; task->fd = file_fd; trunk->data = (void *)task; reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ); } //send data else { send_data.data = resp->data; send_data.info.len = resp->info.len; send_data.info.from_id = resp->info.from_id; send_data.info.fd = resp->info.fd; #ifdef SW_REACTOR_DIRECT_SEND if(!swBuffer_empty(conn->out_buffer)) { trunk = swBuffer_get_trunk(conn->out_buffer); #else { trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA); #endif buf_size = conn->out_buffer->trunk_size - trunk->length; #ifdef SW_REACTOR_DIRECT_SEND append_out_buffer: #else //listen EPOLLOUT event reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ); #endif do { copy_n = (buf_size >= send_data.info.len) ? send_data.info.len : buf_size; memcpy(trunk->data, send_data.data, copy_n); send_data.data += copy_n; send_data.info.len -= copy_n; trunk->length += copy_n; buf_size += copy_n; //trunk is full, create new trunk if (trunk->length == conn->out_buffer->trunk_size) { //trunk no enough space, creating a new trunk trunk = swBuffer_new_trunk(conn->out_buffer, SW_TRUNK_DATA); if (trunk == NULL) { swWarn("append to out_buffer failed."); return SW_ERR; } buf_size = conn->out_buffer->trunk_size; } } while(send_data.info.len > 0); } #ifdef SW_REACTOR_DIRECT_SEND else { //try send int ret = swWrite(send_data.info.fd, send_data.data, send_data.info.len); if (ret < 0) { //连接已被关闭 if (errno == ECONNRESET || errno == EBADF) { goto close_fd; } swWarn("factory->onFinish failed.fd=%d|from_id=%d. Error: %s[%d]", resp->info.fd, resp->info.from_id, strerror(errno), errno); } //Did not finish, add to writable event callback else if(ret < resp->info.len) { trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA); send_data.data += ret; send_data.info.len -= ret; buf_size = conn->out_buffer->trunk_size; goto append_out_buffer; } //printf("[writer]pop.fd=%d|from_id=%d|data=%s\n", resp->info.fd, resp->info.from_id, resp->data); } #endif }