Mercurial > hg > nginx
comparison src/os/unix/ngx_freebsd_sendfile_chain.c @ 362:7650aea1816f
nginx-0.0.7-2004-06-21-19:59:32 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 21 Jun 2004 15:59:32 +0000 |
parents | 446782c909b3 |
children | 744ccb59062d |
comparison
equal
deleted
inserted
replaced
361:446782c909b3 | 362:7650aea1816f |
---|---|
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 off_t limit) | |
32 { | 33 { |
33 int rc; | 34 int rc; |
34 u_char *prev; | 35 u_char *prev; |
35 off_t sent, fprev, send, limit; | 36 off_t fprev, sent, send, sprev, aligned; |
36 size_t hsize, fsize; | 37 size_t hsize, fsize; |
37 ssize_t size; | 38 ssize_t size; |
38 ngx_uint_t eintr, eagain, ready; | 39 ngx_uint_t eintr, eagain, complete; |
39 struct iovec *iov; | 40 struct iovec *iov; |
40 struct sf_hdtr hdtr; | 41 struct sf_hdtr hdtr; |
41 ngx_err_t err; | 42 ngx_err_t err; |
42 ngx_buf_t *file; | 43 ngx_buf_t *file; |
43 ngx_array_t header, trailer; | 44 ngx_array_t header, trailer; |
44 ngx_event_t *wev; | 45 ngx_event_t *wev; |
45 ngx_chain_t *cl, *tail; | 46 ngx_chain_t *cl; |
46 | 47 |
47 wev = c->write; | 48 wev = c->write; |
48 | 49 |
49 if (!wev->ready) { | 50 if (!wev->ready) { |
50 return in; | 51 return in; |
60 return NGX_CHAIN_ERROR; | 61 return NGX_CHAIN_ERROR; |
61 } | 62 } |
62 | 63 |
63 #endif | 64 #endif |
64 | 65 |
65 #if 1 | 66 send = 0; |
66 limit = 4096; | 67 eagain = 0; |
67 #else | 68 |
68 limit = OFF_T_MAX_VALUE; | 69 for ( ;; ) { |
69 #endif | |
70 | |
71 do { | |
72 file = NULL; | 70 file = NULL; |
73 fsize = 0; | 71 fsize = 0; |
74 hsize = 0; | 72 hsize = 0; |
75 send = 0; | |
76 eintr = 0; | 73 eintr = 0; |
77 eagain = 0; | 74 complete = 0; |
78 ready = 0; | 75 sprev = send; |
79 | 76 |
80 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), | 77 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), |
81 NGX_CHAIN_ERROR); | 78 NGX_CHAIN_ERROR); |
82 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), | 79 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), |
83 NGX_CHAIN_ERROR); | 80 NGX_CHAIN_ERROR); |
85 /* create the header iovec and coalesce the neighbouring bufs */ | 82 /* create the header iovec and coalesce the neighbouring bufs */ |
86 | 83 |
87 prev = NULL; | 84 prev = NULL; |
88 iov = NULL; | 85 iov = NULL; |
89 | 86 |
90 for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) { | 87 for (cl = in; |
88 cl && header.nelts < IOV_MAX && send < limit; | |
89 cl = cl->next) | |
90 { | |
91 if (ngx_buf_special(cl->buf)) { | 91 if (ngx_buf_special(cl->buf)) { |
92 continue; | 92 continue; |
93 } | 93 } |
94 | 94 |
95 if (!ngx_buf_in_memory_only(cl->buf)) { | 95 if (!ngx_buf_in_memory_only(cl->buf)) { |
116 send += size; | 116 send += size; |
117 } | 117 } |
118 | 118 |
119 /* get the file buf */ | 119 /* get the file buf */ |
120 | 120 |
121 if (cl && cl->buf->in_file) { | 121 if (cl && cl->buf->in_file && send < limit) { |
122 file = cl->buf; | 122 file = cl->buf; |
123 fsize = 0; | 123 fsize = 0; |
124 | 124 |
125 /* coalesce the neighbouring file bufs */ | 125 /* coalesce the neighbouring file bufs */ |
126 | 126 |
127 do { | 127 do { |
128 size = (size_t) (cl->buf->file_last - cl->buf->file_pos); | 128 size = (size_t) (cl->buf->file_last - cl->buf->file_pos); |
129 | 129 |
130 if (send + size > limit) { | 130 if (send + size > limit) { |
131 size = limit - send; | 131 size = limit - send; |
132 | |
133 aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) | |
134 & ~(ngx_pagesize - 1); | |
135 | |
136 if (aligned <= cl->buf->file_last) { | |
137 size = aligned - cl->buf->file_pos; | |
138 } | |
132 } | 139 } |
133 | 140 |
134 fsize += size; | 141 fsize += size; |
135 send += size; | 142 send += size; |
136 fprev = cl->buf->file_pos + size; | 143 fprev = cl->buf->file_pos + size; |
137 cl = cl->next; | 144 cl = cl->next; |
138 | 145 |
139 } while (cl | 146 } while (cl |
140 && cl->buf->in_file | 147 && cl->buf->in_file |
148 && send < limit | |
141 && file->file->fd == cl->buf->file->fd | 149 && file->file->fd == cl->buf->file->fd |
142 && fprev == cl->buf->file_pos); | 150 && fprev == cl->buf->file_pos); |
143 } | 151 } |
144 | 152 |
145 if (file) { | 153 if (file) { |
146 /* create the tailer iovec and coalesce the neighbouring bufs */ | 154 /* create the tailer iovec and coalesce the neighbouring bufs */ |
147 | 155 |
148 prev = NULL; | 156 prev = NULL; |
149 iov = NULL; | 157 iov = NULL; |
150 | 158 |
151 for ( /* void */; cl && trailer.nelts < IOV_MAX; cl = cl->next) { | 159 for (/* void */; |
160 cl && header.nelts < IOV_MAX && send < limit; | |
161 cl = cl->next) | |
162 { | |
152 if (ngx_buf_special(cl->buf)) { | 163 if (ngx_buf_special(cl->buf)) { |
153 continue; | 164 continue; |
154 } | 165 } |
155 | 166 |
156 if (!ngx_buf_in_memory_only(cl->buf)) { | 167 if (!ngx_buf_in_memory_only(cl->buf)) { |
175 | 186 |
176 prev = cl->buf->pos + size; | 187 prev = cl->buf->pos + size; |
177 send += size; | 188 send += size; |
178 } | 189 } |
179 } | 190 } |
180 | |
181 /* | |
182 * the tail is the rest of the chain that exceedes | |
183 * a single sendfile() capability | |
184 */ | |
185 | |
186 tail = cl; | |
187 | 191 |
188 if (file) { | 192 if (file) { |
189 | 193 |
190 if (ngx_freebsd_use_tcp_nopush | 194 if (ngx_freebsd_use_tcp_nopush |
191 && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET) | 195 && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET) |
284 } | 288 } |
285 | 289 |
286 sent = rc > 0 ? rc : 0; | 290 sent = rc > 0 ? rc : 0; |
287 } | 291 } |
288 | 292 |
289 if (send == sent) { | 293 if (send - sprev == sent) { |
290 ready = 1; | 294 complete = 1; |
291 } | 295 } |
292 | 296 |
293 c->sent += sent; | 297 c->sent += sent; |
294 | 298 |
295 for (cl = in; cl; cl = cl->next) { | 299 for (cl = in; cl; cl = cl->next) { |
326 cl->buf->file_pos += sent; | 330 cl->buf->file_pos += sent; |
327 } | 331 } |
328 | 332 |
329 break; | 333 break; |
330 } | 334 } |
331 | |
332 if (ready) { | |
333 return cl; | |
334 } | |
335 | |
336 in = cl; | |
337 | 335 |
338 if (eagain) { | 336 if (eagain) { |
339 | 337 |
340 /* | 338 /* |
341 * sendfile() can return EAGAIN even if it has sent | 339 * sendfile() can return EAGAIN even if it has sent |
343 * return EAGAIN right away and would not send anything. | 341 * return EAGAIN right away and would not send anything. |
344 * We use it as a hint. | 342 * We use it as a hint. |
345 */ | 343 */ |
346 | 344 |
347 wev->ready = 0; | 345 wev->ready = 0; |
348 break; | 346 return cl; |
349 } | 347 } |
350 | 348 |
351 /* "tail == in" means that a single sendfile() is complete */ | 349 if (eintr) { |
352 | 350 continue; |
353 } while ((tail && tail == in) || eintr); | 351 } |
354 | 352 |
355 if (in) { | 353 if (!complete) { |
356 wev->ready = 0; | 354 wev->ready = 0; |
355 return cl; | |
356 } | |
357 | |
358 if (send >= limit || cl == NULL) { | |
359 return cl; | |
360 } | |
361 | |
362 in = cl; | |
357 } | 363 } |
358 | |
359 return in; | |
360 } | 364 } |