Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

461
vendor/swoole/src/reactor/ReactorBase.c vendored Executable file
View File

@ -0,0 +1,461 @@
/*
+----------------------------------------------------------------------+
| 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 "Connection.h"
#include "async.h"
#include "Server.h"
#ifdef SW_USE_MALLOC_TRIM
#ifdef __APPLE__
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif
#endif
#ifdef SW_COROUTINE
#include "coroutine.h"
#endif
static void swReactor_onTimeout_and_Finish(swReactor *reactor);
static void swReactor_onTimeout(swReactor *reactor);
static void swReactor_onFinish(swReactor *reactor);
static void swReactor_onBegin(swReactor *reactor);
static int swReactor_defer(swReactor *reactor, swCallback callback, void *data);
int swReactor_create(swReactor *reactor, int max_event)
{
int ret;
bzero(reactor, sizeof(swReactor));
#ifdef HAVE_EPOLL
ret = swReactorEpoll_create(reactor, max_event);
#elif defined(HAVE_KQUEUE)
ret = swReactorKqueue_create(reactor, max_event);
#elif defined(HAVE_POLL)
ret = swReactorPoll_create(reactor, max_event);
#else
ret = swReactorSelect_create(reactor);
#endif
reactor->running = 1;
reactor->setHandle = swReactor_setHandle;
reactor->onFinish = swReactor_onFinish;
reactor->onTimeout = swReactor_onTimeout;
reactor->write = swReactor_write;
reactor->defer = swReactor_defer;
reactor->close = swReactor_close;
reactor->socket_array = swArray_new(1024, sizeof(swConnection));
if (!reactor->socket_array)
{
swWarn("create socket array failed.");
return SW_ERR;
}
return ret;
}
int swReactor_setHandle(swReactor *reactor, int _fdtype, swReactor_handle handle)
{
int fdtype = swReactor_fdtype(_fdtype);
if (fdtype >= SW_MAX_FDTYPE)
{
swWarn("fdtype > SW_MAX_FDTYPE[%d]", SW_MAX_FDTYPE);
return SW_ERR;
}
if (swReactor_event_read(_fdtype))
{
reactor->handle[fdtype] = handle;
}
else if (swReactor_event_write(_fdtype))
{
reactor->write_handle[fdtype] = handle;
}
else if (swReactor_event_error(_fdtype))
{
reactor->error_handle[fdtype] = handle;
}
else
{
swWarn("unknow fdtype");
return SW_ERR;
}
return SW_OK;
}
static int swReactor_defer(swReactor *reactor, swCallback callback, void *data)
{
swDefer_callback *cb = sw_malloc(sizeof(swDefer_callback));
if (!cb)
{
swWarn("malloc(%ld) failed.", sizeof(swDefer_callback));
return SW_ERR;
}
cb->callback = callback;
cb->data = data;
LL_APPEND(reactor->defer_callback_list, cb);
return SW_OK;
}
int swReactor_empty(swReactor *reactor)
{
//timer
if (SwooleG.timer.num > 0)
{
return SW_FALSE;
}
int empty = SW_FALSE;
//thread pool
if (SwooleAIO.init && reactor->event_num == 1 && SwooleAIO.task_num == 0)
{
empty = SW_TRUE;
}
//no event
else if (reactor->event_num == 0)
{
empty = SW_TRUE;
}
//coroutine
if (empty && reactor->can_exit && reactor->can_exit(reactor))
{
empty = SW_TRUE;
}
return empty;
}
/**
* execute when reactor timeout and reactor finish
*/
static void swReactor_onTimeout_and_Finish(swReactor *reactor)
{
//check timer
if (reactor->check_timer)
{
swTimer_select(&SwooleG.timer);
}
//defer callback
swDefer_callback *cb, *tmp;
swDefer_callback *defer_callback_list = reactor->defer_callback_list;
reactor->defer_callback_list = NULL;
LL_FOREACH(defer_callback_list, cb)
{
cb->callback(cb->data);
}
LL_FOREACH_SAFE(defer_callback_list, cb, tmp)
{
sw_free(cb);
}
//callback at the end
if (reactor->idle_task.callback)
{
reactor->idle_task.callback(reactor->idle_task.data);
}
#ifdef SW_COROUTINE
//coro timeout
if (!swIsMaster())
{
coro_handle_timeout();
}
#endif
//server worker
swWorker *worker = SwooleWG.worker;
if (worker != NULL)
{
if (SwooleWG.wait_exit == 1)
{
swWorker_try_to_exit();
}
}
//not server, the event loop is empty
if (SwooleG.serv == NULL && swReactor_empty(reactor))
{
reactor->running = 0;
}
#ifdef SW_USE_MALLOC_TRIM
if (SwooleG.serv && reactor->last_malloc_trim_time < SwooleG.serv->gs->now - SW_MALLOC_TRIM_INTERVAL)
{
malloc_trim(SW_MALLOC_TRIM_PAD);
reactor->last_malloc_trim_time = SwooleG.serv->gs->now;
}
#endif
}
static void swReactor_onTimeout(swReactor *reactor)
{
swReactor_onTimeout_and_Finish(reactor);
if (reactor->disable_accept)
{
reactor->enable_accept(reactor);
reactor->disable_accept = 0;
}
}
static void swReactor_onFinish(swReactor *reactor)
{
//check signal
if (reactor->singal_no)
{
swSignal_callback(reactor->singal_no);
reactor->singal_no = 0;
}
swReactor_onTimeout_and_Finish(reactor);
}
void swReactor_activate_future_task(swReactor *reactor)
{
reactor->onBegin = swReactor_onBegin;
}
static void swReactor_onBegin(swReactor *reactor)
{
if (reactor->future_task.callback)
{
reactor->future_task.callback(reactor->future_task.data);
}
}
int swReactor_close(swReactor *reactor, int fd)
{
swConnection *socket = swReactor_get(reactor, fd);
if (socket->out_buffer)
{
swBuffer_free(socket->out_buffer);
}
if (socket->in_buffer)
{
swBuffer_free(socket->in_buffer);
}
if (socket->websocket_buffer)
{
swString_free(socket->websocket_buffer);
}
bzero(socket, sizeof(swConnection));
socket->removed = 1;
swTraceLog(SW_TRACE_CLOSE, "fd=%d.", fd);
return close(fd);
}
int swReactor_write(swReactor *reactor, int fd, void *buf, int n)
{
int ret;
swConnection *socket = swReactor_get(reactor, fd);
swBuffer *buffer = socket->out_buffer;
if (socket->fd == 0)
{
socket->fd = fd;
}
if (socket->buffer_size == 0)
{
socket->buffer_size = SwooleG.socket_buffer_size;
}
if (socket->nonblock == 0)
{
swoole_fcntl_set_option(fd, 1, -1);
socket->nonblock = 1;
}
if (n > socket->buffer_size)
{
swoole_error_log(SW_LOG_WARNING, SW_ERROR_PACKAGE_LENGTH_TOO_LARGE, "data is too large, cannot exceed buffer size.");
return SW_ERR;
}
if (swBuffer_empty(buffer))
{
if (socket->ssl_send)
{
goto do_buffer;
}
do_send:
ret = swConnection_send(socket, buf, n, 0);
if (ret > 0)
{
if (n == ret)
{
return ret;
}
else
{
buf += ret;
n -= ret;
goto do_buffer;
}
}
#ifdef HAVE_KQUEUE
else if (errno == EAGAIN || errno == ENOBUFS)
#else
else if (errno == EAGAIN)
#endif
{
do_buffer:
if (!socket->out_buffer)
{
buffer = swBuffer_new(sizeof(swEventData));
if (!buffer)
{
swWarn("create worker buffer failed.");
return SW_ERR;
}
socket->out_buffer = buffer;
}
socket->events |= SW_EVENT_WRITE;
if (socket->events & SW_EVENT_READ)
{
if (reactor->set(reactor, fd, socket->fdtype | socket->events) < 0)
{
swSysError("reactor->set(%d, SW_EVENT_WRITE) failed.", fd);
}
}
else
{
if (reactor->add(reactor, fd, socket->fdtype | SW_EVENT_WRITE) < 0)
{
swSysError("reactor->add(%d, SW_EVENT_WRITE) failed.", fd);
}
}
goto append_buffer;
}
else if (errno == EINTR)
{
goto do_send;
}
else
{
SwooleG.error = errno;
return SW_ERR;
}
}
else
{
append_buffer: if (buffer->length > socket->buffer_size)
{
if (socket->dontwait)
{
SwooleG.error = SW_ERROR_OUTPUT_BUFFER_OVERFLOW;
return SW_ERR;
}
else
{
swoole_error_log(SW_LOG_WARNING, SW_ERROR_OUTPUT_BUFFER_OVERFLOW, "socket#%d output buffer overflow.", fd);
swYield();
swSocket_wait(fd, SW_SOCKET_OVERFLOW_WAIT, SW_EVENT_WRITE);
}
}
if (swBuffer_append(buffer, buf, n) < 0)
{
return SW_ERR;
}
}
return SW_OK;
}
int swReactor_onWrite(swReactor *reactor, swEvent *ev)
{
int ret;
int fd = ev->fd;
swConnection *socket = swReactor_get(reactor, fd);
swBuffer_trunk *chunk = NULL;
swBuffer *buffer = socket->out_buffer;
//send to socket
while (!swBuffer_empty(buffer))
{
chunk = swBuffer_get_trunk(buffer);
if (chunk->type == SW_CHUNK_CLOSE)
{
close_fd:
reactor->close(reactor, ev->fd);
return SW_OK;
}
else if (chunk->type == SW_CHUNK_SENDFILE)
{
ret = swConnection_onSendfile(socket, chunk);
}
else
{
ret = swConnection_buffer_send(socket);
}
if (ret < 0)
{
if (socket->close_wait)
{
goto close_fd;
}
else if (socket->send_wait)
{
return SW_OK;
}
}
}
//remove EPOLLOUT event
if (swBuffer_empty(buffer))
{
if (socket->events & SW_EVENT_READ)
{
socket->events &= (~SW_EVENT_WRITE);
if (reactor->set(reactor, fd, socket->fdtype | socket->events) < 0)
{
swSysError("reactor->set(%d, SW_EVENT_READ) failed.", fd);
}
}
else
{
if (reactor->del(reactor, fd) < 0)
{
swSysError("reactor->del(%d) failed.", fd);
}
}
}
return SW_OK;
}
int swReactor_wait_write_buffer(swReactor *reactor, int fd)
{
swConnection *conn = swReactor_get(reactor, fd);
swEvent event;
if (conn->out_buffer)
{
swSetBlock(fd);
event.fd = fd;
return swReactor_onWrite(reactor, &event);
}
return SW_OK;
}

