/** * [ReactorThread] dispatch request to worker */ int swFactoryProcess_dispatch(swFactory *factory, swDispatchData *task) { uint32_t schedule_key; uint32_t send_len = sizeof(task->data.info) + task->data.info.len; uint16_t target_worker_id; swServer *serv = SwooleG.serv; if (task->target_worker_id < 0) { //udp use remote port if (task->data.info.type == SW_EVENT_UDP || task->data.info.type == SW_EVENT_UDP6 || task->data.info.type == SW_EVENT_UNIX_DGRAM) { schedule_key = task->data.info.from_id; } else { schedule_key = task->data.info.fd; } #ifndef SW_USE_RINGBUFFER if (SwooleTG.factory_lock_target) { if (SwooleTG.factory_target_worker < 0) { target_worker_id = swServer_worker_schedule(serv, schedule_key); SwooleTG.factory_target_worker = target_worker_id; } else { target_worker_id = SwooleTG.factory_target_worker; } } else #endif { target_worker_id = swServer_worker_schedule(serv, schedule_key); } } else { target_worker_id = task->target_worker_id; } if (SwooleTG.type == SW_THREAD_REACTOR) { return swReactorThread_send2worker((void *) &(task->data), send_len, target_worker_id); } else { swTrace("dispatch to worker#%d", target_worker_id); return swServer_send2worker_blocking(serv, (void *) &(task->data), send_len, target_worker_id); } }
/** * 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; }