/** * [ReactorThread] dispatch request to worker */ static 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) { 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 (swEventData_is_stream(task->data.info.type)) { swConnection *conn = swServer_connection_get(serv, task->data.info.fd); if (conn == NULL || conn->active == 0) { swWarn("dispatch[type=%d] failed, connection#%d is not active.", task->data.info.type, task->data.info.fd); return SW_ERR; } //server active close, discard data. if (conn->closed) { if (!(task->data.info.type == SW_EVENT_CLOSE && conn->close_force)) { swWarn("dispatch[type=%d] failed, connection#%d[session_id=%d] is closed by server.", task->data.info.type, task->data.info.fd, conn->session_id); return SW_OK; } } //converted fd to session_id task->data.info.fd = conn->session_id; task->data.info.from_fd = conn->from_fd; } return swReactorThread_send2worker((void *) &(task->data), send_len, target_worker_id); }
/** * [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); } }
int swConnection_send_in_buffer(swConnection *conn) { swDispatchData task; swFactory *factory = SwooleG.factory; task.data.info.fd = conn->fd; task.data.info.from_id = conn->from_id; swBuffer *buffer = conn->in_buffer; swBuffer_trunk *trunk = swBuffer_get_trunk(buffer); #ifdef SW_USE_RINGBUFFER swServer *serv = SwooleG.serv; uint16_t target_worker_id = swServer_worker_schedule(serv, conn->fd); swWorker *worker = swServer_get_worker(serv, target_worker_id); swMemoryPool *pool = worker->pool_input; swPackage package; package.length = 0; while (1) { package.data = pool->alloc(pool, buffer->length); if (package.data == NULL) { swYield(); swWarn("reactor memory pool full."); continue; } break; } task.data.info.type = SW_EVENT_PACKAGE; while (trunk != NULL) { task.data.info.len = trunk->length; memcpy(package.data + package.length, trunk->store.ptr, trunk->length); package.length += trunk->length; swBuffer_pop_trunk(buffer, trunk); trunk = swBuffer_get_trunk(buffer); } task.data.info.len = sizeof(package); task.target_worker_id = target_worker_id; memcpy(task.data.data, &package, sizeof(package)); //swWarn("[ReactorThread] copy_n=%d", package.length); return factory->dispatch(factory, &task); #else int ret; task.data.info.type = SW_EVENT_PACKAGE_START; task.target_worker_id = -1; /** * lock target */ SwooleTG.factory_lock_target = 1; while (trunk != NULL) { task.data.info.len = trunk->length; memcpy(task.data.data, trunk->store.ptr, task.data.info.len); //package end if (trunk->next == NULL) { task.data.info.type = SW_EVENT_PACKAGE_END; } ret = factory->dispatch(factory, &task); //TODO: 处理数据失败,数据将丢失 if (ret < 0) { swWarn("factory->dispatch() failed."); } swBuffer_pop_trunk(buffer, trunk); trunk = swBuffer_get_trunk(buffer); swTrace("send2worker[trunk_num=%d][type=%d]\n", buffer->trunk_num, _send.info.type); } /** * unlock */ SwooleTG.factory_target_worker = -1; SwooleTG.factory_lock_target = 0; #endif return SW_OK; }
int swConnection_send_string_buffer(swConnection *conn) { int ret; swString *buffer = conn->object; swFactory *factory = SwooleG.factory; swDispatchData task; task.data.info.fd = conn->fd; task.data.info.from_id = conn->from_id; #ifdef SW_USE_RINGBUFFER swServer *serv = SwooleG.serv; int target_worker_id = swServer_worker_schedule(serv, conn->fd); swWorker *worker = swServer_get_worker(serv, target_worker_id); swMemoryPool *pool = worker->pool_input; swPackage package; package.length = buffer->length; while (1) { package.data = pool->alloc(pool, buffer->length); if (package.data == NULL) { swYield(); swWarn("reactor memory pool full."); continue; } break; } task.data.info.type = SW_EVENT_PACKAGE; task.data.info.len = sizeof(package); task.target_worker_id = target_worker_id; //swoole_dump_bin(package.data, 's', buffer->length); memcpy(package.data, buffer->str, buffer->length); memcpy(task.data.data, &package, sizeof(package)); ret = factory->dispatch(factory, &task); #else int send_n = buffer->length; task.data.info.type = SW_EVENT_PACKAGE_START; task.target_worker_id = -1; /** * lock target */ SwooleTG.factory_lock_target = 1; void *send_ptr = buffer->str; do { if (send_n > SW_BUFFER_SIZE) { task.data.info.len = SW_BUFFER_SIZE; memcpy(task.data.data, send_ptr, SW_BUFFER_SIZE); } else { task.data.info.type = SW_EVENT_PACKAGE_END; task.data.info.len = send_n; memcpy(task.data.data, send_ptr, send_n); } swTrace("dispatch, type=%d|len=%d\n", _send.info.type, _send.info.len); ret = factory->dispatch(factory, &task); //TODO: 处理数据失败,数据将丢失 if (ret < 0) { swWarn("factory->dispatch failed."); } send_n -= task.data.info.len; send_ptr += task.data.info.len; } while (send_n > 0); /** * unlock */ SwooleTG.factory_target_worker = -1; SwooleTG.factory_lock_target = 0; #endif return ret; }