comparison src/os/unix/ngx_freebsd_sendfile_chain.c @ 428:5e73d0ea4dab

nginx-0.0.11-2004-09-16-20:10:13 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 16 Sep 2004 16:10:13 +0000
parents f209f3391020
children da8c5707af39
comparison
equal deleted inserted replaced
427:0d08eabe5c7b 428:5e73d0ea4dab
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 can not send 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.3. Besides over the fast ethernet connection sendfile()
16 * may send the partially filled packets, i.e. the 8 file pages may 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 the 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 may 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
30
31 #define NGX_HEADERS 8
32 #define NGX_TRAILERS 4
29 33
30 34
31 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, 35 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
32 off_t limit) 36 off_t limit)
33 { 37 {
35 u_char *prev; 39 u_char *prev;
36 off_t fprev, sent, send, sprev, aligned; 40 off_t fprev, sent, send, sprev, aligned;
37 size_t hsize, fsize; 41 size_t hsize, fsize;
38 ssize_t size; 42 ssize_t size;
39 ngx_uint_t eintr, eagain, complete; 43 ngx_uint_t eintr, eagain, complete;
40 struct iovec *iov;
41 struct sf_hdtr hdtr;
42 ngx_err_t err; 44 ngx_err_t err;
43 ngx_buf_t *file; 45 ngx_buf_t *file;
44 ngx_array_t header, trailer; 46 ngx_array_t header, trailer;
45 ngx_event_t *wev; 47 ngx_event_t *wev;
46 ngx_chain_t *cl; 48 ngx_chain_t *cl;
49 struct sf_hdtr hdtr;
50 struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS];
47 51
48 wev = c->write; 52 wev = c->write;
49 53
50 if (!wev->ready) { 54 if (!wev->ready) {
51 return in; 55 return in;
63 67
64 #endif 68 #endif
65 69
66 send = 0; 70 send = 0;
67 eagain = 0; 71 eagain = 0;
72
73 header.elts = headers;
74 header.size = sizeof(struct iovec);
75 header.nalloc = NGX_HEADERS;
76 header.pool = c->pool;
77
78 trailer.elts = trailers;
79 trailer.size = sizeof(struct iovec);
80 trailer.nalloc = NGX_TRAILERS;
81 trailer.pool = c->pool;
68 82
69 for ( ;; ) { 83 for ( ;; ) {
70 file = NULL; 84 file = NULL;
71 fsize = 0; 85 fsize = 0;
72 hsize = 0; 86 hsize = 0;
73 eintr = 0; 87 eintr = 0;
74 complete = 0; 88 complete = 0;
75 sprev = send; 89 sprev = send;
76 90
77 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), 91 header.nelts = 0;
78 NGX_CHAIN_ERROR); 92 trailer.nelts = 0;
79 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec),
80 NGX_CHAIN_ERROR);
81 93
82 /* create the header iovec and coalesce the neighbouring bufs */ 94 /* create the header iovec and coalesce the neighbouring bufs */
83 95
84 prev = NULL; 96 prev = NULL;
85 iov = NULL; 97 iov = NULL;
104 116
105 if (prev == cl->buf->pos) { 117 if (prev == cl->buf->pos) {
106 iov->iov_len += size; 118 iov->iov_len += size;
107 119
108 } else { 120 } else {
109 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); 121 if (!(iov = ngx_array_push(&header))) {
122 return NGX_CHAIN_ERROR;
123 }
124
110 iov->iov_base = (void *) cl->buf->pos; 125 iov->iov_base = (void *) cl->buf->pos;
111 iov->iov_len = size; 126 iov->iov_len = size;
112 } 127 }
113 128
114 prev = cl->buf->pos + size; 129 prev = cl->buf->pos + size;
175 190
176 if (prev == cl->buf->pos) { 191 if (prev == cl->buf->pos) {
177 iov->iov_len += size; 192 iov->iov_len += size;
178 193
179 } else { 194 } else {
180 ngx_test_null(iov, ngx_push_array(&trailer), 195 if (!(iov = ngx_array_push(&trailer))) {
181 NGX_CHAIN_ERROR); 196 return NGX_CHAIN_ERROR;
197 }
198
182 iov->iov_base = (void *) cl->buf->pos; 199 iov->iov_base = (void *) cl->buf->pos;
183 iov->iov_len = size; 200 iov->iov_len = size;
184 } 201 }
185 202
186 prev = cl->buf->pos + size; 203 prev = cl->buf->pos + size;