304
vendor/swoole/src/reactor/ReactorEpoll.c vendored Executable file
View File

@ -0,0 +1,304 @@
/*
+----------------------------------------------------------------------+
| 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"
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
#ifndef EPOLLRDHUP
#define EPOLLRDHUP 0x2000
#define NO_EPOLLRDHUP
#endif
#ifndef EPOLLONESHOT
#define EPOLLONESHOT (1u << 30)
#endif
typedef struct swReactorEpoll_s swReactorEpoll;
typedef struct _swFd
{
uint32_t fd;
uint32_t fdtype;
} swFd;
static int swReactorEpoll_add(swReactor *reactor, int fd, int fdtype);
static int swReactorEpoll_set(swReactor *reactor, int fd, int fdtype);
static int swReactorEpoll_del(swReactor *reactor, int fd);
static int swReactorEpoll_wait(swReactor *reactor, struct timeval *timeo);
static void swReactorEpoll_free(swReactor *reactor);
static sw_inline int swReactorEpoll_event_set(int fdtype)
{
uint32_t flag = 0;
if (swReactor_event_read(fdtype))
{
flag |= EPOLLIN;
}
if (swReactor_event_write(fdtype))
{
flag |= EPOLLOUT;
}
if (swReactor_event_error(fdtype))
{
//flag |= (EPOLLRDHUP);
flag |= (EPOLLRDHUP | EPOLLHUP | EPOLLERR);
}
return flag;
}
struct swReactorEpoll_s
{
int epfd;
struct epoll_event *events;
};
int swReactorEpoll_create(swReactor *reactor, int max_event_num)
{
//create reactor object
swReactorEpoll *reactor_object = sw_malloc(sizeof(swReactorEpoll));
if (reactor_object == NULL)
{
swWarn("malloc[0] failed.");
return SW_ERR;
}
bzero(reactor_object, sizeof(swReactorEpoll));
reactor->object = reactor_object;
reactor->max_event_num = max_event_num;
reactor_object->events = sw_calloc(max_event_num, sizeof(struct epoll_event));
if (reactor_object->events == NULL)
{
swWarn("malloc[1] failed.");
sw_free(reactor_object);
return SW_ERR;
}
//epoll create
reactor_object->epfd = epoll_create(512);
if (reactor_object->epfd < 0)
{
swWarn("epoll_create failed. Error: %s[%d]", strerror(errno), errno);
sw_free(reactor_object);
return SW_ERR;
}
//binding method
reactor->add = swReactorEpoll_add;
reactor->set = swReactorEpoll_set;
reactor->del = swReactorEpoll_del;
reactor->wait = swReactorEpoll_wait;
reactor->free = swReactorEpoll_free;
return SW_OK;
}
static void swReactorEpoll_free(swReactor *reactor)
{
swReactorEpoll *object = reactor->object;
close(object->epfd);
sw_free(object->events);
sw_free(object);
}
static int swReactorEpoll_add(swReactor *reactor, int fd, int fdtype)
{
swReactorEpoll *object = reactor->object;
struct epoll_event e;
swFd fd_;
bzero(&e, sizeof(struct epoll_event));
fd_.fd = fd;
fd_.fdtype = swReactor_fdtype(fdtype);
e.events = swReactorEpoll_event_set(fdtype);
swReactor_add(reactor, fd, fdtype);
memcpy(&(e.data.u64), &fd_, sizeof(fd_));
if (epoll_ctl(object->epfd, EPOLL_CTL_ADD, fd, &e) < 0)
{
swSysError("add events[fd=%d#%d, type=%d, events=%d] failed.", fd, reactor->id, fd_.fdtype, e.events);
swReactor_del(reactor, fd);
return SW_ERR;
}
swTraceLog(SW_TRACE_EVENT, "add event[reactor_id=%d, fd=%d, events=%d]", reactor->id, fd, swReactor_events(fdtype));
reactor->event_num++;
return SW_OK;
}
static int swReactorEpoll_del(swReactor *reactor, int fd)
{
swReactorEpoll *object = reactor->object;
if (epoll_ctl(object->epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
{
swSysError("epoll remove fd[%d#%d] failed.", fd, reactor->id);
return SW_ERR;
}
swTraceLog(SW_TRACE_REACTOR, "remove event[reactor_id=%d|fd=%d]", reactor->id, fd);
reactor->event_num = reactor->event_num <= 0 ? 0 : reactor->event_num - 1;
swReactor_del(reactor, fd);
return SW_OK;
}
static int swReactorEpoll_set(swReactor *reactor, int fd, int fdtype)
{
swReactorEpoll *object = reactor->object;
swFd fd_;
struct epoll_event e;
int ret;
bzero(&e, sizeof(struct epoll_event));
e.events = swReactorEpoll_event_set(fdtype);
if (e.events & EPOLLOUT)
{
assert(fd > 2);
}
fd_.fd = fd;
fd_.fdtype = swReactor_fdtype(fdtype);
memcpy(&(e.data.u64), &fd_, sizeof(fd_));
ret = epoll_ctl(object->epfd, EPOLL_CTL_MOD, fd, &e);
if (ret < 0)
{
swSysError("reactor#%d->set(fd=%d|type=%d|events=%d) failed.", reactor->id, fd, fd_.fdtype, e.events);
return SW_ERR;
}
swTraceLog(SW_TRACE_EVENT, "set event[reactor_id=%d, fd=%d, events=%d]", reactor->id, fd, swReactor_events(fdtype));
//execute parent method
swReactor_set(reactor, fd, fdtype);
return SW_OK;
}
static int swReactorEpoll_wait(swReactor *reactor, struct timeval *timeo)
{
swEvent event;
swReactorEpoll *object = reactor->object;
swReactor_handle handle;
int i, n, ret, msec;
int reactor_id = reactor->id;
int epoll_fd = object->epfd;
int max_event_num = reactor->max_event_num;
struct epoll_event *events = object->events;
if (reactor->timeout_msec == 0)
{
if (timeo == NULL)
{
reactor->timeout_msec = -1;
}
else
{
reactor->timeout_msec = timeo->tv_sec * 1000 + timeo->tv_usec / 1000;
}
}
reactor->start = 1;
while (reactor->running > 0)
{
if (reactor->onBegin != NULL)
{
reactor->onBegin(reactor);
}
msec = reactor->timeout_msec;
n = epoll_wait(epoll_fd, events, max_event_num, msec);
if (n < 0)
{
if (swReactor_error(reactor) < 0)
{
swWarn("[Reactor#%d] epoll_wait failed. Error: %s[%d]", reactor_id, strerror(errno), errno);
return SW_ERR;
}
else
{
continue;
}
}
else if (n == 0)
{
if (reactor->onTimeout != NULL)
{
reactor->onTimeout(reactor);
}
continue;
}
for (i = 0; i < n; i++)
{
event.fd = events[i].data.u64;
event.from_id = reactor_id;
event.type = events[i].data.u64 >> 32;
event.socket = swReactor_get(reactor, event.fd);
//read
if ((events[i].events & EPOLLIN) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_READ, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("EPOLLIN handle failed. fd=%d.", event.fd);
}
}
//write
if ((events[i].events & EPOLLOUT) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_WRITE, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("EPOLLOUT handle failed. fd=%d.", event.fd);
}
}
//error
#ifndef NO_EPOLLRDHUP
if ((events[i].events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) && !event.socket->removed)
#else
if ((events[i].events & (EPOLLERR | EPOLLHUP)) && !event.socket->removed)
#endif
{
//ignore ERR and HUP, because event is already processed at IN and OUT handler.
if ((events[i].events & EPOLLIN) || (events[i].events & EPOLLOUT))
{
continue;
}
handle = swReactor_getHandle(reactor, SW_EVENT_ERROR, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("EPOLLERR handle failed. fd=%d.", event.fd);
}
}
}
if (reactor->onFinish != NULL)
{
reactor->onFinish(reactor);
}
if (reactor->once)
{
break;
}
}
return 0;
}
#endif

375
vendor/swoole/src/reactor/ReactorKqueue.c vendored Executable file
View File

@ -0,0 +1,375 @@
/*
+----------------------------------------------------------------------+
| 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 <string.h>
#ifdef IDE_HELPER
#ifdef HAVE_KQUEUE
#include <sys/event.h>
#else
#include "helper/kqueue.h"
#define HAVE_KQUEUE
#endif
#else
#ifdef HAVE_KQUEUE
#include <sys/event.h>
#endif
#endif
#ifdef HAVE_KQUEUE
typedef struct swReactorKqueue_s swReactorKqueue;
typedef struct _swFd
{
uint32_t fd;
uint32_t fdtype;
} swFd;
static int swReactorKqueue_add(swReactor *reactor, int fd, int fdtype);
static int swReactorKqueue_set(swReactor *reactor, int fd, int fdtype);
static int swReactorKqueue_del(swReactor *reactor, int fd);
static int swReactorKqueue_wait(swReactor *reactor, struct timeval *timeo);
static void swReactorKqueue_free(swReactor *reactor);
struct swReactorKqueue_s
{
int epfd;
int event_max;
struct kevent *events;
};
int swReactorKqueue_create(swReactor *reactor, int max_event_num)
{
//create reactor object
swReactorKqueue *reactor_object = sw_malloc(sizeof(swReactorKqueue));
if (reactor_object == NULL)
{
swTrace("[swReactorKqueueCreate] malloc[0] fail\n");
return SW_ERR;
}
bzero(reactor_object, sizeof(swReactorKqueue));
reactor->object = reactor_object;
reactor->max_event_num = max_event_num;
reactor_object->events = sw_calloc(max_event_num, sizeof(struct kevent));
if (reactor_object->events == NULL)
{
swTrace("[swReactorKqueueCreate] malloc[1] fail\n");
return SW_ERR;
}
//kqueue create
reactor_object->event_max = max_event_num;
reactor_object->epfd = kqueue();
if (reactor_object->epfd < 0)
{
swTrace("[swReactorKqueueCreate] kqueue_create[0] fail\n");
return SW_ERR;
}
//binding method
reactor->add = swReactorKqueue_add;
reactor->set = swReactorKqueue_set;
reactor->del = swReactorKqueue_del;
reactor->wait = swReactorKqueue_wait;
reactor->free = swReactorKqueue_free;
return SW_OK;
}
static void swReactorKqueue_free(swReactor *reactor)
{
swReactorKqueue *this = reactor->object;
close(this->epfd);
sw_free(this->events);
sw_free(this);
}
static int swReactorKqueue_add(swReactor *reactor, int fd, int fdtype)
{
swReactorKqueue *this = reactor->object;
struct kevent e;
swFd fd_;
int ret;
bzero(&e, sizeof(e));
int fflags = 0;
fd_.fd = fd;
fd_.fdtype = swReactor_fdtype(fdtype);
swReactor_add(reactor, fd, fdtype);
if (swReactor_event_read(fdtype))
{
#ifdef NOTE_EOF
fflags = NOTE_EOF;
#endif
EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, NULL);
memcpy(&e.udata, &fd_, sizeof(swFd));
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("add events[fd=%d#%d, type=%d, events=read] failed.", fd, reactor->id, fd_.fdtype);
swReactor_del(reactor, fd);
return SW_ERR;
}
}
if (swReactor_event_write(fdtype))
{
EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
memcpy(&e.udata, &fd_, sizeof(swFd));
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("add events[fd=%d#%d, type=%d, events=write] failed.", fd, reactor->id, fd_.fdtype);
swReactor_del(reactor, fd);
return SW_ERR;
}
}
swTrace("[THREAD #%d]EP=%d|FD=%d, events=%d", SwooleTG.id, this->epfd, fd, fdtype);
reactor->event_num++;
return SW_OK;
}
static int swReactorKqueue_set(swReactor *reactor, int fd, int fdtype)
{
swReactorKqueue *this = reactor->object;
struct kevent e;
swFd fd_;
int ret;
bzero(&e, sizeof(e));
int fflags = 0;
fd_.fd = fd;
fd_.fdtype = swReactor_fdtype(fdtype);
if (swReactor_event_read(fdtype))
{
#ifdef NOTE_EOF
fflags = NOTE_EOF;
#endif
EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, NULL);
memcpy(&e.udata, &fd_, sizeof(swFd));
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("kqueue->set(%d, SW_EVENT_READ) failed.", fd);
return SW_ERR;
}
}
else
{
EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
memcpy(&e.udata, &fd_, sizeof(swFd));
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("kqueue->del(%d, SW_EVENT_READ) failed.", fd);
return SW_ERR;
}
}
if (swReactor_event_write(fdtype))
{
EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
memcpy(&e.udata, &fd_, sizeof(swFd));
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("kqueue->set(%d, SW_EVENT_WRITE) failed.", fd);
return SW_ERR;
}
}
else
{
EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
memcpy(&e.udata, &fd_, sizeof(swFd));
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("kqueue->del(%d, SW_EVENT_WRITE) failed.", fd);
return SW_ERR;
}
}
swTrace("[THREAD #%d]EP=%d|FD=%d, events=%d", SwooleTG.id, this->epfd, fd, fdtype);
//execute parent method
swReactor_set(reactor, fd, fdtype);
return SW_OK;
}
static int swReactorKqueue_del(swReactor *reactor, int fd)
{
swReactorKqueue *this = reactor->object;
struct kevent e;
int ret;
swConnection *socket = swReactor_get(reactor, fd);
if (socket->events & SW_EVENT_READ)
{
EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("kqueue->del(%d, SW_EVENT_READ) failed.", fd);
return SW_ERR;
}
}
if (socket->events & SW_EVENT_WRITE)
{
EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
if (ret < 0)
{
swSysError("kqueue->del(%d, SW_EVENT_WRITE) failed.", fd);
return SW_ERR;
}
}
swTrace("[THREAD #%d]EP=%d|FD=%d", SwooleTG.id, this->epfd, fd);
reactor->event_num = reactor->event_num <= 0 ? 0 : reactor->event_num - 1;
swReactor_del(reactor, fd);
return SW_OK;
}
static int swReactorKqueue_wait(swReactor *reactor, struct timeval *timeo)
{
swEvent event;
swFd fd_;
swReactorKqueue *object = reactor->object;
swReactor_handle handle;
int i, n, ret;
struct timespec t;
struct timespec *t_ptr;
bzero(&t, sizeof(t));
if (reactor->timeout_msec == 0)
{
if (timeo == NULL)
{
reactor->timeout_msec = -1;
}
else
{
reactor->timeout_msec = timeo->tv_sec * 1000 + timeo->tv_usec / 1000;
}
}
reactor->start = 1;
while (reactor->running > 0)
{
if (reactor->onBegin != NULL)
{
reactor->onBegin(reactor);
}
if (reactor->timeout_msec > 0)
{
t.tv_sec = reactor->timeout_msec / 1000;
t.tv_nsec = (reactor->timeout_msec - t.tv_sec * 1000) * 1000;
t_ptr = &t;
}
else
{
t_ptr = NULL;
}
n = kevent(object->epfd, NULL, 0, object->events, object->event_max, t_ptr);
if (n < 0)
{
swTrace("kqueue error.EP=%d | Errno=%d\n", object->epfd, errno);
if (swReactor_error(reactor) < 0)
{
swWarn("Kqueue[#%d] Error: %s[%d]", reactor->id, strerror(errno), errno);
return SW_ERR;
}
else
{
continue;
}
}
else if (n == 0)
{
if (reactor->onTimeout != NULL)
{
reactor->onTimeout(reactor);
}
continue;
}
for (i = 0; i < n; i++)
{
swTrace("n %d events.", n);
if (object->events[i].udata)
{
memcpy(&fd_, &(object->events[i].udata), sizeof(fd_));
event.fd = fd_.fd;
event.from_id = reactor->id;
event.type = fd_.fdtype;
event.socket = swReactor_get(reactor, event.fd);
//read
if (object->events[i].filter == EVFILT_READ)
{
if (event.socket->removed)
{
continue;
}
handle = swReactor_getHandle(reactor, SW_EVENT_READ, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("kqueue event read socket#%d handler failed.", event.fd);
}
}
//write
else if (object->events[i].filter == EVFILT_WRITE)
{
if (event.socket->removed)
{
continue;
}
handle = swReactor_getHandle(reactor, SW_EVENT_WRITE, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("kqueue event write socket#%d handler failed.", event.fd);
}
}
else
{
swWarn("unknown event filter[%d].", object->events[i].filter);
}
}
}
if (reactor->onFinish != NULL)
{
reactor->onFinish(reactor);
}
if (reactor->once)
{
break;
}
}
return 0;
}
#endif

306
vendor/swoole/src/reactor/ReactorPoll.c vendored Executable file
View File

@ -0,0 +1,306 @@
/*
+----------------------------------------------------------------------+
| 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 <poll.h>
static int swReactorPoll_add(swReactor *reactor, int fd, int fdtype);
static int swReactorPoll_set(swReactor *reactor, int fd, int fdtype);
static int swReactorPoll_del(swReactor *reactor, int fd);
static int swReactorPoll_wait(swReactor *reactor, struct timeval *timeo);
static void swReactorPoll_free(swReactor *reactor);
static int swReactorPoll_exist(swReactor *reactor, int fd);
typedef struct _swPollFdInfo
{
int fdtype;
} swPollFdInfo;
typedef struct _swReactorPoll
{
int max_fd_num;
swPollFdInfo *fds;
struct pollfd *events;
} swReactorPoll;
int swReactorPoll_create(swReactor *reactor, int max_fd_num)
{
//create reactor object
swReactorPoll *object = sw_malloc(sizeof(swReactorPoll));
if (object == NULL)
{
swWarn("malloc[0] failed");
return SW_ERR;
}
bzero(object, sizeof(swReactorPoll));
object->fds = sw_calloc(max_fd_num, sizeof(swPollFdInfo));
if (object->fds == NULL)
{
swWarn("malloc[1] failed");
sw_free(object);
return SW_ERR;
}
object->events = sw_calloc(max_fd_num, sizeof(struct pollfd));
if (object->events == NULL)
{
swWarn("malloc[2] failed");
sw_free(object);
return SW_ERR;
}
object->max_fd_num = max_fd_num;
reactor->max_event_num = max_fd_num;
bzero(reactor->handle, sizeof(reactor->handle));
reactor->object = object;
//binding method
reactor->add = swReactorPoll_add;
reactor->del = swReactorPoll_del;
reactor->set = swReactorPoll_set;
reactor->wait = swReactorPoll_wait;
reactor->free = swReactorPoll_free;
return SW_OK;
}
static void swReactorPoll_free(swReactor *reactor)
{
swReactorPoll *object = reactor->object;
sw_free(object->fds);
sw_free(reactor->object);
}
static int swReactorPoll_add(swReactor *reactor, int fd, int fdtype)
{
if (swReactorPoll_exist(reactor, fd))
{
swWarn("fd#%d is already exists.", fd);
return SW_ERR;
}
swReactorPoll *object = reactor->object;
int cur = reactor->event_num;
if (reactor->event_num == object->max_fd_num)
{
swWarn("too many connection, more than %d", object->max_fd_num);
return SW_ERR;
}
swReactor_add(reactor, fd, fdtype);
swTrace("fd=%d, fdtype=%d", fd, fdtype);
object->fds[cur].fdtype = swReactor_fdtype(fdtype);
object->events[cur].fd = fd;
object->events[cur].events = 0;
if (swReactor_event_read(fdtype))
{
object->events[cur].events |= POLLIN;
}
if (swReactor_event_write(fdtype))
{
object->events[cur].events |= POLLOUT;
}
if (swReactor_event_error(fdtype))
{
object->events[cur].events |= POLLHUP;
}
reactor->event_num++;
return SW_OK;
}
static int swReactorPoll_set(swReactor *reactor, int fd, int fdtype)
{
uint32_t i;
swReactorPoll *object = reactor->object;
swTrace("fd=%d, fdtype=%d", fd, fdtype);
for (i = 0; i < reactor->event_num; i++)
{
//found
if (object->events[i].fd == fd)
{
object->fds[i].fdtype = swReactor_fdtype(fdtype);
//object->events[i].events = POLLRDHUP;
object->events[i].events = 0;
if (swReactor_event_read(fdtype))
{
object->events[i].events |= POLLIN;
}
if (swReactor_event_write(fdtype))
{
object->events[i].events |= POLLOUT;
}
//execute parent method
swReactor_set(reactor, fd, fdtype);
return SW_OK;
}
}
return SW_ERR;
}
static int swReactorPoll_del(swReactor *reactor, int fd)
{
uint32_t i;
swReactorPoll *object = reactor->object;
for (i = 0; i < reactor->event_num; i++)
{
if (object->events[i].fd == fd)
{
uint32_t old_num = reactor->event_num;
reactor->event_num = reactor->event_num <= 0 ? 0 : reactor->event_num - 1;
for (; i < old_num; i++)
{
if (i == old_num)
{
object->fds[i].fdtype = 0;
object->events[i].fd = 0;
object->events[i].events = 0;
}
else
{
object->fds[i] = object->fds[i + 1];
object->events[i] = object->events[i + 1];
}
}
swReactor_del(reactor, fd);
return SW_OK;
}
}
return SW_ERR;
}
static int swReactorPoll_wait(swReactor *reactor, struct timeval *timeo)
{
swReactorPoll *object = reactor->object;
swEvent event;
swReactor_handle handle;
int ret, msec, i;
if (reactor->timeout_msec == 0)
{
if (timeo == NULL)
{
reactor->timeout_msec = -1;
}
else
{
reactor->timeout_msec = timeo->tv_sec * 1000 + timeo->tv_usec / 1000;
}
}
reactor->start = 1;
while (reactor->running > 0)
{
if (reactor->onBegin != NULL)
{
reactor->onBegin(reactor);
}
msec = reactor->timeout_msec;
ret = poll(object->events, reactor->event_num, msec);
if (ret < 0)
{
if (swReactor_error(reactor) < 0)
{
swWarn("poll error. Error: %s[%d]", strerror(errno), errno);
}
continue;
}
else if (ret == 0)
{
if (reactor->onTimeout != NULL)
{
reactor->onTimeout(reactor);
}
continue;
}
else
{
for (i = 0; i < reactor->event_num; i++)
{
event.fd = object->events[i].fd;
event.from_id = reactor->id;
event.type = object->fds[i].fdtype;
event.socket = swReactor_get(reactor, event.fd);
swTrace("Event: fd=%d|from_id=%d|type=%d", event.fd, reactor->id, object->fds[i].fdtype);
//in
if ((object->events[i].revents & POLLIN) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_READ, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swWarn("poll[POLLIN] handler failed. fd=%d. Error: %s[%d]", event.fd, strerror(errno), errno);
}
}
//out
if ((object->events[i].revents & POLLOUT) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_WRITE, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swWarn("poll[POLLOUT] handler failed. fd=%d. Error: %s[%d]", event.fd, strerror(errno), errno);
}
}
//error
if ((object->events[i].revents & (POLLHUP | POLLERR)) && !event.socket->removed)
{
//ignore ERR and HUP, because event is already processed at IN and OUT handler.
if ((object->events[i].revents & POLLIN) || (object->events[i].revents & POLLOUT))
{
continue;
}
handle = swReactor_getHandle(reactor, SW_EVENT_ERROR, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swWarn("poll[POLLERR] handler failed. fd=%d. Error: %s[%d]", event.fd, strerror(errno), errno);
}
}
}
}
if (reactor->onFinish != NULL)
{
reactor->onFinish(reactor);
}
if (reactor->once)
{
break;
}
}
return SW_OK;
}
static int swReactorPoll_exist(swReactor *reactor, int fd)
{
swReactorPoll *object = reactor->object;
int i;
for (i = 0; i < reactor->event_num; i++)
{
if (object->events[i].fd == fd )
{
return SW_TRUE;
}
}
return SW_FALSE;
}

286
vendor/swoole/src/reactor/ReactorSelect.c vendored Executable file
View File

@ -0,0 +1,286 @@
/*
+----------------------------------------------------------------------+
| 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 <sys/select.h>
typedef struct _swFdList_node
{
struct _swFdList_node *next, *prev;
int fd;
int fdtype;
} swFdList_node;
typedef struct _swReactorSelect
{
fd_set rfds;
fd_set wfds;
fd_set efds;
swFdList_node *fds;
int maxfd;
} swReactorSelect;
#define SW_FD_SET(fd, set) do{ if (fd<FD_SETSIZE) FD_SET(fd, set);} while(0)
#define SW_FD_CLR(fd, set) do{ if (fd<FD_SETSIZE) FD_CLR(fd, set);} while(0)
#define SW_FD_ISSET(fd, set) ((fd < FD_SETSIZE) && FD_ISSET(fd, set))
static int swReactorSelect_add(swReactor *reactor, int fd, int fdtype);
static int swReactorSelect_wait(swReactor *reactor, struct timeval *timeo);
static void swReactorSelect_free(swReactor *reactor);
static int swReactorSelect_del(swReactor *reactor, int fd);
static int swReactorSelect_set(swReactor *reactor, int fd, int fdtype);
static int swReactorSelect_cmp(swFdList_node *a, swFdList_node *b);
int swReactorSelect_create(swReactor *reactor)
{
//create reactor object
swReactorSelect *object = sw_malloc(sizeof(swReactorSelect));
if (object == NULL)
{
swWarn("[swReactorSelect_create] malloc[0] fail\n");
return SW_ERR;
}
bzero(object, sizeof(swReactorSelect));
object->fds = NULL;
object->maxfd = 0;
bzero(reactor->handle, sizeof(reactor->handle));
reactor->object = object;
//binding method
reactor->add = swReactorSelect_add;
reactor->set = swReactorSelect_set;
reactor->del = swReactorSelect_del;
reactor->wait = swReactorSelect_wait;
reactor->free = swReactorSelect_free;
return SW_OK;
}
void swReactorSelect_free(swReactor *reactor)
{
swReactorSelect *object = reactor->object;
swFdList_node *ev, *tmp;
LL_FOREACH_SAFE(object->fds, ev, tmp)
{
LL_DELETE(object->fds, ev);
sw_free(ev);
}
sw_free(reactor->object);
}
int swReactorSelect_add(swReactor *reactor, int fd, int fdtype)
{
if (fd > FD_SETSIZE)
{
swWarn("max fd value is FD_SETSIZE(%d).\n", FD_SETSIZE);
return SW_ERR;
}
swReactorSelect *object = reactor->object;
swFdList_node *ev = sw_malloc(sizeof(swFdList_node));
if (ev == NULL)
{
swWarn("malloc(%ld) failed.", sizeof(swFdList_node));
return SW_ERR;
}
swReactor_add(reactor, fd, fdtype);
ev->fd = fd;
ev->fdtype = fdtype;
LL_APPEND(object->fds, ev);
reactor->event_num++;
if (fd > object->maxfd)
{
object->maxfd = fd;
}
return SW_OK;
}
static int swReactorSelect_cmp(swFdList_node *a, swFdList_node *b)
{
return a->fd == b->fd ? 0 : (a->fd > b->fd ? -1 : 1);
}
int swReactorSelect_del(swReactor *reactor, int fd)
{
swReactorSelect *object = reactor->object;
swFdList_node ev, *s_ev = NULL;
ev.fd = fd;
LL_SEARCH(object->fds, s_ev, &ev, swReactorSelect_cmp);
if (s_ev == NULL)
{
swWarn("swReactorSelect: fd[%d] not found", fd);
return SW_ERR;
}
LL_DELETE(object->fds, s_ev);
SW_FD_CLR(fd, &object->rfds);
SW_FD_CLR(fd, &object->wfds);
SW_FD_CLR(fd, &object->efds);
reactor->event_num = reactor->event_num <= 0 ? 0 : reactor->event_num - 1;
sw_free(s_ev);
swReactor_del(reactor, fd);
return SW_OK;
}
int swReactorSelect_set(swReactor *reactor, int fd, int fdtype)
{
swReactorSelect *object = reactor->object;
swFdList_node ev, *s_ev = NULL;
ev.fd = fd;
LL_SEARCH(object->fds, s_ev, &ev, swReactorSelect_cmp);
if (s_ev == NULL)
{
swWarn("swReactorSelect: sock[%d] not found.", fd);
return SW_ERR;
}
s_ev->fdtype = fdtype;
//execute parent method
swReactor_set(reactor, fd, fdtype);
return SW_OK;
}
int swReactorSelect_wait(swReactor *reactor, struct timeval *timeo)
{
swReactorSelect *object = reactor->object;
swFdList_node *ev;
swFdList_node *tmp;
swEvent event;
swReactor_handle handle;
struct timeval timeout;
int ret;
if (reactor->timeout_msec == 0)
{
if (timeo == NULL)
{
reactor->timeout_msec = -1;
}
else
{
reactor->timeout_msec = timeo->tv_sec * 1000 + timeo->tv_usec / 1000;
}
}
reactor->start = 1;
while (reactor->running > 0)
{
FD_ZERO(&(object->rfds));
FD_ZERO(&(object->wfds));
FD_ZERO(&(object->efds));
if (reactor->onBegin != NULL)
{
reactor->onBegin(reactor);
}
LL_FOREACH(object->fds, ev)
{
if (swReactor_event_read(ev->fdtype))
{
SW_FD_SET(ev->fd, &(object->rfds));
}
if (swReactor_event_write(ev->fdtype))
{
SW_FD_SET(ev->fd, &(object->wfds));
}
if (swReactor_event_error(ev->fdtype))
{
SW_FD_SET(ev->fd, &(object->efds));
}
}
if (reactor->timeout_msec < 0)
{
timeout.tv_sec = SW_MAX_UINT;
timeout.tv_usec = 0;
}
else
{
timeout.tv_sec = reactor->timeout_msec / 1000;
timeout.tv_usec = reactor->timeout_msec - timeout.tv_sec * 1000;
}
ret = select(object->maxfd + 1, &(object->rfds), &(object->wfds), &(object->efds), &timeout);
if (ret < 0)
{
if (swReactor_error(reactor) < 0)
{
swWarn("select error. Error: %s[%d]", strerror(errno), errno);
}
continue;
}
else if (ret == 0)
{
if (reactor->onTimeout != NULL)
{
reactor->onTimeout(reactor);
}
continue;
}
else
{
LL_FOREACH_SAFE(object->fds, ev, tmp)
{
event.fd = ev->fd;
event.from_id = reactor->id;
event.type = swReactor_fdtype(ev->fdtype);
event.socket = swReactor_get(reactor, event.fd);
//read
if (SW_FD_ISSET(event.fd, &(object->rfds)) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_READ, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("[Reactor#%d] select event[type=READ, fd=%d] handler fail.", reactor->id, event.fd);
}
}
//write
if (SW_FD_ISSET(event.fd, &(object->wfds)) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_WRITE, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("[Reactor#%d] select event[type=WRITE, fd=%d] handler fail.", reactor->id, event.fd);
}
}
//error
if (SW_FD_ISSET(event.fd, &(object->efds)) && !event.socket->removed)
{
handle = swReactor_getHandle(reactor, SW_EVENT_ERROR, event.type);
ret = handle(reactor, &event);
if (ret < 0)
{
swSysError("[Reactor#%d] select event[type=ERROR, fd=%d] handler fail.", reactor->id, event.fd);
}
}
}
}
if (reactor->onFinish != NULL)
{
reactor->onFinish(reactor);
}
if (reactor->once)
{
break;
}
}
return SW_OK;
}