You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
170
vendor/swoole/src/factory/Factory.c
vendored
Executable file
170
vendor/swoole/src/factory/Factory.c
vendored
Executable file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "Server.h"
|
||||
|
||||
int swFactory_create(swFactory *factory)
|
||||
{
|
||||
factory->dispatch = swFactory_dispatch;
|
||||
factory->finish = swFactory_finish;
|
||||
factory->start = swFactory_start;
|
||||
factory->shutdown = swFactory_shutdown;
|
||||
factory->end = swFactory_end;
|
||||
factory->notify = swFactory_notify;
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
int swFactory_start(swFactory *factory)
|
||||
{
|
||||
SwooleWG.run_always = 1;
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
int swFactory_shutdown(swFactory *factory)
|
||||
{
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
int swFactory_dispatch(swFactory *factory, swDispatchData *task)
|
||||
{
|
||||
swServer *serv = factory->ptr;
|
||||
factory->last_from_id = task->data.info.from_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)
|
||||
{
|
||||
swWarn("dispatch[type=%d] failed, connection#%d is closed by server.", task->data.info.type,
|
||||
task->data.info.fd);
|
||||
return SW_OK;
|
||||
}
|
||||
//converted fd to session_id
|
||||
task->data.info.fd = conn->session_id;
|
||||
task->data.info.from_fd = conn->from_fd;
|
||||
}
|
||||
return swWorker_onTask(factory, &task->data);
|
||||
}
|
||||
|
||||
int swFactory_notify(swFactory *factory, swDataHead *info)
|
||||
{
|
||||
swServer *serv = factory->ptr;
|
||||
swConnection *conn = swServer_connection_get(serv, info->fd);
|
||||
if (conn == NULL || conn->active == 0)
|
||||
{
|
||||
swWarn("dispatch[type=%d] failed, connection#%d is not active.", info->type, info->fd);
|
||||
return SW_ERR;
|
||||
}
|
||||
//server active close, discard data.
|
||||
if (conn->closed)
|
||||
{
|
||||
swWarn("dispatch[type=%d] failed, connection#%d is closed by server.", info->type, info->fd);
|
||||
return SW_OK;
|
||||
}
|
||||
//converted fd to session_id
|
||||
info->fd = conn->session_id;
|
||||
info->from_fd = conn->from_fd;
|
||||
return swWorker_onTask(factory, (swEventData *) info);
|
||||
}
|
||||
|
||||
int swFactory_end(swFactory *factory, int fd)
|
||||
{
|
||||
swServer *serv = factory->ptr;
|
||||
swSendData _send;
|
||||
swDataHead info;
|
||||
|
||||
bzero(&_send, sizeof(_send));
|
||||
_send.info.fd = fd;
|
||||
_send.info.len = 0;
|
||||
_send.info.type = SW_EVENT_CLOSE;
|
||||
|
||||
swConnection *conn = swWorker_get_connection(serv, fd);
|
||||
if (conn == NULL || conn->active == 0)
|
||||
{
|
||||
//swWarn("can not close. Connection[%d] not found.", _send.info.fd);
|
||||
return SW_ERR;
|
||||
}
|
||||
else if (conn->close_force)
|
||||
{
|
||||
goto do_close;
|
||||
}
|
||||
else if (conn->closing)
|
||||
{
|
||||
swWarn("The connection[%d] is closing.", fd);
|
||||
return SW_ERR;
|
||||
}
|
||||
else if (conn->closed)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_close:
|
||||
conn->closing = 1;
|
||||
if (serv->onClose != NULL)
|
||||
{
|
||||
info.fd = fd;
|
||||
if (conn->close_actively)
|
||||
{
|
||||
info.from_id = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.from_id = conn->from_id;
|
||||
}
|
||||
info.from_fd = conn->from_fd;
|
||||
serv->onClose(serv, &info);
|
||||
}
|
||||
conn->closing = 0;
|
||||
conn->closed = 1;
|
||||
conn->close_errno = 0;
|
||||
|
||||
if (swBuffer_empty(conn->out_buffer) || conn->removed)
|
||||
{
|
||||
swReactor *reactor = &serv->reactor_threads[SwooleTG.id].reactor;
|
||||
return swReactorThread_close(reactor, conn->fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
swBuffer_trunk *trunk = swBuffer_new_trunk(conn->out_buffer, SW_CHUNK_CLOSE, 0);
|
||||
trunk->store.data.val1 = _send.info.type;
|
||||
return SW_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int swFactory_finish(swFactory *factory, swSendData *resp)
|
||||
{
|
||||
if (resp->length == 0)
|
||||
{
|
||||
resp->length = resp->info.len;
|
||||
}
|
||||
if (swReactorThread_send(resp) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SW_OK;
|
||||
}
|
||||
}
|
335
vendor/swoole/src/factory/FactoryProcess.c
vendored
Executable file
335
vendor/swoole/src/factory/FactoryProcess.c
vendored
Executable file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "Server.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static int swFactoryProcess_start(swFactory *factory);
|
||||
static int swFactoryProcess_notify(swFactory *factory, swDataHead *event);
|
||||
static int swFactoryProcess_dispatch(swFactory *factory, swDispatchData *buf);
|
||||
static int swFactoryProcess_finish(swFactory *factory, swSendData *data);
|
||||
static int swFactoryProcess_shutdown(swFactory *factory);
|
||||
static int swFactoryProcess_end(swFactory *factory, int fd);
|
||||
|
||||
int swFactoryProcess_create(swFactory *factory, int worker_num)
|
||||
{
|
||||
swFactoryProcess *object;
|
||||
object = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(swFactoryProcess));
|
||||
if (object == NULL)
|
||||
{
|
||||
swWarn("[Master] malloc[object] failed");
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
factory->object = object;
|
||||
factory->dispatch = swFactoryProcess_dispatch;
|
||||
factory->finish = swFactoryProcess_finish;
|
||||
factory->start = swFactoryProcess_start;
|
||||
factory->notify = swFactoryProcess_notify;
|
||||
factory->shutdown = swFactoryProcess_shutdown;
|
||||
factory->end = swFactoryProcess_end;
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static int swFactoryProcess_shutdown(swFactory *factory)
|
||||
{
|
||||
int status;
|
||||
swServer *serv = factory->ptr;
|
||||
|
||||
if (swKill(serv->gs->manager_pid, SIGTERM) < 0)
|
||||
{
|
||||
swSysError("kill(%d) failed.", serv->gs->manager_pid);
|
||||
}
|
||||
|
||||
if (swWaitpid(serv->gs->manager_pid, &status, 0) < 0)
|
||||
{
|
||||
swSysError("waitpid(%d) failed.", serv->gs->manager_pid);
|
||||
}
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static int swFactoryProcess_start(swFactory *factory)
|
||||
{
|
||||
int i;
|
||||
swServer *serv = factory->ptr;
|
||||
swWorker *worker;
|
||||
|
||||
for (i = 0; i < serv->worker_num; i++)
|
||||
{
|
||||
worker = swServer_get_worker(serv, i);
|
||||
if (swWorker_create(worker) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
serv->reactor_pipe_num = serv->worker_num / serv->reactor_num;
|
||||
|
||||
//必须先启动manager进程组,否则会带线程fork
|
||||
if (swManager_start(factory) < 0)
|
||||
{
|
||||
swWarn("swFactoryProcess_manager_start failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
//主进程需要设置为直写模式
|
||||
factory->finish = swFactory_finish;
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static __thread struct
|
||||
{
|
||||
long target_worker_id;
|
||||
swDataHead _send;
|
||||
} sw_notify_data;
|
||||
|
||||
/**
|
||||
* [ReactorThread] notify info to worker process
|
||||
*/
|
||||
static int swFactoryProcess_notify(swFactory *factory, swDataHead *ev)
|
||||
{
|
||||
memcpy(&sw_notify_data._send, ev, sizeof(swDataHead));
|
||||
sw_notify_data._send.len = 0;
|
||||
sw_notify_data.target_worker_id = -1;
|
||||
return factory->dispatch(factory, (swDispatchData *) &sw_notify_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* [ReactorThread] dispatch request to worker
|
||||
*/
|
||||
static int swFactoryProcess_dispatch(swFactory *factory, swDispatchData *task)
|
||||
{
|
||||
uint32_t send_len = sizeof(task->data.info) + task->data.info.len;
|
||||
int target_worker_id;
|
||||
swServer *serv = SwooleG.serv;
|
||||
int fd = task->data.info.fd;
|
||||
|
||||
if (task->target_worker_id < 0)
|
||||
{
|
||||
#ifndef SW_USE_RINGBUFFER
|
||||
if (SwooleTG.factory_lock_target)
|
||||
{
|
||||
if (SwooleTG.factory_target_worker < 0)
|
||||
{
|
||||
target_worker_id = swServer_worker_schedule(serv, fd, &task->data);
|
||||
SwooleTG.factory_target_worker = target_worker_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_worker_id = SwooleTG.factory_target_worker;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
target_worker_id = swServer_worker_schedule(serv, fd, &task->data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_worker_id = task->target_worker_id;
|
||||
}
|
||||
//discard the data packet.
|
||||
if (target_worker_id < 0)
|
||||
{
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
if (swEventData_is_stream(task->data.info.type))
|
||||
{
|
||||
swConnection *conn = swServer_connection_get(serv, fd);
|
||||
if (conn == NULL || conn->active == 0)
|
||||
{
|
||||
swWarn("dispatch[type=%d] failed, connection#%d is not active.", task->data.info.type, fd);
|
||||
return SW_ERR;
|
||||
}
|
||||
//server active close, discard data.
|
||||
if (conn->closed)
|
||||
{
|
||||
//Connection has been clsoed by server
|
||||
if (!(task->data.info.type == SW_EVENT_CLOSE && conn->close_force))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* worker: send to client
|
||||
*/
|
||||
static int swFactoryProcess_finish(swFactory *factory, swSendData *resp)
|
||||
{
|
||||
int ret, sendn;
|
||||
swServer *serv = factory->ptr;
|
||||
int session_id = resp->info.fd;
|
||||
|
||||
swConnection *conn;
|
||||
if (resp->info.type != SW_EVENT_CLOSE)
|
||||
{
|
||||
conn = swServer_connection_verify(serv, session_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
conn = swServer_connection_verify_no_ssl(serv, session_id);
|
||||
}
|
||||
if (!conn)
|
||||
{
|
||||
swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, "connection[fd=%d] does not exists.", session_id);
|
||||
return SW_ERR;
|
||||
}
|
||||
else if ((conn->closed || conn->removed) && resp->info.type != SW_EVENT_CLOSE)
|
||||
{
|
||||
int _len = resp->length > 0 ? resp->length : resp->info.len;
|
||||
swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "send %d byte failed, because connection[fd=%d] is closed.", _len, session_id);
|
||||
return SW_ERR;
|
||||
}
|
||||
else if (conn->overflow)
|
||||
{
|
||||
swoole_error_log(SW_LOG_WARNING, SW_ERROR_OUTPUT_BUFFER_OVERFLOW, "send failed, connection[fd=%d] output buffer has been overflowed.", session_id);
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
swEventData ev_data;
|
||||
ev_data.info.fd = session_id;
|
||||
ev_data.info.type = resp->info.type;
|
||||
swWorker *worker = swServer_get_worker(serv, SwooleWG.id);
|
||||
|
||||
/**
|
||||
* Big response, use shared memory
|
||||
*/
|
||||
if (resp->length > 0)
|
||||
{
|
||||
if (worker == NULL || worker->send_shm == NULL)
|
||||
{
|
||||
goto pack_data;
|
||||
}
|
||||
|
||||
//worker process
|
||||
if (SwooleG.main_reactor)
|
||||
{
|
||||
int _pipe_fd = swWorker_get_send_pipe(serv, session_id, conn->from_id);
|
||||
swConnection *_pipe_socket = swReactor_get(SwooleG.main_reactor, _pipe_fd);
|
||||
|
||||
//cannot use send_shm
|
||||
if (!swBuffer_empty(_pipe_socket->out_buffer))
|
||||
{
|
||||
pack_data:
|
||||
if (swTaskWorker_large_pack(&ev_data, resp->data, resp->length) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
ev_data.info.from_fd = SW_RESPONSE_TMPFILE;
|
||||
goto send_to_reactor_thread;
|
||||
}
|
||||
}
|
||||
|
||||
swPackage_response response;
|
||||
response.length = resp->length;
|
||||
response.worker_id = SwooleWG.id;
|
||||
ev_data.info.from_fd = SW_RESPONSE_SHM;
|
||||
ev_data.info.len = sizeof(response);
|
||||
memcpy(ev_data.data, &response, sizeof(response));
|
||||
|
||||
swTrace("[Worker] big response, length=%d|worker_id=%d", response.length, response.worker_id);
|
||||
|
||||
worker->lock.lock(&worker->lock);
|
||||
memcpy(worker->send_shm, resp->data, resp->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
//copy data
|
||||
memcpy(ev_data.data, resp->data, resp->info.len);
|
||||
|
||||
ev_data.info.len = resp->info.len;
|
||||
ev_data.info.from_fd = SW_RESPONSE_SMALL;
|
||||
}
|
||||
|
||||
send_to_reactor_thread: ev_data.info.from_id = conn->from_id;
|
||||
sendn = ev_data.info.len + sizeof(resp->info);
|
||||
|
||||
swTrace("[Worker] send: sendn=%d|type=%d|content=%s", sendn, resp->info.type, resp->data);
|
||||
ret = swWorker_send2reactor(&ev_data, sendn, session_id);
|
||||
if (ret < 0)
|
||||
{
|
||||
swWarn("sendto to reactor failed. Error: %s [%d]", strerror(errno), errno);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int swFactoryProcess_end(swFactory *factory, int fd)
|
||||
{
|
||||
swServer *serv = factory->ptr;
|
||||
swSendData _send;
|
||||
swDataHead info;
|
||||
|
||||
bzero(&_send, sizeof(_send));
|
||||
_send.info.fd = fd;
|
||||
_send.info.len = 0;
|
||||
_send.info.type = SW_EVENT_CLOSE;
|
||||
|
||||
swConnection *conn = swWorker_get_connection(serv, fd);
|
||||
if (conn == NULL || conn->active == 0)
|
||||
{
|
||||
SwooleG.error = SW_ERROR_SESSION_NOT_EXIST;
|
||||
return SW_ERR;
|
||||
}
|
||||
else if (conn->close_force)
|
||||
{
|
||||
goto do_close;
|
||||
}
|
||||
else if (conn->closing)
|
||||
{
|
||||
swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSING, "The connection[%d] is closing.", fd);
|
||||
return SW_ERR;
|
||||
}
|
||||
else if (conn->closed)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_close:
|
||||
conn->closing = 1;
|
||||
if (serv->onClose != NULL)
|
||||
{
|
||||
info.fd = fd;
|
||||
if (conn->close_actively)
|
||||
{
|
||||
info.from_id = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.from_id = conn->from_id;
|
||||
}
|
||||
info.from_fd = conn->from_fd;
|
||||
serv->onClose(serv, &info);
|
||||
}
|
||||
conn->closing = 0;
|
||||
conn->closed = 1;
|
||||
conn->close_errno = 0;
|
||||
return factory->finish(factory, &_send);
|
||||
}
|
||||
}
|
245
vendor/swoole/src/factory/FactoryThread.c
vendored
Executable file
245
vendor/swoole/src/factory/FactoryThread.c
vendored
Executable file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "Server.h"
|
||||
|
||||
static int swFactoryThread_dispatch(swFactory *factory, swDispatchData *buf);
|
||||
static int swFactoryThread_finish(swFactory *factory, swSendData *data);
|
||||
static int swFactoryThread_shutdown(swFactory *factory);
|
||||
static int swFactoryThread_start(swFactory *factory);
|
||||
|
||||
typedef struct _swWorkerThread
|
||||
{
|
||||
pthread_t ptid; //线程ID
|
||||
int pipe_num; //writer thread's pipe num
|
||||
int *pipes; //worker pipes
|
||||
int c_pipe; //current pipe
|
||||
swReactor reactor;
|
||||
swShareMemory shm; //共享内存
|
||||
swPipe evfd; //eventfd
|
||||
} swWorkerThread;
|
||||
|
||||
typedef struct _swFactoryThread
|
||||
{
|
||||
int worker_num;
|
||||
swThreadPool workers;
|
||||
} swFactoryThread;
|
||||
|
||||
static int swFactoryThread_onTask(swThreadPool *pool, void *data, int len);
|
||||
static void swFactoryThread_onStart(swThreadPool *pool, int id);
|
||||
static void swFactoryThread_onStop(swThreadPool *pool, int id);
|
||||
|
||||
int swFactoryThread_create(swFactory *factory, int worker_num)
|
||||
{
|
||||
swFactoryThread *object;
|
||||
swServer *serv = factory->ptr;
|
||||
|
||||
object = sw_calloc(worker_num, sizeof(swFactoryThread));
|
||||
if (object == NULL)
|
||||
{
|
||||
swWarn("malloc[0] failed");
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
if (swThreadPool_create(&object->workers, worker_num) < 0)
|
||||
{
|
||||
sw_free(object);
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
int i;
|
||||
swReactorThread *thread;
|
||||
for (i = 0; i < serv->reactor_num; i++)
|
||||
{
|
||||
thread = swServer_get_thread(serv, i);
|
||||
swMutex_create(&thread->lock, 0);
|
||||
}
|
||||
|
||||
object->worker_num = worker_num;
|
||||
|
||||
factory->object = object;
|
||||
factory->dispatch = swFactoryThread_dispatch;
|
||||
factory->finish = swFactoryThread_finish;
|
||||
factory->end = swFactory_end;
|
||||
factory->start = swFactoryThread_start;
|
||||
factory->shutdown = swFactoryThread_shutdown;
|
||||
factory->notify = swFactory_notify;
|
||||
|
||||
object->workers.onStart = swFactoryThread_onStart;
|
||||
object->workers.onStop = swFactoryThread_onStop;
|
||||
object->workers.onTask = swFactoryThread_onTask;
|
||||
|
||||
object->workers.ptr1 = factory->ptr;
|
||||
object->workers.ptr2 = factory;
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static int swFactoryThread_start(swFactory *factory)
|
||||
{
|
||||
swFactoryThread *object = factory->object;
|
||||
SwooleWG.run_always = 1;
|
||||
swThreadPool_run(&object->workers);
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static int swFactoryThread_shutdown(swFactory *factory)
|
||||
{
|
||||
SwooleG.running = 0;
|
||||
swFactoryThread *object = factory->object;
|
||||
swThreadPool_free(&object->workers);
|
||||
sw_free(object);
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static int swFactoryThread_finish(swFactory *factory, swSendData *_send)
|
||||
{
|
||||
swServer *serv = SwooleG.serv;
|
||||
uint32_t session_id = _send->info.fd;
|
||||
|
||||
if (_send->length == 0)
|
||||
{
|
||||
_send->length = _send->info.len;
|
||||
}
|
||||
|
||||
swConnection *conn = swServer_connection_verify(serv, session_id);
|
||||
if (!conn)
|
||||
{
|
||||
if (_send->info.type == SW_EVENT_TCP)
|
||||
{
|
||||
swWarn("send %d byte failed, session#%d is closed.", _send->length, session_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
swWarn("send [%d] failed, session#%d is closed.", _send->info.type, session_id);
|
||||
}
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
return swSocket_write_blocking(conn->fd, _send->data, _send->length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写线程模式
|
||||
*/
|
||||
int swFactoryThread_dispatch(swFactory *factory, swDispatchData *task)
|
||||
{
|
||||
swServer *serv = SwooleG.serv;
|
||||
swFactoryThread *object = factory->object;
|
||||
|
||||
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)
|
||||
{
|
||||
swWarn("dispatch[type=%d] failed, connection#%d is closed by server.", task->data.info.type,
|
||||
task->data.info.fd);
|
||||
return SW_OK;
|
||||
}
|
||||
//converted fd to session_id
|
||||
task->data.info.fd = conn->session_id;
|
||||
task->data.info.from_fd = conn->from_fd;
|
||||
}
|
||||
|
||||
int mem_size = sizeof(swDataHead) + task->data.info.len + 1;
|
||||
char *data = sw_malloc(mem_size);
|
||||
if (data == NULL)
|
||||
{
|
||||
swWarn("malloc failed");
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
memcpy(data, &(task->data), mem_size);
|
||||
data[sizeof(swDataHead) + task->data.info.len] = 0;
|
||||
|
||||
if (swThreadPool_dispatch(&object->workers, (void *) data, 0) < 0)
|
||||
{
|
||||
swWarn("RingQueue is full");
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static void swFactoryThread_onStart(swThreadPool *pool, int id)
|
||||
{
|
||||
swServer *serv = pool->ptr1;
|
||||
|
||||
if (serv->onWorkerStart != NULL)
|
||||
{
|
||||
serv->onWorkerStart(serv, id);
|
||||
}
|
||||
|
||||
swSignal_none();
|
||||
|
||||
SwooleTG.id = serv->reactor_num + id;
|
||||
SwooleTG.type = SW_THREAD_WORKER;
|
||||
|
||||
SwooleTG.buffer_input = swServer_create_worker_buffer(serv);
|
||||
if (!SwooleTG.buffer_input)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//cpu affinity setting
|
||||
#ifdef HAVE_CPU_AFFINITY
|
||||
if (serv->open_cpu_affinity)
|
||||
{
|
||||
cpu_set_t cpu_set;
|
||||
CPU_ZERO(&cpu_set);
|
||||
if (serv->cpu_affinity_available_num)
|
||||
{
|
||||
CPU_SET(serv->cpu_affinity_available[id % serv->cpu_affinity_available_num], &cpu_set);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU_SET(id % SW_CPU_NUM, &cpu_set);
|
||||
}
|
||||
if (0 != pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set))
|
||||
{
|
||||
swWarn("pthread_setaffinity_np() failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void swFactoryThread_onStop(swThreadPool *pool, int id)
|
||||
{
|
||||
swServer *serv = SwooleG.serv;
|
||||
|
||||
if (serv->onWorkerStop != NULL)
|
||||
{
|
||||
serv->onWorkerStop(serv, id);
|
||||
}
|
||||
}
|
||||
|
||||
static int swFactoryThread_onTask(swThreadPool *pool, void *data, int len)
|
||||
{
|
||||
swFactory *factory = pool->ptr2;
|
||||
int ret = swWorker_onTask(factory, (swEventData*) data);
|
||||
sw_free(data);
|
||||
return ret;
|
||||
}
|
Reference in New Issue
Block a user