# HG changeset patch # User Igor Sysoev # Date 1040624962 0 # Node ID c14d7232b11f7a37b47156967122736b4cfb83e2 # Parent 79c1fce18e710388cc8a01049b10c76b1ba03b8f nginx-0.0.1-2002-12-23-09:29:22 import diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -39,6 +39,9 @@ ngx_array_t *ngx_listening_sockets; int main(int argc, char *const *argv) { + ngx_str_t conf_file; + ngx_conf_t conf; + /* STUB */ ngx_log.log_level = NGX_LOG_DEBUG; @@ -53,6 +56,19 @@ int main(int argc, char *const *argv) /* TODO: read config */ +#if 1 + ngx_memzero(&conf, sizeof(ngx_conf_t)); + ngx_test_null(conf.args, + ngx_create_array(ngx_pool, 10, sizeof(ngx_str_t)), 1); + conf.pool = ngx_pool; + conf.log = &ngx_log; + + conf_file.len = sizeof("nginx.conf") - 1; + conf_file.data = "nginx.conf"; + + ngx_conf_parse(&conf, &conf_file); +#endif + ngx_test_null(ngx_listening_sockets, ngx_create_array(ngx_pool, 10, sizeof(ngx_listen_t)), 1); diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -9,6 +9,8 @@ ngx_inline inline __inline __inline__ */ +/* STUB */ +#undef FD_SETSIZE #define FD_SETSIZE 1024 @@ -85,6 +87,11 @@ #include #include +#ifndef HAVE_POLL +#define HAVE_POLL 1 +#include +#endif + #define ngx_inline inline diff --git a/src/core/ngx_config_file.c b/src/core/ngx_config_file.c --- a/src/core/ngx_config_file.c +++ b/src/core/ngx_config_file.c @@ -12,9 +12,9 @@ static int argument_number[] = { NGX_CONF_TAKE2 }; -#if 0 +#if 1 -int ngx_conf_parse(ngx_conf_t *cf, char *filename) +int ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { int rc; char *error; @@ -23,22 +23,34 @@ int ngx_conf_parse(ngx_conf_t *cf, char if (filename) { - fd = ngx_open_file(filename, NGX_FILE_RDONLY); + fd = ngx_open_file(filename->data, NGX_FILE_RDONLY); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, - "ngx_conf_open: " - ngx_open_file_n " %s failed", filename); + "ngx_conf_file: " + ngx_open_file_n " %s failed", filename->data); return NGX_ERROR; } - prev = cf->file; - ngx_test_null(cf->file, ngx_palloc(cf->pool, sizeof(ngx_conf_file_t)), + prev = cf->conf_file; + ngx_test_null(cf->conf_file, + ngx_palloc(cf->pool, sizeof(ngx_conf_file_t)), NGX_ERROR); - cf->file->fd = fd; - cf->file->name = filename; - cf->file->line = 1; - cf->file->pos = 0; + if (ngx_stat_fd(fd, &cf->conf_file->file.info) == -1) { + ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, + "ngx_conf_file: " + ngx_stat_fd_n " %s failed", filename->data); + } + + ngx_test_null(cf->conf_file->hunk, + ngx_create_temp_hunk(cf->pool, 1024, 0, 0), + NGX_ERROR); + + cf->conf_file->file.fd = fd; + cf->conf_file->file.name.len = filename->len; + cf->conf_file->file.name.data = filename->data; + cf->conf_file->file.log = cf->log;; + cf->conf_file->line = 1; } for ( ;; ) { @@ -56,13 +68,14 @@ int ngx_conf_parse(ngx_conf_t *cf, char if (cf->handler) { - if (*(cf->handler)(cf) == NGX_ERROR) { + if ((*cf->handler)(cf) == NGX_ERROR) { return NGX_ERROR; } continue; } +#if 0 cmd = ngx_conf_find_token(cf); if (cmd == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, @@ -71,7 +84,7 @@ int ngx_conf_parse(ngx_conf_t *cf, char return NGX_ERROR; } - if (cmd->type & argument_number[cf->args->nelts]) { + if (cmd->type & argument_number[cf->args->nelts - 1]) { error = cmd->set(cf, cmd->offset, cf->args); if (error) { @@ -81,6 +94,7 @@ int ngx_conf_parse(ngx_conf_t *cf, char return NGX_ERROR; } } +#endif #if 0 if (cmd->type == NGX_CONF_CONTAINER) { @@ -133,32 +147,36 @@ int ngx_conf_parse(ngx_conf_t *cf, char cf->name, cf->file->name, cf->file->line); return NGX_ERROR; } +#endif } -#endif if (filename) { - cf->file = prev; + cf->conf_file = prev; if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, ngx_errno, - ngx_close_file_n " %s failed", cf->name); + ngx_close_file_n " %s failed", + cf->conf_file->file.name.data); return NGX_ERROR; } } return NGX_OK; -} +} #endif -#if 0 +#if 1 int ngx_conf_read_token(ngx_conf_t *cf) { char *start, ch, *src, *dst; - int n, need_space, last_space, len, quoted, s_quoted, d_quoted; + int found, need_space, last_space, len, quoted, s_quoted, d_quoted; + ssize_t n; + ngx_str_t *word; ngx_hunk_t *h; + found = 0; need_space = 0; last_space = 1; len = 0; @@ -167,14 +185,21 @@ int ngx_conf_read_token(ngx_conf_t *cf) cf->args->nelts = 0; h = cf->conf_file->hunk; - for (start = h->pos.mem; /* end_of_file */ ; h->pos.mem++) { +ngx_log_debug(cf->log, "TOKEN START"); + + for (start = h->pos.mem; /* void */ ; /* void */) { if (h->pos.mem >= h->last.mem) { + if (cf->conf_file->file.offset + >= ngx_file_size(cf->conf_file->file.info)) { + return NGX_FILE_DONE; + } + if (h->pos.mem - start) { ngx_memcpy(h->start, start, h->pos.mem - start); } - n = ngx_read_file(cf->conf_file->file, + n = ngx_read_file(&cf->conf_file->file, h->start + (h->pos.mem - start), h->end - (h->start + (h->pos.mem - start)), cf->conf_file->file.offset); @@ -188,12 +213,30 @@ int ngx_conf_read_token(ngx_conf_t *cf) h->last.mem = h->pos.mem + n; } - ch = *h->pos.mem; + ch = *h->pos.mem++; + +ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _ + last_space _ need_space _ + quoted _ s_quoted _ d_quoted _ ch); if (ch == LF) { cf->conf_file->line++; } + if (need_space) { + if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { + last_space = 1; + need_space = 0; + continue; + } + + if (ch == ';' || ch == '{') { + return NGX_OK; + } + + return NGX_ERROR; + } + if (quoted) { quoted = 0; continue; @@ -202,86 +245,93 @@ int ngx_conf_read_token(ngx_conf_t *cf) len++; if (last_space) { - start = h->pos.mem; - if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { - start++; - continue; - } - } - - if (ch = '\\') { - quoted = 1; - continue; - } - - if (d_quoted) { - - if (ch == '"') { - d_quoted = 0; - need_space = 1; - last_space = 1; + len = 0; continue; } - } else if (s_quoted) { + start = h->pos.mem - 1; + + switch (ch) { + + case '\\': + quoted = 1; + last_space = 0; + continue; - if (ch == '\'') { - s_quoted = 0; - need_space = 1; - last_space = 1; + case '"': + start++; + len--; + d_quoted = 1; + last_space = 0; continue; + + case '\'': + start++; + len--; + s_quoted = 1; + last_space = 0; + continue; + + default: + last_space = 0; } } else { + if (ch == '\\') { + quoted = 1; + continue; + } - if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { + if (d_quoted) { + if (ch == '"') { + len--; + d_quoted = 0; + need_space = 1; + found = 1; + } + + } else if (s_quoted) { + if (ch == '\'') { + len--; + s_quoted = 0; + need_space = 1; + found = 1; + } + + } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF + || ch == ';' || ch == '{') { + len--; + last_space = 1; + found = 1; + } + + if (found) { ngx_test_null(word, ngx_push_array(cf->args), NGX_ERROR); - ngx_test_null(word->data, ngx_palloc(cf->temp_pool, len + 1), + ngx_test_null(word->data, ngx_palloc(cf->pool, len + 1), NGX_ERROR); word->len = len; - for (dst = word->data, src = start; src < h->pos; /* void */) { - if (*src == '\\') + for (dst = word->data, src = start; + src < h->pos.mem - 1; + /* void */) + { + if (*src == '\\') { src++; + } *dst++ = *src++; } *dst = '\0'; - need_space = 0; - last_space = 1; - continue; - } - - if (need_space) { - return NGX_ERROR; - } - - if (ch == ';') { - return NGX_OK; - } +ngx_log_debug(cf->log, "FOUND %d:'%s'" _ word->len _ word->data); - if (ch == '{') { - return NGX_OK; - } - - if (ch == '}') { - return NGX_BLOCK_DONE; - } - - if (last_space) { - if (ch == '"') { - d_quoted = 1; - continue; + if (ch == ';' || ch == '{') { + return NGX_OK; } - if (ch == '\'') { - s_quoted = 1; - continue; - } + found = 0; + len = 0; } - - last_space = 0; } } } diff --git a/src/core/ngx_config_file.h b/src/core/ngx_config_file.h --- a/src/core/ngx_config_file.h +++ b/src/core/ngx_config_file.h @@ -19,6 +19,10 @@ #define NGX_CONF_UNSET -1 +#define NGX_BLOCK_DONE 1 +#define NGX_FILE_DONE 2 + + typedef struct { ngx_file_t file; ngx_hunk_t *hunk; diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -44,12 +45,9 @@ void ngx_log_error_core(int level, ngx_l len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1, " [%s] ", err_levels[level]); + /* pid#tid */ len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1, -#if (WIN32) - "%d#%d: ", 0, 0); -#else - "%d#%d: ", getpid(), 0); -#endif + "%d#%d: ", ngx_getpid(), 0); #if (HAVE_VARIADIC_MACROS) va_start(args, fmt); @@ -60,12 +58,14 @@ void ngx_log_error_core(int level, ngx_l #endif if (err) { - if ((unsigned) err < 0x80000000) +#if (WIN32) + if ((unsigned) err >= 0x80000000) len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1, - " (%d: ", err); + " (%X: ", err); else +#endif len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1, - " (%X: ", err); + " (%d: ", err); len += ngx_strerror_r(err, errstr + len, sizeof(errstr) - len - 1); if (len < sizeof(errstr) - 2) { @@ -75,16 +75,26 @@ void ngx_log_error_core(int level, ngx_l } } - if (level != NGX_LOG_DEBUG && log->handler) + if (level != NGX_LOG_DEBUG && log->handler) { len += log->handler(log->data, errstr + len, sizeof(errstr) - len - 1); + } + + if (len > sizeof(errstr) - 2) { + len = sizeof(errstr) - 2; + } - if (len > sizeof(errstr) - 2) - len = sizeof(errstr) - 2; - errstr[len] = '\n'; - errstr[len + 1] = '\0'; +#if (WIN32) + errstr[len++] = '\r'; +#endif + errstr[len++] = '\n'; + write(2, errstr, len); + +#if 0 + errstr[len] = '\0'; fputs(errstr, stderr); fflush(stderr); +#endif } #if !(HAVE_VARIADIC_MACROS) diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c new file mode 100644 --- /dev/null +++ b/src/event/modules/ngx_devpoll_module.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2002 Igor Sysoev, http://sysoev.ru + */ + + +#include +#include +#include +#include +#include +#include +#include + +#if (USE_DEVPOLL) && !(HAVE_DEVPOLL) +#error "/dev/poll is not supported on this platform" +#endif + + +/* should be per-thread */ +static int dp; +static struct pollfd *change_list, *event_list; +static int nchanges, nevents; + +static ngx_event_t timer_queue; +/* */ + + +int ngx_devpoll_init(int max_connections, ngx_log_t *log) +{ + int size; + + size = sizeof(struct pollfd) * 512; + nchanges = 0; + nevents = 512; + + dp = open("/dev/poll", O_RDWR); + + if (dp == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(/dev/poll) failed"); + return NGX_ERROR; + } + + ngx_test_null(change_list, ngx_alloc(size, log), NGX_ERROR); + ngx_test_null(event_list, ngx_alloc(size, log), NGX_ERROR); + ngx_test_null(event_index, ngx_alloc(sizeof(ngx_event_t *) * nevents, log), + NGX_ERROR); + + timer_queue.timer_prev = &timer_queue; + timer_queue.timer_next = &timer_queue; + +#if !(USE_DEVPOLL) + ngx_event_actions.add = ngx_devpoll_add_event; + ngx_event_actions.del = ngx_devpoll_del_event; + ngx_event_actions.timer = ngx_devpoll_add_timer; + ngx_event_actions.process = ngx_devpoll_process_events; +#endif + + return NGX_OK; +} + + +/* NOT READY */ + +int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_event_t *e; + ngx_connection_t *c; + + c = (ngx_connection_t *) ev->data; + + ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; + + if (event == NGX_READ_EVENT) { + e = c->write; +#if (NGX_READ_EVENT != POLLIN) + event = POLLIN; +#endif + + } else { + e = c->read; +#if (NGX_WRITE_EVENT != POLLOUT) + event = POLLOUT; +#endif + } + + ngx_log_debug(ev->log, "poll fd:%d event:%d" _ c->fd _ event); + + if (e == NULL || e->index == NGX_INVALID_INDEX) { + event_list[nevents].fd = c->fd; + event_list[nevents].events = event; + event_list[nevents].revents = 0; + + event_index[nevents] = ev; + ev->index = nevents; + nevents++; + + } else { + event_list[e->index].events |= event; + ev->index = e->index; + } + + return ngx_devpoll_set_event(ev, event, EV_ADD | flags); +} + +/* NOT READY */ + +int ngx_devpoll_del_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_event_t *e; + + if (nchanges > 0 && ev->index < nchanges + && change_list[ev->index].udata == ev) + { + ngx_connection_t *cn = (ngx_connection_t *) ev->data; + ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ + cn->fd _ event); + + if (ev->index < --nchanges) { + e = (ngx_event_t *) change_list[nchanges].udata; + change_list[ev->index] = change_list[nchanges]; + e->index = ev->index; + } + + return NGX_OK; + } + + if (flags & NGX_CLOSE_EVENT) + return NGX_OK; + + return ngx_devpoll_set_event(ev, POLLREMOVE); +} + +/* NOT READY */ + +int ngx_devpoll_set_event(ngx_event_t *ev, int event) +{ + int n; + ngx_connection_t *c; + + c = (ngx_connection_t *) ev->data; + + ngx_log_debug(ev->log, "devpoll fd:%d event:%d" _ c->fd _ event); + + if (nchanges >= nevents) { + ngx_log_error(NGX_LOG_WARN, ev->log, 0, + "/dev/pool change list is filled up"); + + n = nchanges * sizeof(struct pollfd); + if (write(dp, change_list, n) != n) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "write(/dev/poll) failed"); + return NGX_ERROR; + } + + nchanges = 0; + } + + event_list[nchanges].fd = c->fd; + event_list[nchanges].events = event; + event_list[nchanges].revents = 0; + + event_index[nchanges] = ev; + ev->index = nchanges; + +/* + if (flags == EV_ADD) + ev->index = nchanges; +*/ + + nchanges++; + + return NGX_OK; +} + + +int ngx_devpoll_process_events(ngx_log_t *log) +{ + int events, i; + u_int timer, delta; + ngx_event_t *ev; + struct dvpoll dvpoll; + struct timeval tv; + + if (timer_queue.timer_next != &timer_queue) { + timer = timer_queue.timer_next->timer_delta; +#if 1 + gettimeofday(&tv, NULL); + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; +#else + delta = ngx_msec(); +#endif + + } else { + timer = INFTIM; + delta = 0; + } + + ngx_log_debug(log, "devpoll timer: %d" _ timer); + + n = nchanges * sizeof(struct pollfd); + if (write(dp, change_list, n) != n) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "write(/dev/poll) failed"); + return NGX_ERROR; + } + + dvpoll.dp_fds = event_list; + dvpoll.dp_nfds = nevents; + dvpoll.dp_timeout = timer; + events = ioctl(dp, DP_POLL, &dvpoll); + + if (events == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "ioctl(DP_POLL) failed"); + return NGX_ERROR; + } + + nchanges = 0; + + if (timer != INFTIM) { +#if 1 + gettimeofday(&tv, NULL); + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; +#else + delta = ngx_msec() - delta; +#endif + + } else { + ngx_assert((events != 0), return NGX_ERROR, log, + "ioctl(DP_POLL) returns no events without timeout"); + } + + ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ delta); + + if (timer != INFTIM) { + if (delta >= timer) { + for ( ;; ) { + ev = timer_queue.timer_next; + + if (ev == &timer_queue || delta < ev->timer_delta) + break; + + delta -= ev->timer_delta; + ngx_del_timer(ev); + ev->timedout = 1; + if (ev->event_handler(ev) == NGX_ERROR) + ev->close_handler(ev); + } + + } else { + timer_queue.timer_next->timer_delta -= delta; + } + } + + for (i = 0; i < events; i++) { + + ngx_log_debug(log, "devpoll: %d: ev:%d rev:%d" _ + event_list[i].fd _ + event_list[i].events _ event_list[i].revents); + + + if (event_list[i].revents & POLLIN) { + c->read->ready = 1; + + if (c->read->oneshot) { + ngx_del_timer(c->read); + ngx_select_del_event(c->read, NGX_READ_EVENT, 0); + } + + if (c->read->event_handler(c->read) == NGX_ERROR) { + c->read->close_handler(c->read); + } + } + + if (event_list[i].revents & POLLOUT) { + c->write->ready = 1; + + if (c->write->oneshot) { + ngx_del_timer(c->write); + ngx_select_del_event(c->write, NGX_WRITE_EVENT, 0); + } + + if (c->write->event_handler(c->write) == NGX_ERROR) { + c->write->close_handler(c->write); + } + } + + if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { + ngx_log_error(NGX_LOG_ERR, log, ngx_errno, + "ioctl(DP_POLL) error on %d:%d", + event_list[i].fd, event_list[i].revents); + } + } + + return NGX_OK; +} + + +void ngx_devpoll_add_timer(ngx_event_t *ev, ngx_msec_t timer) +{ + ngx_event_t *e; + + ngx_log_debug(ev->log, "set timer: %d" _ timer); + + ngx_assert((!ev->timer_next && !ev->timer_prev), return, ev->log, + "timer already set"); + + for (e = timer_queue.timer_next; + e != &timer_queue && timer > e->timer_delta; + e = e->timer_next) + timer -= e->timer_delta; + + ev->timer_delta = timer; + + ev->timer_next = e; + ev->timer_prev = e->timer_prev; + + e->timer_prev->timer_next = ev; + e->timer_prev = ev; +} diff --git a/src/event/modules/ngx_devpoll_module.h b/src/event/modules/ngx_devpoll_module.h new file mode 100644 --- /dev/null +++ b/src/event/modules/ngx_devpoll_module.h @@ -0,0 +1,21 @@ +#ifndef _NGX_DEVPOLL_MODULE_H_INCLUDED_ +#define _NGX_DEVPOLL_MODULE_H_INCLUDED_ + + +#include +#include +#include + +int ngx_devpoll_init(int max_connections, ngx_log_t *log); +int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags); +int ngx_devpoll_del_event(ngx_event_t *ev, int event, u_int flags); +void ngx_devpoll_add_timer(ngx_event_t *ev, ngx_msec_t timer); +int ngx_devpoll_process_events(ngx_log_t *log); + + +/* DEBUG */ +#define POLLREMOVE 0x0800 +#define DP_POLL 1 + + +#endif /* _NGX_DEVPOLL_MODULE_H_INCLUDED_ */ diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -61,6 +61,22 @@ int ngx_kqueue_add_event(ngx_event_t *ev { ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; +#if 1 + if (nchanges > 0 + && ev->index < nchanges + && change_list[ev->index].udata == ev) + { + /* DEBUG */ + ngx_connection_t *c = (ngx_connection_t *) ev->data; + ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event); + + change_list[ev->index].filter = event; + change_list[ev->index].flags = flags; + + return NGX_OK; + } +#endif + return ngx_kqueue_set_event(ev, event, EV_ADD | flags); } @@ -69,12 +85,13 @@ int ngx_kqueue_del_event(ngx_event_t *ev { ngx_event_t *e; - if (nchanges > 0 && ev->index < nchanges + if (nchanges > 0 + && ev->index < nchanges && change_list[ev->index].udata == ev) { - ngx_connection_t *cn = (ngx_connection_t *) ev->data; - ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ - cn->fd _ event); + /* DEBUG */ + ngx_connection_t *c = (ngx_connection_t *) ev->data; + ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event); if (ev->index < --nchanges) { e = (ngx_event_t *) change_list[nchanges].udata; @@ -95,12 +112,12 @@ int ngx_kqueue_del_event(ngx_event_t *ev int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) { struct timespec ts; - ngx_connection_t *cn; + ngx_connection_t *c; - cn = (ngx_connection_t *) ev->data; + c = (ngx_connection_t *) ev->data; ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _ - cn->fd _ filter _ flags); + c->fd _ filter _ flags); if (nchanges >= nevents) { ngx_log_error(NGX_LOG_WARN, ev->log, 0, @@ -116,14 +133,16 @@ int ngx_kqueue_set_event(ngx_event_t *ev nchanges = 0; } - change_list[nchanges].ident = cn->fd; + change_list[nchanges].ident = c->fd; change_list[nchanges].filter = filter; change_list[nchanges].flags = flags; change_list[nchanges].fflags = 0; change_list[nchanges].data = 0; change_list[nchanges].udata = ev; +#if 0 if (flags == EV_ADD) +#endif ev->index = nchanges; nchanges++; @@ -140,10 +159,6 @@ int ngx_kqueue_process_events(ngx_log_t struct timeval tv; struct timespec ts, *tp; - timer = 0; - delta = 0; - tp = NULL; - if (timer_queue.timer_next != &timer_queue) { timer = timer_queue.timer_next->timer_delta; ts.tv_sec = timer / 1000; @@ -151,6 +166,11 @@ int ngx_kqueue_process_events(ngx_log_t tp = &ts; gettimeofday(&tv, NULL); delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + } else { + timer = 0; + delta = 0; + tp = NULL; } ngx_log_debug(log, "kevent timer: %d" _ timer); diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c new file mode 100644 --- /dev/null +++ b/src/event/modules/ngx_poll_module.c @@ -0,0 +1,258 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* should be per-thread */ +static struct pollfd *event_list; +static int nevents; + +static ngx_event_t **event_index; +static ngx_event_t timer_queue; +/* */ + +int ngx_poll_init(int max_connections, ngx_log_t *log) +{ + ngx_test_null(event_list, + ngx_alloc(sizeof(struct pollfd) * max_connections, log), + NGX_ERROR); + + ngx_test_null(event_index, + ngx_alloc(sizeof(ngx_event_t *) * max_connections, log), + NGX_ERROR); + + nevents = 0; + + timer_queue.timer_prev = &timer_queue; + timer_queue.timer_next = &timer_queue; + + ngx_event_actions.add = ngx_poll_add_event; + ngx_event_actions.del = ngx_poll_del_event; + ngx_event_actions.timer = ngx_poll_add_timer; + ngx_event_actions.process = ngx_poll_process_events; + + return NGX_OK; +} + +int ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_event_t *e; + ngx_connection_t *c; + + c = (ngx_connection_t *) ev->data; + + ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; + + if (event == NGX_READ_EVENT) { + e = c->write; +#if (NGX_READ_EVENT != POLLIN) + event = POLLIN; +#endif + + } else { + e = c->read; +#if (NGX_WRITE_EVENT != POLLOUT) + event = POLLOUT; +#endif + } + + ngx_log_debug(ev->log, "poll fd:%d event:%d" _ c->fd _ event); + + if (e == NULL || e->index == NGX_INVALID_INDEX) { + event_list[nevents].fd = c->fd; + event_list[nevents].events = event; + event_list[nevents].revents = 0; + + event_index[nevents] = ev; + ev->index = nevents; + nevents++; + + } else { + event_list[e->index].events |= event; + ev->index = e->index; + } + + return NGX_OK; +} + +int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_event_t *e; + ngx_connection_t *c; + + c = (ngx_connection_t *) ev->data; + + if (ev->index == NGX_INVALID_INDEX) + return NGX_OK; + + if (event == NGX_READ_EVENT) { + e = c->write; +#if (NGX_READ_EVENT != POLLIN) + event = POLLIN; +#endif + + } else { + e = c->read; +#if (NGX_WRITE_EVENT != POLLOUT) + event = POLLOUT; +#endif + } + + ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event); + + if (e == NULL || e->index == NGX_INVALID_INDEX) { + if (ev->index < --nevents) { + event_index[ev->index] = event_index[nevents]; + event_index[ev->index]->index = ev->index; + } + + } else { + event_list[e->index].events &= ~event; + } + + ev->index = NGX_INVALID_INDEX; + + return NGX_OK; +} + +int ngx_poll_process_events(ngx_log_t *log) +{ + int i, ready, found; + u_int timer, delta; + ngx_event_t *ev; + ngx_connection_t *c; + + if (timer_queue.timer_next != &timer_queue) { + timer = timer_queue.timer_next->timer_delta; + delta = ngx_msec(); + + } else { + timer = INFTIM; + delta = 0; + } + +#if 1 + /* DEBUG */ + for (i = 0; i < nevents; i++) { + ngx_log_debug(log, "poll: %d, %d" _ + event_list[i].fd _ event_list[i].events); + } +#endif + + ngx_log_debug(log, "poll timer: %d" _ timer); + + if ((ready = poll(event_list, nevents, timer)) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "poll() failed"); + return NGX_ERROR; + } + + ngx_log_debug(log, "poll ready %d" _ ready); + + if (timer != INFTIM) { + delta = ngx_msec() - delta; + + } else { + ngx_assert((ready != 0), return NGX_ERROR, log, + "poll() returns no events without timeout"); + } + + ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ delta); + + if (timer != INFTIM) { + if (delta >= timer) { + for ( ;; ) { + ev = timer_queue.timer_next; + + if (ev == &timer_queue || delta < ev->timer_delta) { + break; + } + + delta -= ev->timer_delta; + ngx_del_timer(ev); + ev->timedout = 1; + + if (ev->event_handler(ev) == NGX_ERROR) { + ev->close_handler(ev); + } + } + + } else { + timer_queue.timer_next->timer_delta -= delta; + } + } + + for (i = 0; ready; i++) { + c = &ngx_connections[event_list[i].fd]; + + ngx_log_debug(log, "poll: fd:%d, ev:%d, rev:%d" _ + event_list[i].fd _ + event_list[i].events _ event_list[i].revents); + + found = 0; + + if (event_list[i].revents & POLLIN) { + found = 1; + c->read->ready = 1; + + if (c->read->oneshot) { + ngx_del_timer(c->read); + ngx_select_del_event(c->read, NGX_READ_EVENT, 0); + } + + if (c->read->event_handler(c->read) == NGX_ERROR) { + c->read->close_handler(c->read); + } + } + + if (event_list[i].revents & POLLOUT) { + found = 1; + c->write->ready = 1; + + if (c->write->oneshot) { + ngx_del_timer(c->write); + ngx_select_del_event(c->write, NGX_WRITE_EVENT, 0); + } + + if (c->write->event_handler(c->write) == NGX_ERROR) { + c->write->close_handler(c->write); + } + } + + if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { + found = 1; + ngx_log_error(NGX_LOG_ERR, log, ngx_errno, + "poll() error on %d:%d", + event_list[i].fd, event_list[i].revents); + } + + if (found) { + ready--; + } + } + + return NGX_OK; +} + +void ngx_poll_add_timer(ngx_event_t *ev, ngx_msec_t timer) +{ + ngx_event_t *e; + + for (e = timer_queue.timer_next; + e != &timer_queue && timer > e->timer_delta; + e = e->timer_next) + timer -= e->timer_delta; + + ev->timer_delta = timer; + + ev->timer_next = e; + ev->timer_prev = e->timer_prev; + + e->timer_prev->timer_next = ev; + e->timer_prev = ev; +} diff --git a/src/event/modules/ngx_poll_module.h b/src/event/modules/ngx_poll_module.h new file mode 100644 --- /dev/null +++ b/src/event/modules/ngx_poll_module.h @@ -0,0 +1,16 @@ +#ifndef _NGX_POLL_MODULE_H_INCLUDED_ +#define _NGX_POLL_MODULE_H_INCLUDED_ + + +#include +#include +#include + +int ngx_poll_init(int max_connections, ngx_log_t *log); +int ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags); +int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags); +void ngx_poll_add_timer(ngx_event_t *ev, ngx_msec_t timer); +int ngx_poll_process_events(ngx_log_t *log); + + +#endif /* _NGX_POLL_MODULE_H_INCLUDED_ */ diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -29,9 +29,6 @@ static ngx_event_t **ready_index; static ngx_event_t timer_queue; /* */ -static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event, - ngx_log_t *log); - int ngx_select_init(int max_connections, ngx_log_t *log) { if (max_connections > FD_SETSIZE) { diff --git a/src/event/modules/ngx_select_module.h b/src/event/modules/ngx_select_module.h --- a/src/event/modules/ngx_select_module.h +++ b/src/event/modules/ngx_select_module.h @@ -9,7 +9,6 @@ int ngx_select_init(int max_connections, ngx_log_t *log); int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags); int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags); -int ngx_select_set_event(ngx_event_t *ev, int filter, u_int flags); void ngx_select_add_timer(ngx_event_t *ev, ngx_msec_t timer); int ngx_select_process_events(ngx_log_t *log); diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -12,6 +12,9 @@ #include #include +#if (HAVE_POLL) +#include +#endif #if (HAVE_KQUEUE) #include #endif @@ -23,11 +26,15 @@ ngx_event_t *ngx_read_events, *n #if !(USE_KQUEUE) #if (HAVE_KQUEUE) -#if 1 + +#if 0 ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; +#elif 1 +ngx_event_type_e ngx_event_type = NGX_POLL_EVENT; #else ngx_event_type_e ngx_event_type = NGX_KQUEUE_EVENT; #endif + #else ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; #endif @@ -51,7 +58,10 @@ static int (*ngx_event_init[]) (int max_ void ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log) { int i, fd; - ngx_listen_t *s; + + ngx_listen_t *s; + ngx_event_t *ev; + ngx_connection_t *c; /* STUB */ int max_connections = 512; @@ -70,6 +80,9 @@ void ngx_pre_thread(ngx_array_t *ls, ngx fd = s[i].fd; + c = &ngx_connections[fd]; + ev = &ngx_read_events[fd]; + ngx_memzero(&ngx_connections[fd], sizeof(ngx_connection_t)); ngx_memzero(&ngx_read_events[fd], sizeof(ngx_event_t)); @@ -89,6 +102,7 @@ void ngx_pre_thread(ngx_array_t *ls, ngx ngx_palloc(pool, sizeof(ngx_log_t)), /* void */ ; ); ngx_memcpy(ngx_read_events[fd].log, ngx_connections[fd].log, sizeof(ngx_log_t)); + c->read = ev; ngx_read_events[fd].data = &ngx_connections[fd]; ngx_read_events[fd].event_handler = &ngx_event_accept; ngx_read_events[fd].listening = 1; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -22,7 +22,7 @@ struct ngx_event_s { void *context; char *action; - int index; + unsigned int index; ngx_event_t *prev; /* queue in mutex(), aio_read(), aio_write() */ ngx_event_t *next; /* */ @@ -120,6 +120,14 @@ NGX_CLOSE_EVENT kqueue: kqueu #define NGX_CLEAR_EVENT EV_CLEAR #endif +#elif (HAVE_POLL) + +#define NGX_READ_EVENT POLLIN +#define NGX_WRITE_EVENT POLLOUT + +#define NGX_LEVEL_EVENT 0 +#define NGX_ONESHOT_EVENT 1 + #else #define NGX_READ_EVENT 0 diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c --- a/src/http/ngx_http_event.c +++ b/src/http/ngx_http_event.c @@ -1,7 +1,3 @@ -/* - TODO: Win32 inet_ntoa - ngx_inet_ntop -*/ #include #include diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_process.h @@ -0,0 +1,8 @@ +#ifndef _NGX_PROCESS_H_INCLUDED_ +#define _NGX_PROCESS_H_INCLUDED_ + + +#define ngx_getpid getpid + + +#endif /* _NGX_PROCESS_H_INCLUDED_ */ diff --git a/src/os/win32/ngx_process.h b/src/os/win32/ngx_process.h new file mode 100644 --- /dev/null +++ b/src/os/win32/ngx_process.h @@ -0,0 +1,8 @@ +#ifndef _NGX_PROCESS_H_INCLUDED_ +#define _NGX_PROCESS_H_INCLUDED_ + + +#define ngx_getpid GetCurrentProcessId + + +#endif /* _NGX_PROCESS_H_INCLUDED_ */