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) {