/** * dispatch data to worker */ int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int *dst_worker_id) { int ret = 0; swWorker *worker; if (*dst_worker_id < 0) { *dst_worker_id = swProcessPool_schedule(pool); } *dst_worker_id += pool->start_id; worker = swProcessPool_get_worker(pool, *dst_worker_id); int sendn = sizeof(data->info) + data->info.len; ret = swWorker_send2worker(worker, data, sendn, SW_PIPE_MASTER | SW_PIPE_NONBLOCK); if (ret >= 0) { sw_atomic_fetch_add(&worker->tasking_num, 1); } else { swWarn("send %d bytes to worker#%d failed.", sendn, *dst_worker_id); } return ret; }
/** * dispatch data to worker */ int swProcessPool_dispatch_blocking(swProcessPool *pool, swEventData *data, int *dst_worker_id) { int ret = 0; int sendn = sizeof(data->info) + data->info.len; if (pool->use_socket) { swClient _socket; if (swClient_create(&_socket, SW_SOCK_UNIX_STREAM, SW_SOCK_SYNC) < 0) { return SW_ERR; } if (_socket.connect(&_socket, pool->stream->socket_file, 0, -1, 0) < 0) { return SW_ERR; } if (_socket.send(&_socket, (void*) data, sendn, 0) < 0) { return SW_ERR; } _socket.close(&_socket); return SW_OK; } if (*dst_worker_id < 0) { *dst_worker_id = swProcessPool_schedule(pool); } *dst_worker_id += pool->start_id; swWorker *worker = swProcessPool_get_worker(pool, *dst_worker_id); ret = swWorker_send2worker(worker, data, sendn, SW_PIPE_MASTER); if (ret < 0) { swWarn("send %d bytes to worker#%d failed.", sendn, *dst_worker_id); } else { sw_atomic_fetch_add(&worker->tasking_num, 1); } return ret; }
/** * dispatch data to worker */ int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int *dst_worker_id) { int ret = 0; swWorker *worker; if (pool->use_socket) { swStream *stream = swStream_new(pool->stream->socket_file, 0, SW_SOCK_UNIX_STREAM); if (stream == NULL) { return SW_ERR; } stream->response = NULL; stream->session_id = 0; if (swStream_send(stream, (char*) data, sizeof(data->info) + data->info.len) < 0) { stream->cancel = 1; return SW_ERR; } return SW_OK; } if (*dst_worker_id < 0) { *dst_worker_id = swProcessPool_schedule(pool); } *dst_worker_id += pool->start_id; worker = swProcessPool_get_worker(pool, *dst_worker_id); int sendn = sizeof(data->info) + data->info.len; ret = swWorker_send2worker(worker, data, sendn, SW_PIPE_MASTER | SW_PIPE_NONBLOCK); if (ret >= 0) { sw_atomic_fetch_add(&worker->tasking_num, 1); } else { swWarn("send %d bytes to worker#%d failed.", sendn, *dst_worker_id); } return ret; }
/** * dispatch data to worker */ int swProcessPool_dispatch_blocking(swProcessPool *pool, swEventData *data, int *dst_worker_id) { int ret = 0; swWorker *worker; if (*dst_worker_id < 0) { *dst_worker_id = swProcessPool_schedule(pool); } *dst_worker_id += pool->start_id; worker = swProcessPool_get_worker(pool, *dst_worker_id); int sendn = sizeof(data->info) + data->info.len; ret = swWorker_send2worker(worker, data, sendn, SW_PIPE_MASTER); if (ret < 0) { swWarn("send %d bytes to worker#%d failed.", sendn, *dst_worker_id); } return ret; }
/** * Send the task result to worker */ int swTaskWorker_finish(swServer *serv, char *data, int data_len, int flags) { 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 (swTask_type(current_task) & SW_TASK_NONBLOCK) { buf.info.type = SW_EVENT_FINISH; buf.info.fd = current_task->info.fd; swTask_type(&buf) = flags; //write to file if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { 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; } uint16_t target_worker_id = current_task->info.from_id; swWorker *worker = swServer_get_worker(serv, target_worker_id); ret = swWorker_send2worker(worker, &buf, sizeof(buf.info) + buf.info.len, SW_PIPE_MASTER); } 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; swTask_type(result) = flags; if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { 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; } while (1) { ret = task_notify_pipe->write(task_notify_pipe, &flag, sizeof(flag)); #ifdef HAVE_KQUEUE if (errno == EAGAIN || errno == ENOBUFS) #else if (errno == EAGAIN) #endif { 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; }
/** * Send the task result to worker */ int swTaskWorker_finish(swServer *serv, char *data, int data_len, int flags) { swEventData buf; if (!current_task) { swWarn("cannot use finish in worker"); return SW_ERR; } if (serv->task_worker_num < 1) { swWarn("cannot use task/finish, because no set serv->task_worker_num."); return SW_ERR; } if (current_task->info.type == SW_EVENT_PIPE_MESSAGE) { swWarn("task/finish is not supported in onPipeMessage callback."); return SW_ERR; } uint16_t source_worker_id = current_task->info.from_id; swWorker *worker = swServer_get_worker(serv, source_worker_id); if (worker == NULL) { swWarn("invalid worker_id[%d].", source_worker_id); return SW_ERR; } int ret; //for swoole_server_task if (swTask_type(current_task) & SW_TASK_NONBLOCK) { buf.info.type = SW_EVENT_FINISH; buf.info.fd = current_task->info.fd; //callback function if (swTask_type(current_task) & SW_TASK_CALLBACK) { flags |= SW_TASK_CALLBACK; } else if (swTask_type(current_task) & SW_TASK_COROUTINE) { flags |= SW_TASK_COROUTINE; } swTask_type(&buf) = flags; //write to file if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { 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; } if (worker->pool->use_socket && worker->pool->stream->last_connection > 0) { int32_t _len = htonl(data_len); ret = swSocket_write_blocking(worker->pool->stream->last_connection, (void *) &_len, sizeof(_len)); if (ret > 0) { ret = swSocket_write_blocking(worker->pool->stream->last_connection, data, data_len); } } else { ret = swWorker_send2worker(worker, &buf, sizeof(buf.info) + buf.info.len, SW_PIPE_MASTER); } } else { uint64_t flag = 1; /** * Use worker shm store the result */ swEventData *result = &(serv->task_result[source_worker_id]); swPipe *task_notify_pipe = &(serv->task_notify[source_worker_id]); //lock worker worker->lock.lock(&worker->lock); if (swTask_type(current_task) & SW_TASK_WAITALL) { sw_atomic_t *finish_count = (sw_atomic_t*) result->data; char *_tmpfile = result->data + 4; int fd = open(_tmpfile, O_APPEND | O_WRONLY); if (fd >= 0) { buf.info.type = SW_EVENT_FINISH; buf.info.fd = current_task->info.fd; swTask_type(&buf) = flags; //result pack if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { if (swTaskWorker_large_pack(&buf, data, data_len) < 0) { swWarn("large task pack failed()"); buf.info.len = 0; } } else { buf.info.len = data_len; memcpy(buf.data, data, data_len); } //write to tmpfile if (swoole_sync_writefile(fd, &buf, sizeof(buf.info) + buf.info.len) < 0) { swSysError("write(%s, %ld) failed.", _tmpfile, sizeof(buf.info) + buf.info.len); } sw_atomic_fetch_add(finish_count, 1); close(fd); } } else { result->info.type = SW_EVENT_FINISH; result->info.fd = current_task->info.fd; swTask_type(result) = flags; if (data_len >= SW_IPC_MAX_SIZE - sizeof(buf.info)) { if (swTaskWorker_large_pack(result, data, data_len) < 0) { //unlock worker worker->lock.unlock(&worker->lock); swWarn("large task pack failed()"); return SW_ERR; } } else { memcpy(result->data, data, data_len); result->info.len = data_len; } } //unlock worker worker->lock.unlock(&worker->lock); while (1) { ret = task_notify_pipe->write(task_notify_pipe, &flag, sizeof(flag)); #ifdef HAVE_KQUEUE if (ret < 0 && (errno == EAGAIN || errno == ENOBUFS)) #else if (ret < 0 && errno == EAGAIN) #endif { 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; }