Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2004-06-20 23:54:15 +0400
committerIgor Sysoev <igor@sysoev.ru>2004-06-20 23:54:15 +0400
commit73a73b5a60b1c6c985f3e9a5d7cddbe292ad01a4 (patch)
treefe274167bb823494fe327e9f48a97a330cfe5c49
parentf7290501f2426950f6c3ff7a2e3280bfaa831f0b (diff)
nginx-0.0.7-2004-06-20-23:54:15 import
-rw-r--r--auto/types/maxvalue6
-rwxr-xr-xauto/unix1
-rw-r--r--src/event/ngx_event.h6
-rw-r--r--src/event/ngx_event_timer.c10
-rw-r--r--src/event/ngx_event_timer.h2
-rw-r--r--src/http/ngx_http_request.c53
-rw-r--r--src/http/ngx_http_request.h1
-rw-r--r--src/http/ngx_http_write_filter.c12
-rw-r--r--src/os/unix/ngx_freebsd_config.h16
-rw-r--r--src/os/unix/ngx_freebsd_init.c11
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c79
-rw-r--r--src/os/unix/ngx_process_cycle.c59
12 files changed, 176 insertions, 80 deletions
diff --git a/auto/types/maxvalue b/auto/types/maxvalue
new file mode 100644
index 000000000..91752a26d
--- /dev/null
+++ b/auto/types/maxvalue
@@ -0,0 +1,6 @@
+
+cat << END >> $NGX_AUTO_CONFIG_H
+
+#ifndef $ngx_type_max_value
+#define $ngx_type_max_value $ngx_max_size
+#endif
diff --git a/auto/unix b/auto/unix
index 5cd940eb6..f4bc83da0 100755
--- a/auto/unix
+++ b/auto/unix
@@ -46,6 +46,7 @@ CC_WARN=$CC_STRONG
ngx_fmt_collect=no
ngx_fmt_name=OFF_T_FMT; ngx_type="off_t"; . auto/types/sizeof
+ngx_type_max_value=OFF_T_MAX_VALUE; . auto/types/maxvalue
eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/fmt
ngx_fmt_name=TIME_T_FMT; ngx_type="time_t"; . auto/types/sizeof
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 0c2e5d8fa..344982e21 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -91,8 +91,6 @@ struct ngx_event_s {
unsigned short timedout:1;
unsigned short timer_set:1;
- unsigned short delayed:1;
-
unsigned short read_discarded:1;
unsigned short unexpected_eof:1;
@@ -499,7 +497,7 @@ ngx_inline static int ngx_handle_read_event(ngx_event_t *rev, u_int flags)
}
}
- /* aio, iocp, epoll, rt signals */
+ /* aio, iocp, epoll, rtsig */
return NGX_OK;
}
@@ -570,7 +568,7 @@ ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, u_int flags)
}
}
- /* aio, iocp, epoll, rt signals */
+ /* aio, iocp, epoll, rtsig */
return NGX_OK;
}
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index a3d4d808d..fb401cf84 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -91,15 +91,7 @@ void ngx_event_expire_timers(ngx_msec_t timer)
ngx_del_timer(ev);
- if (ev->delayed) {
- ev->delayed = 0;
- if (ev->ready == 0) {
- continue;
- }
-
- } else {
- ev->timedout = 1;
- }
+ ev->timedout = 1;
if (ngx_threaded) {
if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h
index 3ff0e7c10..e7e49d28d 100644
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -85,7 +85,7 @@ ngx_inline static void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
* for the fast connections.
*/
- if (key - ev->rbtree_key < 100 / NGX_TIMER_RESOLUTION) {
+ if (abs(key - ev->rbtree_key) < 100 / NGX_TIMER_RESOLUTION) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"event timer: %d, old: %d, new: %d",
ngx_event_ident(ev->data), ev->rbtree_key, key);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0f30a3177..814e582e8 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1050,13 +1050,15 @@ static void ngx_http_set_write_handler(ngx_http_request_t *r)
wev = r->connection->write;
wev->event_handler = ngx_http_writer;
- if (wev->delayed && wev->ready) {
+ if (wev->ready && r->delayed) {
return;
}
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_core_module);
- ngx_add_timer(wev, clcf->send_timeout);
+ if (!r->delayed) {
+ ngx_add_timer(wev, clcf->send_timeout);
+ }
wev->available = clcf->send_lowat;
if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
@@ -1080,15 +1082,36 @@ void ngx_http_writer(ngx_event_t *wev)
c = wev->data;
r = c->data;
-#if 0 /* TODO: THINK */
- if (wev->delayed) {
- return;
- }
-#endif
-
if (wev->timedout) {
- ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
- return;
+ if (!r->delayed) {
+ ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
+ return;
+ }
+
+ wev->timedout = 0;
+ r->delayed = 0;
+
+ if (!wev->ready) {
+ clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+ ngx_http_core_module);
+ ngx_add_timer(wev, clcf->send_timeout);
+
+ wev->available = clcf->send_lowat;
+
+ if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
+ ngx_http_close_request(r, 0);
+ ngx_http_close_connection(r->connection);
+ }
+
+ return;
+ }
+
+ } else {
+ if (r->delayed) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
+ "http writer delayed");
+ return;
+ }
}
rc = ngx_http_output_filter(r, NULL);
@@ -1097,13 +1120,15 @@ void ngx_http_writer(ngx_event_t *wev)
"http writer output filter: %d", rc);
if (rc == NGX_AGAIN) {
- if (!wev->ready) {
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+ ngx_http_core_module);
+ if (!wev->ready && !r->delayed) {
ngx_add_timer(wev, clcf->send_timeout);
}
- if (ngx_handle_level_write_event(wev) == NGX_ERROR) {
+ wev->available = clcf->send_lowat;
+
+ if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
ngx_http_close_request(r, 0);
ngx_http_close_connection(r->connection);
}
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 52e110af7..7054d92e5 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -284,6 +284,7 @@ struct ngx_http_request_s {
/* can we use sendfile ? */
unsigned sendfile:1;
+ unsigned delayed:1;
unsigned chunked:1;
unsigned header_only:1;
unsigned keepalive:1;
diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c
index b0e47371b..bdef48b1b 100644
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -69,7 +69,7 @@ ngx_module_t ngx_http_write_filter_module = {
ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
int last;
- off_t size, flush;
+ off_t size, flush, sent;
ngx_chain_t *cl, *ln, **ll, *chain;
ngx_http_write_filter_ctx_t *ctx;
ngx_http_write_filter_conf_t *conf;
@@ -138,7 +138,7 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_OK;
}
- if (r->connection->write->delayed) {
+ if (r->delayed) {
return NGX_AGAIN;
}
@@ -150,11 +150,19 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_OK;
}
+ sent = r->connection->sent;
+
chain = ngx_write_chain(r->connection, ctx->out);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http write filter %X", chain);
+#if 1
+ sent = r->connection->sent - sent;
+ r->delayed = 1;
+ ngx_add_timer(r->connection->write, sent * 1000 / (4 * 1024));
+#endif
+
if (chain == NGX_CHAIN_ERROR) {
return NGX_ERROR;
}
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index ce77ab938..570eee89b 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -35,6 +35,22 @@
#include <sys/sysctl.h>
#include <netinet/tcp.h> /* TCP_NOPUSH */
+
+#if __FreeBSD_version < 400017
+
+#include <sys/param.h> /* ALIGN() */
+
+/* FreeBSD 3.x has no CMSG_SPACE() at all and has the broken CMSG_DATA() */
+
+#undef CMSG_SPACE
+#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l))
+
+#undef CMSG_DATA
+#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr)))
+
+#endif
+
+
#include <ngx_auto_config.h>
diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c
index eb66cf067..35be16412 100644
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -121,15 +121,18 @@ int ngx_os_init(ngx_log_t *log)
#if (HAVE_SENDFILE)
/*
- * The determination of the sendfile() nbytes bug is complex enough.
+ * The determination of the sendfile() "nbytes bug" is complex enough.
* There are two sendfile() syscalls: a new #393 has no bug while
* an old #336 has the bug in some versions and has not in others.
* Besides libc_r wrapper also emulates the bug in some versions.
* There's no way to say exactly if a given FreeBSD version has the bug.
- * Here is the algorithm that works at least for RELEASEs
+ * We use the algorithm that is correct at least for RELEASEs
* and for syscalls only (not libc_r wrapper).
*
- * We detect the new sendfile() version available at the compile time
+ * 4.6.1-RELEASE and below have the bug
+ * 4.6.2-RELEASE and above have the new syscall
+ *
+ * We detect the new sendfile() syscall available at the compile time
* to allow an old binary to run correctly on an updated FreeBSD system.
*/
@@ -142,7 +145,7 @@ int ngx_os_init(ngx_log_t *log)
#else
- /* an old syscall that can have the bug */
+ /* an old syscall that may have the bug */
ngx_freebsd_sendfile_nbytes_bug = 1;
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index abc3d19b5..f4d8ffdeb 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -11,9 +11,9 @@
/*
* Although FreeBSD sendfile() allows to pass a header and a trailer
- * it never sends a header with a part of the file in one packet until
+ * it can not send a header with a part of the file in one packet until
* FreeBSD 5.2-STABLE. Besides over the fast ethernet connection sendfile()
- * can send the partially filled packets, i.e. the 8 file pages can be sent
+ * may send the partially filled packets, i.e. the 8 file pages may be sent
* as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet,
* and then again the 11 full 1460-bytes packets.
*
@@ -22,7 +22,7 @@
* of the file in one packet but also sends file pages in the full packets.
*
* But until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending
- * data that less than MSS so that data can be sent with 5 second delay.
+ * data that less than MSS so that data may be sent with 5 second delay.
* So we do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
* for non-keepalive HTTP connections.
*/
@@ -32,10 +32,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
{
int rc;
u_char *prev;
- off_t sent, fprev;
+ off_t sent, fprev, send, limit;
size_t hsize, fsize;
ssize_t size;
- ngx_int_t eintr, eagain;
+ ngx_uint_t eintr, eagain, ready;
struct iovec *iov;
struct sf_hdtr hdtr;
ngx_err_t err;
@@ -62,12 +62,20 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
#endif
+#if 1
+ limit = 4096;
+#else
+ limit = OFF_T_MAX_VALUE;
+#endif
+
do {
file = NULL;
fsize = 0;
hsize = 0;
+ send = 0;
eintr = 0;
eagain = 0;
+ ready = 0;
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
NGX_CHAIN_ERROR);
@@ -88,40 +96,50 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
break;
}
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
if (prev == cl->buf->pos) {
- iov->iov_len += cl->buf->last - cl->buf->pos;
+ iov->iov_len += size;
} else {
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = cl->buf->last - cl->buf->pos;
+ iov->iov_len = size;
}
- prev = cl->buf->last;
- hsize += cl->buf->last - cl->buf->pos;
+ prev = cl->buf->pos + size;
+ hsize += size;
+ send += size;
}
/* get the file buf */
if (cl && cl->buf->in_file) {
file = cl->buf;
- fsize = (size_t) (file->file_last - file->file_pos);
- fprev = file->file_last;
- cl = cl->next;
+ fsize = 0;
/* coalesce the neighbouring file bufs */
- while (cl && cl->buf->in_file) {
- if (file->file->fd != cl->buf->file->fd
- || fprev != cl->buf->file_pos)
- {
- break;
+ do {
+ size = (size_t) (cl->buf->file_last - cl->buf->file_pos);
+
+ if (send + size > limit) {
+ size = limit - send;
}
- fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos);
- fprev = cl->buf->file_last;
+ fsize += size;
+ send += size;
+ fprev = cl->buf->file_pos + size;
cl = cl->next;
- }
+
+ } while (cl
+ && cl->buf->in_file
+ && file->file->fd == cl->buf->file->fd
+ && fprev == cl->buf->file_pos);
}
if (file) {
@@ -139,17 +157,24 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
break;
}
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
if (prev == cl->buf->pos) {
- iov->iov_len += cl->buf->last - cl->buf->pos;
+ iov->iov_len += size;
} else {
ngx_test_null(iov, ngx_push_array(&trailer),
NGX_CHAIN_ERROR);
iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = cl->buf->last - cl->buf->pos;
+ iov->iov_len = size;
}
- prev = cl->buf->last;
+ prev = cl->buf->pos + size;
+ send += size;
}
}
@@ -261,6 +286,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
sent = rc > 0 ? rc : 0;
}
+ if (send == sent) {
+ ready = 1;
+ }
+
c->sent += sent;
for (cl = in; cl; cl = cl->next) {
@@ -300,6 +329,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
break;
}
+ if (ready) {
+ return cl;
+ }
+
in = cl;
if (eagain) {
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index d1da06368..818676ae9 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -763,26 +763,30 @@ int ngx_worker_thread_cycle(void *data)
ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
ngx_log_t *log)
{
- ssize_t n;
- ngx_err_t err;
- struct iovec iov[1];
- struct msghdr msg;
- struct cmsghdr cm;
+ ssize_t n;
+ ngx_err_t err;
+ struct iovec iov[1];
+ struct msghdr msg;
#if (HAVE_MSGHDR_MSG_CONTROL)
+ union {
+ struct cmsghdr cm;
+ char space[CMSG_SPACE(sizeof(int))];
+ } cmsg;
+
if (ch->fd == -1) {
msg.msg_control = NULL;
msg.msg_controllen = 0;
} else {
- msg.msg_control = (caddr_t) &cm;
- msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
- cm.cmsg_len = sizeof(struct cmsghdr) + sizeof(int);
- cm.cmsg_level = SOL_SOCKET;
- cm.cmsg_type = SCM_RIGHTS;
- *((int *) ((char *) &cm + sizeof(struct cmsghdr))) = ch->fd;
+ cmsg.cm.cmsg_len = sizeof(cmsg);
+ cmsg.cm.cmsg_level = SOL_SOCKET;
+ cmsg.cm.cmsg_type = SCM_RIGHTS;
+ *(int *) CMSG_DATA(&cmsg) = ch->fd;
}
#else
@@ -825,12 +829,19 @@ ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
ngx_log_t *log)
{
- int fd;
- ssize_t n;
- ngx_err_t err;
- struct iovec iov[1];
- struct msghdr msg;
- struct cmsghdr cm;
+ ssize_t n;
+ ngx_err_t err;
+ struct iovec iov[1];
+ struct msghdr msg;
+
+#if (HAVE_MSGHDR_MSG_CONTROL)
+ union {
+ struct cmsghdr cm;
+ char space[CMSG_SPACE(sizeof(int))];
+ } cmsg;
+#else
+ int fd;
+#endif
iov[0].iov_base = (char *) ch;
iov[0].iov_len = size;
@@ -841,8 +852,8 @@ ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
msg.msg_iovlen = 1;
#if (HAVE_MSGHDR_MSG_CONTROL)
- msg.msg_control = (caddr_t) &cm;
- msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
#else
msg.msg_accrights = (caddr_t) &fd;
msg.msg_accrightslen = sizeof(int);
@@ -870,20 +881,22 @@ ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
if (ch->command == NGX_CMD_OPEN_CHANNEL) {
- if (cm.cmsg_len < sizeof(struct cmsghdr) + sizeof(int)) {
+ if (cmsg.cm.cmsg_len < sizeof(cmsg)) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned too small ancillary data");
return NGX_ERROR;
}
- if (cm.cmsg_level != SOL_SOCKET || cm.cmsg_type != SCM_RIGHTS) {
+ if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS)
+ {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned invalid ancillary data "
- "level %d or type %d", cm.cmsg_level, cm.cmsg_type);
+ "level %d or type %d",
+ cmsg.cm.cmsg_level, cmsg.cm.cmsg_type);
return NGX_ERROR;
}
- ch->fd = *((int *) ((char *) &cm + sizeof(struct cmsghdr)));
+ ch->fd = *(int *) CMSG_DATA(&cmsg);
}
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {