From 1e7ec9dcd2360ca5ef1a4db75a7971f0dec7ea54 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Tue, 11 Feb 2003 07:14:40 +0000 Subject: [PATCH] nginx-0.0.1-2003-02-11-10:14:40 import --- src/event/modules/ngx_kqueue_module.c | 16 +- src/event/modules/ngx_poll_module.c | 2 + src/event/modules/ngx_sigio_module.c | 117 +++++++++ src/event/ngx_event.c | 41 +--- src/event/ngx_event.h | 24 +- src/event/ngx_event_accept.c | 2 +- src/event/ngx_event_acceptex.c | 4 +- src/event/ngx_event_recv.c | 4 +- .../modules/ngx_http_event_proxy_handler.c | 2 +- src/http/ngx_http.h | 3 + src/http/ngx_http_core_module.c | 6 +- src/http/ngx_http_event.c | 106 ++++---- src/http/ngx_http_output_filter.c | 229 +++++++++++++++++- src/http/ngx_http_output_filter.h | 1 - src/os/win32/ngx_sendfile.c | 7 +- src/os/win32/ngx_socket.c | 12 +- 16 files changed, 468 insertions(+), 108 deletions(-) create mode 100644 src/event/modules/ngx_sigio_module.c diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c index da8450e62..501b4960e 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -66,13 +66,21 @@ int ngx_kqueue_init(int max_connections, ngx_log_t *log) ngx_event_actions.timer = ngx_event_add_timer; ngx_event_actions.process = ngx_kqueue_process_events; +#if (HAVE_AIO_EVENT) + + ngx_event_flags = NGX_HAVE_AIO_EVENT; + +#else + ngx_event_flags = NGX_HAVE_LEVEL_EVENT |NGX_HAVE_ONESHOT_EVENT -#if (HAVE_AIO_EVENT) - |NGX_HAVE_AIO_EVENT; -#else - |NGX_HAVE_CLEAR_EVENT; +#if (HAVE_CLEAR_EVENT) + |NGX_HAVE_CLEAR_EVENT #endif + |NGX_HAVE_KQUEUE_EVENT; + +#endif + #endif return NGX_OK; diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index 939340e46..25319c806 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -214,6 +214,8 @@ int ngx_poll_process_events(ngx_log_t *log) if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { found = 1; + /* need ot add to ready_index[nready++] = c->read or c->write; */ + err = 0; if (event_list[i].revents & POLLNVAL) { err = EBADF; diff --git a/src/event/modules/ngx_sigio_module.c b/src/event/modules/ngx_sigio_module.c new file mode 100644 index 000000000..f597b393d --- /dev/null +++ b/src/event/modules/ngx_sigio_module.c @@ -0,0 +1,117 @@ + + +int ngx_sigio_add_event(ngx_event_t *ev, int signal) +{ + ngx_connection_t *c; + + c = (ngx_connection_t *) ev->data; + + if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed"); + return NGX_ERROR; + } + + if (fcntl(c->fd, F_SETSIG, signal) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "fcntl(F_SETSIG) failed"); + return NGX_ERROR; + } + + if (fcntl(c->fd, F_SETOWN, pid) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "fcntl(F_SETOWN) failed"); + return NGX_ERROR; + } + +#if (HAVE_ONESIGFD) + if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "fcntl(F_SETAUXFL) failed"); + return NGX_ERROR; + } +#endif + + return NGX_OK; +} + +int ngx_sigio_process_events(ngx_log_t *log) +{ + struct siginfo si; + + for ( ;; ) { + if (timer) { + sig = sigtimedwait(&sigio_set, &si, &ts); + + if (sig == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "sigtimedwait() failed"); + continue; + } + } + + } else { + sig = sigwaitinfo(&set, &si); + + if (sig == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "sigwaitinfo() failed"); + } + } + + if (sig == rtsig) { + c = &ngx_connections[si.si_fd]; + + if (si.si_band & (POLLERR|POLLHUP|POLLNVAL)) { + ev = ???; + + if (ev->active) { + ev->ready = 1; + if (ev->event_handler(ev) == NGX_ERROR) { + ev->close_handler(ev); + } + } + } + + if (si.si_band & (POLLIN)) { + ev = c->read; + + if (ev->active) { + ev->ready = 1; + if (ev->event_handler(ev) == NGX_ERROR) { + ev->close_handler(ev); + } + } + } + + if (si.si_band & (POLLOUT)) { + ev = c->write; + + if (ev->active) { + ev->ready = 1; + if (ev->event_handler(ev) == NGX_ERROR) { + ev->close_handler(ev); + } + } + } + + } else if (sig == SIGIO) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "Signal queue overflowed: " + "SIGIO, fd:%d, band:%d", si.si_fd, si.si_band); + + /* flush queue: method #1 (dphttpd) */ + ts.tv_sec = 0; + ts.tv_nsec = 0; + while (sigtimedwait(&sigio_set, &si, &ts) > 0); + + /* flush queue: method #2 (dkftpbench) */ + signal(m_signum, SIG_IGN); + signal(m_signum, SIG_DFL); + + /* do poll */ + + } else { + } + } +} diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 063385dba..84e5e29da 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -36,33 +36,9 @@ ngx_event_t *ngx_read_events, *ngx_write_events; #if !(USE_KQUEUE) -#if (HAVE_KQUEUE) +ngx_event_type_e ngx_event_type; -#if 0 -ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; -#elif 0 -ngx_event_type_e ngx_event_type = NGX_POLL_EVENT; -#else -ngx_event_type_e ngx_event_type = NGX_KQUEUE_EVENT; -#endif - -#elif (HAVE_DEVPOLL) - -#if 0 -ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; -#elif 0 -ngx_event_type_e ngx_event_type = NGX_POLL_EVENT; -#else -ngx_event_type_e ngx_event_type = NGX_DEVPOLL_EVENT; -#endif - -#else - -ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; - -#endif - -int ngx_event_flags; +int ngx_event_flags; ngx_event_actions_t ngx_event_actions; @@ -97,8 +73,17 @@ void ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log) /* STUB */ int max_connections = 512; -#if (HAVE_IOCP) - ngx_event_type = NGX_IOCP_EVENT; +#if 0 + ngx_event_type = NGX_POLL_EVENT_N; +#endif +#if 1 + ngx_event_type = NGX_KQUEUE_EVENT_N; +#endif +#if 0 + ngx_event_type = NGX_DEVPOLL_EVENT_N; +#endif +#if 0 + ngx_event_type = NGX_IOCP_EVENT_N; #endif if (ngx_init_events(max_connections, log) == NGX_ERROR) { diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index d81be38fe..450fbe2b4 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -106,20 +106,20 @@ struct ngx_event_s { }; typedef enum { - NGX_SELECT_EVENT = 0, + NGX_SELECT_EVENT_N = 0, #if (HAVE_POLL) - NGX_POLL_EVENT, + NGX_POLL_EVENT_N, #endif #if (HAVE_DEVPOLL) - NGX_DEVPOLL_EVENT, + NGX_DEVPOLL_EVENT_N, #endif #if (HAVE_KQUEUE) - NGX_KQUEUE_EVENT, + NGX_KQUEUE_EVENT_N, #endif #if (HAVE_IOCP) - NGX_IOCP_EVENT, + NGX_IOCP_EVENT_N, #endif - NGX_DUMMY_EVENT /* avoid comma at end of enumerator list */ + NGX_DUMMY_EVENT_N /* avoid comma at end of enumerator list */ } ngx_event_type_e ; typedef struct { @@ -145,15 +145,21 @@ typedef struct { /* Event filter notifies only changes and initial level - kqueue */ #define NGX_HAVE_CLEAR_EVENT 4 +/* Event filter has kqueue features - eof flag, errno, available data, etc */ +#define NGX_HAVE_KQUEUE_EVENT 8 + /* Event filter notifies only changes (edgesi) but not initial level - epoll */ -#define NGX_HAVE_EDGE_EVENT 8 +#define NGX_HAVE_EDGE_EVENT 16 + +/* No need to add or delete event filters - rt signals */ +#define NGX_HAVE_SIGIO_EVENT 32 /* No need to add or delete event filters - overlapped, aio_read, aioread */ -#define NGX_HAVE_AIO_EVENT 16 +#define NGX_HAVE_AIO_EVENT 64 /* Need to add socket or halde only once - i/o completion port. It also requires to set HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT */ -#define NGX_HAVE_IOCP_EVENT 32 +#define NGX_HAVE_IOCP_EVENT 128 /* Event filter is deleted before closing file. Has no meaning for select, poll, epoll. diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 2d64c0d9b..941f57c4e 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -156,7 +156,7 @@ int ngx_event_accept(ngx_event_t *ev) #elif (HAVE_KQUEUE) - if (ngx_event_type == NGX_KQUEUE_EVENT) { + if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { ev->available--; } diff --git a/src/event/ngx_event_acceptex.c b/src/event/ngx_event_acceptex.c index 83b3c42fc..0654c80fa 100644 --- a/src/event/ngx_event_acceptex.c +++ b/src/event/ngx_event_acceptex.c @@ -29,7 +29,7 @@ int ngx_event_acceptex(ngx_event_t *ev) return NGX_OK; } - GetAcceptExSockaddrs(c->data, 0, + getacceptexsockaddrs(c->data, 0, c->socklen + 16, c->socklen + 16, &c->local_sockaddr, &c->local_socklen, &c->sockaddr, &c->socklen); @@ -130,7 +130,7 @@ int ngx_event_post_acceptex(ngx_listen_t *ls, int n) return NGX_ERROR; } - if (AcceptEx(ls->fd, s, c->data, 0, + if (acceptex(ls->fd, s, c->data, 0, c->socklen + 16, c->socklen + 16, &rcvd, (LPOVERLAPPED) &rev->ovlp) == 0) { diff --git a/src/event/ngx_event_recv.c b/src/event/ngx_event_recv.c index 4fa95c3ae..39eb32014 100644 --- a/src/event/ngx_event_recv.c +++ b/src/event/ngx_event_recv.c @@ -36,7 +36,7 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size) #elif (HAVE_KQUEUE) - if (ngx_event_type == NGX_KQUEUE_EVENT) { + if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { if (c->read->eof && c->read->available == 0) { if (c->read->error) { ngx_log_error(NGX_LOG_ERR, c->log, c->read->error, @@ -70,7 +70,7 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size) #elif (HAVE_KQUEUE) - if (ngx_event_type == NGX_KQUEUE_EVENT) { + if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { c->read->available -= n; } diff --git a/src/http/modules/ngx_http_event_proxy_handler.c b/src/http/modules/ngx_http_event_proxy_handler.c index 195e4b3ff..c7f115acf 100644 --- a/src/http/modules/ngx_http_event_proxy_handler.c +++ b/src/http/modules/ngx_http_event_proxy_handler.c @@ -437,7 +437,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev) #elif (HAVE_KQUEUE) - if (ngx_event_type == NGX_KQUEUE_EVENT) { + if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { /* do not allocate new block if there is EOF */ if (ev->eof && ev->available == 0) { left = 1; diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 296657679..41bd932eb 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -163,6 +163,9 @@ struct ngx_http_request_s { unsigned unusual_uri:1; /* URI is not started with '/' - "GET http://" */ unsigned complex_uri:1; /* URI with "/." or with "//" (WIN32) */ unsigned path_not_found:1; +#ifdef NGX_EVENT + unsigned write_level_event:1; +#endif int state; char *uri_start; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 2f33b5726..072fe3666 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -101,10 +101,10 @@ int ngx_http_handler(ngx_http_request_t *r) r->connection->unexpected_eof = 0; - r->lingering_close = 0; - r->keepalive = 0; + r->lingering_close = 1; + r->keepalive = 1; -#if 0 +#if 1 r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; #endif diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c index ea5b3225b..0b69209ba 100644 --- a/src/http/ngx_http_event.c +++ b/src/http/ngx_http_event.c @@ -30,6 +30,7 @@ static int ngx_http_event_request_handler(ngx_http_request_t *r); static int ngx_http_writer(ngx_event_t *ev); static int ngx_http_block_read(ngx_event_t *ev); static int ngx_http_read_discarded_body(ngx_event_t *ev); +static int ngx_http_set_keepalive(ngx_http_request_t *r); static int ngx_http_keepalive_handler(ngx_event_t *ev); static int ngx_http_set_lingering_close(ngx_http_request_t *r); static int ngx_http_lingering_close_handler(ngx_event_t *ev); @@ -112,10 +113,11 @@ int ngx_http_init_connection(ngx_connection_t *c) #endif +/* THINK: should ngx_edge_add_event() be moved to accept part ? */ #if (HAVE_EDGE_EVENT) /* epoll */ if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { - if (ngx_add_event(ev, NGX_READ_EVENT, NGX_EDGE_EVENT) == NGX_ERROR) { + if (ngx_edge_add_event(ev) == NGX_ERROR) { return NGX_ERROR; } return ngx_http_init_request(ev); @@ -129,7 +131,7 @@ int ngx_http_init_connection(ngx_connection_t *c) return ngx_http_init_request(ev); } -#endif /* HAVE_AIO_EVENT */ +#endif /* select, poll, /dev/poll */ @@ -498,9 +500,9 @@ static int ngx_http_event_request_handler(ngx_http_request_t *r) #else -#if (HAVE_AIO_EVENT) /* aio, iocp */ +#if (HAVE_AIO_EVENT) || (HAVE_EDGE_EVENT) /* aio, iocp, epoll */ - if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { + if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { return rc; } @@ -512,30 +514,14 @@ static int ngx_http_event_request_handler(ngx_http_request_t *r) event = NGX_CLEAR_EVENT; } else { - event = NGX_ONESHOT_EVENT; - } - -#elif (HAVE_EDGE_EVENT) /* epoll */ - - if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { - event = NGX_EDGE_EVENT; - - } else { - event = NGX_ONESHOT_EVENT; - } - -#elif (HAVE_DEVPOLL_EVENT) /* /dev/poll */ - - if (ngx_event_flags & NGX_HAVE_LEVEL_EVENT) { event = NGX_LEVEL_EVENT; - - } else { - event = NGX_ONESHOT_EVENT; + r->write_level_event = 1; } -#else /* select, poll */ +#else /* select, poll, /dev/poll */ - event = NGX_ONESHOT_EVENT; + event = NGX_LEVEL_EVENT; + r->write_level_event = 1; #endif @@ -571,13 +557,7 @@ static int ngx_http_event_request_handler(ngx_http_request_t *r) /* keepalive */ - r->connection->buffer->pos.mem = r->connection->buffer->last.mem - = r->connection->buffer->start; - rev->event_handler = ngx_http_keepalive_handler; - - ngx_http_close_request(r); - - return NGX_OK; + return ngx_http_set_keepalive(r); } @@ -617,14 +597,6 @@ static int ngx_http_writer(ngx_event_t *ev) ngx_add_timer(ev, timeout); } - /* TODO: /dev/poll, epoll, aio_write */ - - if (ev->oneshot) - if (ngx_add_event(ev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) - == NGX_ERROR) { - return ngx_http_close_request(r); - } - return rc; } @@ -646,15 +618,11 @@ static int ngx_http_writer(ngx_event_t *ev) /* keepalive */ - c->buffer->pos.mem = c->buffer->last.mem = c->buffer->start; - c->read->event_handler = ngx_http_keepalive_handler; - - ngx_http_close_request(r); - - return NGX_OK; + return ngx_http_set_keepalive(r); } +/* TODO */ static int ngx_http_block_read(ngx_event_t *ev) { ngx_log_debug(ev->log, "http read blocked"); @@ -693,6 +661,7 @@ static int ngx_http_block_read(ngx_event_t *ev) } +/* TODO */ int ngx_http_discard_body(ngx_http_request_t *r) { ngx_event_t *ev; @@ -716,6 +685,7 @@ int ngx_http_discard_body(ngx_http_request_t *r) } +/* TODO */ static int ngx_http_read_discarded_body(ngx_event_t *ev) { size_t size; @@ -757,6 +727,34 @@ static int ngx_http_read_discarded_body(ngx_event_t *ev) } +/* TODO: if c->read->blocked */ +static int ngx_http_set_keepalive(ngx_http_request_t *r) +{ + ngx_connection_t *c; + + c = (ngx_connection_t *) r->connection; + + c->buffer->pos.mem = c->buffer->last.mem = c->buffer->start; + c->read->event_handler = ngx_http_keepalive_handler; + + if (r->write_level_event) { + if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) { + return NGX_ERROR; + } + } + + ngx_http_close_request(r); + +#if (HAVE_AIO_EVENT) /* aio, iocp */ + if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { + return ngx_http_keepalive_handler(c->read); + } +#endif + + return NGX_OK; +} + + static int ngx_http_keepalive_handler(ngx_event_t *ev) { ssize_t n; @@ -796,8 +794,10 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev) static int ngx_http_set_lingering_close(ngx_http_request_t *r) { ngx_event_t *ev; + ngx_connection_t *c; ngx_http_core_loc_conf_t *lcf; + c = r->connection; ev = r->connection->read; lcf = (ngx_http_core_loc_conf_t *) @@ -832,7 +832,21 @@ static int ngx_http_set_lingering_close(ngx_http_request_t *r) return ngx_http_close_request(r); } - return NGX_OK; +#if (HAVE_AIO_EVENT) /* aio, iocp */ + if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { + return ngx_http_lingering_close_handler(ev); + } +#endif + +#if (HAVE_CLEAR_EVENT) || (HAVE_EDGE_EVENT) /* kqueue, epoll */ + if (ngx_event_flags & (NGX_HAVE_CLEAR_EVENT|NGX_HAVE_EDGE_EVENT)) { + return NGX_OK; + } +#endif + + /* select, poll, /dev/poll */ + + return ngx_del_event(c->write, NGX_WRITE_EVENT, 0); } diff --git a/src/http/ngx_http_output_filter.c b/src/http/ngx_http_output_filter.c index 93a7d61c4..2ca32f75e 100644 --- a/src/http/ngx_http_output_filter.c +++ b/src/http/ngx_http_output_filter.c @@ -57,6 +57,224 @@ ngx_module_t ngx_http_output_filter_module = { }; +#if 1 + +#define next_filter ngx_http_output_filter_module_ctx.next_output_body_filter + +#define need_to_copy(r, hunk) \ + (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \ + && (hunk->type & NGX_HUNK_FILE)) \ + || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \ + && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))) + +int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) +{ + int rc; + size_t size; + ngx_chain_t *ce, *pe; + ngx_http_output_filter_ctx_t *ctx; + ngx_http_output_filter_conf_t *conf; + + ctx = (ngx_http_output_filter_ctx_t *) + ngx_http_get_module_ctx(r->main ? r->main : r, + ngx_http_output_filter_module); + + if (ctx == NULL) { + ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module, + sizeof(ngx_http_output_filter_ctx_t)); + } + + /* the incoming chain ctx->in is empty */ + if (ctx->in == NULL) { + + if (hunk == NULL) { + return next_filter(r, NULL); + } + + /* we do not need to copy the incoming hunk to our hunk */ + if (!need_to_copy(r, hunk)) { + ctx->out.hunk = hunk; + ctx->out.next = NULL; + + return next_filter(r, &ctx->out); + } + + /* we need to copy the incoming hunk to our hunk */ + + /* allocate ctx->hunk if it's needed */ + if (ctx->hunk == NULL) { + + conf = (ngx_http_output_filter_conf_t *) + ngx_http_get_module_loc_conf(r->main ? r->main : r, + ngx_http_output_filter_module); + + if (hunk->type & NGX_HUNK_LAST) { + size = hunk->last.mem - hunk->pos.mem; + if (size > conf->hunk_size) { + size = conf->hunk_size; + } + + } else { + size = conf->hunk_size; + } + + ngx_test_null(ctx->hunk, + ngx_create_temp_hunk(r->pool, size, 50, 50), + NGX_ERROR); + + ctx->hunk->type |= NGX_HUNK_RECYCLED; + } + + /* copy the incoming hunk or its part to our hunk + and pass it to the next filter */ + + do { + rc = ngx_http_output_filter_copy_hunk(ctx->hunk, hunk); + + if (rc == NGX_ERROR) { + return rc; + } + +#if (NGX_FILE_AIO_READ) + + if (rc == NGX_AGAIN) { + /* add the incoming hunk to the incoming chain */ + ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); + return rc; + } + +#endif + ctx->out.hunk = ctx->hunk; + ctx->out.next = NULL; + + rc = next_filter(r, &ctx->out); + + if (rc == NGX_ERROR) { + return rc; + } + + if (rc == NGX_AGAIN) { + /* add the incoming hunk to the incoming chain */ + ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); + return rc; + } + + /* NGX_OK */ + + /* set our hunk free */ + ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; + + /* repeat until we will have copied the whole incoming hunk */ + } while (hunk->pos.mem < hunk->last.mem); + + return NGX_OK; + } + + /* the incoming chain ctx->in is not empty */ + + /* add the incoming hunk to the incoming chain */ + if (hunk) { + for (ce = ctx->in; ce->next; ce = ce->next) { + /* void */ ; + } + + ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR); + } + + /* our hunk is still busy */ + if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { + rc = next_filter(r, NULL); + + if (rc == NGX_ERROR || rc == NGX_AGAIN) { + return rc; + } + + /* NGX_OK */ + ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; + } + +#if (NGX_SUPPRESS_WARN) + pe = NULL; +#endif + + /* process the incoming chain ctx->in */ + do { + /* find the hunks that do not need to be copied ... */ + for (ce = ctx->in; ce; ce = ce->next) { + if (need_to_copy(r, ce->hunk)) { + break; + } + pe = ce; + } + + /* ... and pass them to the next filter */ + if (ctx->in != ce) { + + ctx->out.hunk = ctx->in->hunk; + ctx->out.next = ctx->in->next; + ctx->in = ce; + pe->next = NULL; + + rc = next_filter(r, &ctx->out); + + if (rc == NGX_ERROR || rc == NGX_AGAIN) { + return rc; + } + + /* NGX_OK */ + if (ctx->in == NULL) { + return rc; + } + } + + + /* copy the first hunk or its part from the incoming chain ctx->in + to our hunk and pass it to the next filter */ + do { + rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); + + if (rc == NGX_ERROR) { + return rc; + } + +#if (NGX_FILE_AIO_READ) + + if (rc == NGX_AGAIN) { + return rc; + } + +#endif + ctx->out.hunk = ctx->hunk; + ctx->out.next = NULL; + + rc = next_filter(r, &ctx->out); + + if (rc == NGX_ERROR || rc == NGX_AGAIN) { + return rc; + } + + /* NGX_OK */ + + /* set our hunk free */ + ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; + + /* repeat until we will have copied the whole first hunk from + the incoming chain ctx->in */ + } while (ctx->in->hunk->pos.mem < ctx->in->hunk->last.mem); + + /* delete the completed hunk from the incoming chain */ + ctx->in = ctx->in->next; + + /* repeat until we will have processed the whole incoming chain ctx->in */ + } while (ctx->in); + + return NGX_OK; +} + + +#else + + int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) { int rc, once; @@ -106,6 +324,7 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) } else { ctx->out.hunk = ctx->hunk; + /* XXX: should we check hunk type before copy it ? */ rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); #if (NGX_FILE_AIO_READ) if (rc == NGX_AGAIN) { @@ -116,6 +335,8 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) return rc; } + /* NGX_OK */ + /* whole hunk is copied so we send to next filter chain part up to next hunk that need to be copied */ if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) { @@ -242,8 +463,10 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) } } - if (rc == NGX_OK && ctx->hunk) + /* set free our hunk if operation has completed */ + if (rc == NGX_OK && ctx->hunk) { ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; + } } #if (NGX_SUPPRESS_WARN) @@ -259,7 +482,7 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) } if (rc == NGX_OK) { - if (ctx->hunk) { + if (ctx->hunk) { /* XXX: double upper code ? */ ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; } #if (NGX_LEVEL_EVENT) @@ -270,6 +493,8 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) return rc; } +#endif + static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src) { diff --git a/src/http/ngx_http_output_filter.h b/src/http/ngx_http_output_filter.h index 175550eaa..cb7367b93 100644 --- a/src/http/ngx_http_output_filter.h +++ b/src/http/ngx_http_output_filter.h @@ -21,7 +21,6 @@ typedef struct { ngx_hunk_t *hunk; ngx_chain_t *in; ngx_chain_t out; - unsigned last; } ngx_http_output_filter_ctx_t; diff --git a/src/os/win32/ngx_sendfile.c b/src/os/win32/ngx_sendfile.c index ce43b37b3..c2bdf6c62 100644 --- a/src/os/win32/ngx_sendfile.c +++ b/src/os/win32/ngx_sendfile.c @@ -83,11 +83,12 @@ int ngx_sendfile(ngx_connection_t *c, ptfb = NULL; } -#if 0 +#if 1 flags = TF_DISCONNECT|TF_REUSE_SOCKET; -#endif - + tfrc = transmitfile(c->fd, NULL, 0, 0, &olp, NULL, flags); +#else tfrc = TransmitFile(c->fd, fd, nbytes, 0, &olp, ptfb, flags); +#endif #if 0 #if 1 diff --git a/src/os/win32/ngx_socket.c b/src/os/win32/ngx_socket.c index 09cbddf6b..f289a33e7 100644 --- a/src/os/win32/ngx_socket.c +++ b/src/os/win32/ngx_socket.c @@ -8,9 +8,9 @@ /* These pointers should be per protocol ? */ -LPFN_ACCEPTEX AcceptEx; -LPFN_GETACCEPTEXSOCKADDRS GetAcceptExSockaddrs; -LPFN_TRANSMITFILE TransmitFile; +LPFN_ACCEPTEX acceptex; +LPFN_GETACCEPTEXSOCKADDRS getacceptexsockaddrs; +LPFN_TRANSMITFILE transmitfile; static GUID ae_guid = WSAID_ACCEPTEX; static GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS; @@ -37,7 +37,7 @@ int ngx_init_sockets(ngx_log_t *log) } if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ae_guid, sizeof(GUID), - &AcceptEx, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL) == -1) { + &acceptex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " @@ -46,7 +46,7 @@ int ngx_init_sockets(ngx_log_t *log) } if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID), - &GetAcceptExSockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS), + &getacceptexsockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS), &bytes, NULL, NULL) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, @@ -56,7 +56,7 @@ int ngx_init_sockets(ngx_log_t *log) } if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tf_guid, sizeof(GUID), - &TransmitFile, sizeof(LPFN_TRANSMITFILE), &bytes, + &transmitfile, sizeof(LPFN_TRANSMITFILE), &bytes, NULL, NULL) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "