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 }