Mercurial > hg > nginx
comparison src/os/unix/ngx_freebsd_sendfile_chain.c @ 361:446782c909b3
nginx-0.0.7-2004-06-20-23:54:15 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 20 Jun 2004 19:54:15 +0000 |
parents | e366ba5db8f8 |
children | 7650aea1816f |
comparison
equal
deleted
inserted
replaced
360:239e37d44a34 | 361:446782c909b3 |
---|---|
9 #include <ngx_event.h> | 9 #include <ngx_event.h> |
10 | 10 |
11 | 11 |
12 /* | 12 /* |
13 * Although FreeBSD sendfile() allows to pass a header and a trailer | 13 * Although FreeBSD sendfile() allows to pass a header and a trailer |
14 * it never sends a header with a part of the file in one packet until | 14 * it can not send a header with a part of the file in one packet until |
15 * FreeBSD 5.2-STABLE. Besides over the fast ethernet connection sendfile() | 15 * FreeBSD 5.2-STABLE. Besides over the fast ethernet connection sendfile() |
16 * can send the partially filled packets, i.e. the 8 file pages can be sent | 16 * may send the partially filled packets, i.e. the 8 file pages may be sent |
17 * as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet, | 17 * as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet, |
18 * and then again the 11 full 1460-bytes packets. | 18 * and then again the 11 full 1460-bytes packets. |
19 * | 19 * |
20 * So we use the TCP_NOPUSH option (similar to Linux's TCP_CORK) | 20 * So we use the TCP_NOPUSH option (similar to Linux's TCP_CORK) |
21 * to postpone the sending - it not only sends a header and the first part | 21 * to postpone the sending - it not only sends a header and the first part |
22 * of the file in one packet but also sends file pages in the full packets. | 22 * of the file in one packet but also sends file pages in the full packets. |
23 * | 23 * |
24 * But until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending | 24 * But until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending |
25 * data that less than MSS so that data can be sent with 5 second delay. | 25 * data that less than MSS so that data may be sent with 5 second delay. |
26 * So we do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used | 26 * So we do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used |
27 * for non-keepalive HTTP connections. | 27 * for non-keepalive HTTP connections. |
28 */ | 28 */ |
29 | 29 |
30 | 30 |
31 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) | 31 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) |
32 { | 32 { |
33 int rc; | 33 int rc; |
34 u_char *prev; | 34 u_char *prev; |
35 off_t sent, fprev; | 35 off_t sent, fprev, send, limit; |
36 size_t hsize, fsize; | 36 size_t hsize, fsize; |
37 ssize_t size; | 37 ssize_t size; |
38 ngx_int_t eintr, eagain; | 38 ngx_uint_t eintr, eagain, ready; |
39 struct iovec *iov; | 39 struct iovec *iov; |
40 struct sf_hdtr hdtr; | 40 struct sf_hdtr hdtr; |
41 ngx_err_t err; | 41 ngx_err_t err; |
42 ngx_buf_t *file; | 42 ngx_buf_t *file; |
43 ngx_array_t header, trailer; | 43 ngx_array_t header, trailer; |
60 return NGX_CHAIN_ERROR; | 60 return NGX_CHAIN_ERROR; |
61 } | 61 } |
62 | 62 |
63 #endif | 63 #endif |
64 | 64 |
65 #if 1 | |
66 limit = 4096; | |
67 #else | |
68 limit = OFF_T_MAX_VALUE; | |
69 #endif | |
70 | |
65 do { | 71 do { |
66 file = NULL; | 72 file = NULL; |
67 fsize = 0; | 73 fsize = 0; |
68 hsize = 0; | 74 hsize = 0; |
75 send = 0; | |
69 eintr = 0; | 76 eintr = 0; |
70 eagain = 0; | 77 eagain = 0; |
78 ready = 0; | |
71 | 79 |
72 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), | 80 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), |
73 NGX_CHAIN_ERROR); | 81 NGX_CHAIN_ERROR); |
74 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), | 82 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), |
75 NGX_CHAIN_ERROR); | 83 NGX_CHAIN_ERROR); |
86 | 94 |
87 if (!ngx_buf_in_memory_only(cl->buf)) { | 95 if (!ngx_buf_in_memory_only(cl->buf)) { |
88 break; | 96 break; |
89 } | 97 } |
90 | 98 |
99 size = cl->buf->last - cl->buf->pos; | |
100 | |
101 if (send + size > limit) { | |
102 size = limit - send; | |
103 } | |
104 | |
91 if (prev == cl->buf->pos) { | 105 if (prev == cl->buf->pos) { |
92 iov->iov_len += cl->buf->last - cl->buf->pos; | 106 iov->iov_len += size; |
93 | 107 |
94 } else { | 108 } else { |
95 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); | 109 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); |
96 iov->iov_base = (void *) cl->buf->pos; | 110 iov->iov_base = (void *) cl->buf->pos; |
97 iov->iov_len = cl->buf->last - cl->buf->pos; | 111 iov->iov_len = size; |
98 } | 112 } |
99 | 113 |
100 prev = cl->buf->last; | 114 prev = cl->buf->pos + size; |
101 hsize += cl->buf->last - cl->buf->pos; | 115 hsize += size; |
116 send += size; | |
102 } | 117 } |
103 | 118 |
104 /* get the file buf */ | 119 /* get the file buf */ |
105 | 120 |
106 if (cl && cl->buf->in_file) { | 121 if (cl && cl->buf->in_file) { |
107 file = cl->buf; | 122 file = cl->buf; |
108 fsize = (size_t) (file->file_last - file->file_pos); | 123 fsize = 0; |
109 fprev = file->file_last; | |
110 cl = cl->next; | |
111 | 124 |
112 /* coalesce the neighbouring file bufs */ | 125 /* coalesce the neighbouring file bufs */ |
113 | 126 |
114 while (cl && cl->buf->in_file) { | 127 do { |
115 if (file->file->fd != cl->buf->file->fd | 128 size = (size_t) (cl->buf->file_last - cl->buf->file_pos); |
116 || fprev != cl->buf->file_pos) | 129 |
117 { | 130 if (send + size > limit) { |
118 break; | 131 size = limit - send; |
119 } | 132 } |
120 | 133 |
121 fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos); | 134 fsize += size; |
122 fprev = cl->buf->file_last; | 135 send += size; |
136 fprev = cl->buf->file_pos + size; | |
123 cl = cl->next; | 137 cl = cl->next; |
124 } | 138 |
139 } while (cl | |
140 && cl->buf->in_file | |
141 && file->file->fd == cl->buf->file->fd | |
142 && fprev == cl->buf->file_pos); | |
125 } | 143 } |
126 | 144 |
127 if (file) { | 145 if (file) { |
128 /* create the tailer iovec and coalesce the neighbouring bufs */ | 146 /* create the tailer iovec and coalesce the neighbouring bufs */ |
129 | 147 |
137 | 155 |
138 if (!ngx_buf_in_memory_only(cl->buf)) { | 156 if (!ngx_buf_in_memory_only(cl->buf)) { |
139 break; | 157 break; |
140 } | 158 } |
141 | 159 |
160 size = cl->buf->last - cl->buf->pos; | |
161 | |
162 if (send + size > limit) { | |
163 size = limit - send; | |
164 } | |
165 | |
142 if (prev == cl->buf->pos) { | 166 if (prev == cl->buf->pos) { |
143 iov->iov_len += cl->buf->last - cl->buf->pos; | 167 iov->iov_len += size; |
144 | 168 |
145 } else { | 169 } else { |
146 ngx_test_null(iov, ngx_push_array(&trailer), | 170 ngx_test_null(iov, ngx_push_array(&trailer), |
147 NGX_CHAIN_ERROR); | 171 NGX_CHAIN_ERROR); |
148 iov->iov_base = (void *) cl->buf->pos; | 172 iov->iov_base = (void *) cl->buf->pos; |
149 iov->iov_len = cl->buf->last - cl->buf->pos; | 173 iov->iov_len = size; |
150 } | 174 } |
151 | 175 |
152 prev = cl->buf->last; | 176 prev = cl->buf->pos + size; |
177 send += size; | |
153 } | 178 } |
154 } | 179 } |
155 | 180 |
156 /* | 181 /* |
157 * the tail is the rest of the chain that exceedes | 182 * the tail is the rest of the chain that exceedes |
259 } | 284 } |
260 | 285 |
261 sent = rc > 0 ? rc : 0; | 286 sent = rc > 0 ? rc : 0; |
262 } | 287 } |
263 | 288 |
289 if (send == sent) { | |
290 ready = 1; | |
291 } | |
292 | |
264 c->sent += sent; | 293 c->sent += sent; |
265 | 294 |
266 for (cl = in; cl; cl = cl->next) { | 295 for (cl = in; cl; cl = cl->next) { |
267 | 296 |
268 if (ngx_buf_special(cl->buf)) { | 297 if (ngx_buf_special(cl->buf)) { |
296 if (cl->buf->in_file) { | 325 if (cl->buf->in_file) { |
297 cl->buf->file_pos += sent; | 326 cl->buf->file_pos += sent; |
298 } | 327 } |
299 | 328 |
300 break; | 329 break; |
330 } | |
331 | |
332 if (ready) { | |
333 return cl; | |
301 } | 334 } |
302 | 335 |
303 in = cl; | 336 in = cl; |
304 | 337 |
305 if (eagain) { | 338 if (eagain) { |