Mercurial > hg > nginx
comparison src/os/unix/ngx_freebsd_sendfile_chain.c @ 143:5526213be452
nginx-0.0.1-2003-10-10-19:10:50 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 10 Oct 2003 15:10:50 +0000 |
parents | cb77c084acdb |
children | ef8c87afcfc5 |
comparison
equal
deleted
inserted
replaced
142:cb77c084acdb | 143:5526213be452 |
---|---|
12 * with the part of the file in one packet. So we use TCP_NOPUSH (similar | 12 * with the part of the file in one packet. So we use TCP_NOPUSH (similar |
13 * to Linux's TCP_CORK) to postpone the sending - it not only sends the header | 13 * to Linux's TCP_CORK) to postpone the sending - it not only sends the header |
14 * and the first part of the file in one packet but also sends 4K pages | 14 * and the first part of the file in one packet but also sends 4K pages |
15 * in the full packets. | 15 * in the full packets. |
16 * | 16 * |
17 * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not not flush | 17 * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush |
18 * the pending data that less than MSS and the data sent with 5 second delay. | 18 * the pending data that less than MSS so the data is sent with 5 second delay. |
19 * So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection | 19 * We do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used |
20 * is not needed to be keepalive. | 20 * for non-keepalive HTTP connections. |
21 */ | 21 */ |
22 | 22 |
23 | 23 |
24 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) | 24 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) |
25 { | 25 { |
26 int rc, eintr, tcp_nopush; | 26 int rc, eintr; |
27 char *prev; | 27 char *prev; |
28 ssize_t hsize, size; | 28 ssize_t hsize, size; |
29 off_t sent; | 29 off_t sent; |
30 struct iovec *iov; | 30 struct iovec *iov; |
31 struct sf_hdtr hdtr; | 31 struct sf_hdtr hdtr; |
32 ngx_err_t err; | 32 ngx_err_t err; |
33 ngx_array_t header, trailer; | 33 ngx_array_t header, trailer; |
34 ngx_hunk_t *file; | 34 ngx_hunk_t *file; |
35 ngx_chain_t *ce, *tail; | 35 ngx_chain_t *ce, *tail; |
36 | 36 |
37 tcp_nopush = 0; | |
38 | |
39 do { | 37 do { |
40 ce = in; | 38 ce = in; |
41 file = NULL; | 39 file = NULL; |
42 hsize = 0; | 40 hsize = 0; |
43 eintr = 0; | 41 eintr = 0; |
45 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), | 43 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), |
46 NGX_CHAIN_ERROR); | 44 NGX_CHAIN_ERROR); |
47 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), | 45 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), |
48 NGX_CHAIN_ERROR); | 46 NGX_CHAIN_ERROR); |
49 | 47 |
50 /* create the header iovec */ | 48 /* create the iovec and coalesce the neighbouring chain entries */ |
51 | 49 |
52 #if 0 | 50 prev = NULL; |
53 if (ngx_hunk_in_memory_only(ce->hunk) || ngx_hunk_special(ce->hunk)) { | 51 iov = NULL; |
54 #endif | 52 |
55 prev = NULL; | 53 for (ce = in; ce; ce = ce->next) { |
56 iov = NULL; | 54 if (ngx_hunk_special(ce->hunk)) { |
57 | 55 continue; |
58 /* create the iovec and coalesce the neighbouring chain entries */ | 56 } |
59 | 57 |
60 for ( /* void */; ce; ce = ce->next) { | 58 if (!ngx_hunk_in_memory_only(ce->hunk)) { |
61 if (ngx_hunk_special(ce->hunk)) { | 59 break; |
62 continue; | 60 } |
63 } | 61 |
64 | 62 if (prev == ce->hunk->pos) { |
65 if (!ngx_hunk_in_memory_only(ce->hunk)) { | 63 iov->iov_len += ce->hunk->last - ce->hunk->pos; |
66 break; | 64 prev = ce->hunk->last; |
67 } | 65 |
68 | 66 } else { |
69 if (prev == ce->hunk->pos) { | 67 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); |
70 iov->iov_len += ce->hunk->last - ce->hunk->pos; | 68 iov->iov_base = ce->hunk->pos; |
71 prev = ce->hunk->last; | 69 iov->iov_len = ce->hunk->last - ce->hunk->pos; |
72 | 70 prev = ce->hunk->last; |
73 } else { | 71 } |
74 ngx_test_null(iov, ngx_push_array(&header), | 72 |
75 NGX_CHAIN_ERROR); | 73 hsize += ce->hunk->last - ce->hunk->pos; |
76 iov->iov_base = ce->hunk->pos; | 74 } |
77 iov->iov_len = ce->hunk->last - ce->hunk->pos; | |
78 prev = ce->hunk->last; | |
79 } | |
80 | |
81 hsize += ce->hunk->last - ce->hunk->pos; | |
82 } | |
83 #if 0 | |
84 } | |
85 #endif | |
86 | 75 |
87 /* TODO: coalesce the neighbouring file hunks */ | 76 /* TODO: coalesce the neighbouring file hunks */ |
88 | 77 |
89 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { | 78 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { |
90 file = ce->hunk; | 79 file = ce->hunk; |
91 ce = ce->next; | 80 ce = ce->next; |
92 } | 81 } |
93 | 82 |
94 /* create the trailer iovec */ | 83 /* create the iovec and coalesce the neighbouring chain entries */ |
95 | 84 |
96 #if 0 | 85 prev = NULL; |
97 if (ce | 86 iov = NULL; |
98 && (ngx_hunk_in_memory_only(ce->hunk) | 87 |
99 || ngx_hunk_special(ce->hunk))) | 88 for ( /* void */; ce; ce = ce->next) { |
100 { | 89 if (ngx_hunk_special(ce->hunk)) { |
101 #endif | 90 continue; |
102 prev = NULL; | 91 } |
103 iov = NULL; | 92 |
104 | 93 if (!ngx_hunk_in_memory_only(ce->hunk)) { |
105 /* create the iovec and coalesce the neighbouring chain entries */ | 94 break; |
106 | 95 } |
107 for ( /* void */; ce; ce = ce->next) { | 96 |
108 if (ngx_hunk_special(ce->hunk)) { | 97 if (prev == ce->hunk->pos) { |
109 continue; | 98 iov->iov_len += ce->hunk->last - ce->hunk->pos; |
110 } | 99 prev = ce->hunk->last; |
111 | 100 |
112 if (!ngx_hunk_in_memory_only(ce->hunk)) { | 101 } else { |
113 break; | 102 ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR); |
114 } | 103 iov->iov_base = ce->hunk->pos; |
115 | 104 iov->iov_len = ce->hunk->last - ce->hunk->pos; |
116 if (prev == ce->hunk->pos) { | 105 prev = ce->hunk->last; |
117 iov->iov_len += ce->hunk->last - ce->hunk->pos; | 106 } |
118 prev = ce->hunk->last; | 107 } |
119 | |
120 } else { | |
121 ngx_test_null(iov, ngx_push_array(&trailer), | |
122 NGX_CHAIN_ERROR); | |
123 iov->iov_base = ce->hunk->pos; | |
124 iov->iov_len = ce->hunk->last - ce->hunk->pos; | |
125 prev = ce->hunk->last; | |
126 } | |
127 } | |
128 #if 0 | |
129 } | |
130 #endif | |
131 | 108 |
132 tail = ce; | 109 tail = ce; |
133 | 110 |
134 if (file) { | 111 if (file) { |
135 | 112 |
136 if (!c->tcp_nopush && c->tcp_nopush_enabled) { | 113 if (ngx_freebsd_use_tcp_nopush && !c->tcp_nopush) { |
137 c->tcp_nopush = 1; | 114 c->tcp_nopush = 1; |
138 tcp_nopush = 1; | 115 |
116 ngx_log_debug(c->log, "NOPUSH"); | |
117 | |
139 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { | 118 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { |
140 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, | 119 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, |
141 ngx_tcp_nopush_n " failed"); | 120 ngx_tcp_nopush_n " failed"); |
142 return NGX_CHAIN_ERROR; | 121 return NGX_CHAIN_ERROR; |
143 } | 122 } |
144 ngx_log_debug(c->log, "NOPUSH"); | |
145 } | 123 } |
146 | 124 |
147 hdtr.headers = (struct iovec *) header.elts; | 125 hdtr.headers = (struct iovec *) header.elts; |
148 hdtr.hdr_cnt = header.nelts; | 126 hdtr.hdr_cnt = header.nelts; |
149 hdtr.trailers = (struct iovec *) trailer.elts; | 127 hdtr.trailers = (struct iovec *) trailer.elts; |
180 rc _ file->file_pos _ sent _ | 158 rc _ file->file_pos _ sent _ |
181 (size_t) (file->file_last - file->file_pos) + hsize); | 159 (size_t) (file->file_last - file->file_pos) + hsize); |
182 #endif | 160 #endif |
183 | 161 |
184 } else { | 162 } else { |
185 if (hsize) { | 163 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts); |
186 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts); | 164 |
187 | 165 if (rc == -1) { |
188 if (rc == -1) { | 166 err = ngx_errno; |
189 err = ngx_errno; | 167 if (err == NGX_EAGAIN) { |
190 if (err == NGX_EAGAIN) { | 168 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN"); |
191 ngx_log_error(NGX_LOG_INFO, c->log, err, | 169 |
192 "writev() EAGAIN"); | 170 } else if (err == NGX_EINTR) { |
193 | 171 eintr = 1; |
194 } else if (err == NGX_EINTR) { | 172 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR"); |
195 eintr = 1; | 173 |
196 ngx_log_error(NGX_LOG_INFO, c->log, err, | 174 } else { |
197 "writev() EINTR"); | 175 ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed"); |
198 | 176 return NGX_CHAIN_ERROR; |
199 } else { | 177 } |
200 ngx_log_error(NGX_LOG_CRIT, c->log, err, | 178 } |
201 "writev() failed"); | 179 |
202 return NGX_CHAIN_ERROR; | 180 sent = rc > 0 ? rc : 0; |
203 } | |
204 } | |
205 | |
206 sent = rc > 0 ? rc : 0; | |
207 | 181 |
208 #if (NGX_DEBUG_WRITE_CHAIN) | 182 #if (NGX_DEBUG_WRITE_CHAIN) |
209 ngx_log_debug(c->log, "writev: %qd" _ sent); | 183 ngx_log_debug(c->log, "writev: %qd" _ sent); |
210 #endif | 184 #endif |
211 | |
212 } else { | |
213 sent = 0; | |
214 } | |
215 } | 185 } |
216 | 186 |
217 c->sent += sent; | 187 c->sent += sent; |
218 | 188 |
219 for (ce = in; ce && sent > 0; ce = ce->next) { | 189 for (ce = in; ce && sent > 0; ce = ce->next) { |