Mercurial > hg > nginx
comparison src/os/unix/ngx_freebsd_sendfile_chain.c @ 142:cb77c084acdb
nginx-0.0.1-2003-10-09-11:00:45 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 09 Oct 2003 07:00:45 +0000 |
parents | 6dfda4cf5200 |
children | 5526213be452 |
comparison
equal
deleted
inserted
replaced
141:656d468f4ead | 142:cb77c084acdb |
---|---|
1 | 1 |
2 #include <ngx_config.h> | 2 #include <ngx_config.h> |
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_event.h> | |
4 #include <ngx_freebsd_init.h> | 5 #include <ngx_freebsd_init.h> |
5 | 6 |
6 | 7 |
7 /* | 8 /* |
8 sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 and 1176 | 9 * sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 and 1176 |
9 or in 6 packets: 5x1460 and 892. Besides although sendfile() allows | 10 * or in 6 packets: 5x1460 and 892. Besides although sendfile() allows |
10 to pass the header and the trailer it never sends the header or the trailer | 11 * to pass the header and the trailer it never sends the header or the trailer |
11 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 |
12 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 |
13 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 |
14 in the full packets. | 15 * in the full packets. |
15 | 16 * |
16 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 not flush |
17 the pending data that less than MSS and the data sent with 5 second delay. | 18 * the pending data that less than MSS and the data sent with 5 second delay. |
18 So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection | 19 * So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection |
19 is not needed not keepalive. | 20 * is not needed to be keepalive. |
20 */ | 21 */ |
21 | 22 |
22 | 23 |
23 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) |
24 { | 25 { |
25 int rc, eintr, tcp_nopush; | 26 int rc, eintr, tcp_nopush; |
45 NGX_CHAIN_ERROR); | 46 NGX_CHAIN_ERROR); |
46 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), | 47 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), |
47 NGX_CHAIN_ERROR); | 48 NGX_CHAIN_ERROR); |
48 | 49 |
49 /* create the header iovec */ | 50 /* create the header iovec */ |
50 if (ngx_hunk_in_memory_only(ce->hunk)) { | 51 |
52 #if 0 | |
53 if (ngx_hunk_in_memory_only(ce->hunk) || ngx_hunk_special(ce->hunk)) { | |
54 #endif | |
51 prev = NULL; | 55 prev = NULL; |
52 iov = NULL; | 56 iov = NULL; |
53 | 57 |
54 /* create the iovec and coalesce the neighbouring chain entries */ | 58 /* create the iovec and coalesce the neighbouring chain entries */ |
55 while (ce && ngx_hunk_in_memory_only(ce->hunk)) { | 59 |
60 for ( /* void */; ce; ce = ce->next) { | |
61 if (ngx_hunk_special(ce->hunk)) { | |
62 continue; | |
63 } | |
64 | |
65 if (!ngx_hunk_in_memory_only(ce->hunk)) { | |
66 break; | |
67 } | |
56 | 68 |
57 if (prev == ce->hunk->pos) { | 69 if (prev == ce->hunk->pos) { |
58 iov->iov_len += ce->hunk->last - ce->hunk->pos; | 70 iov->iov_len += ce->hunk->last - ce->hunk->pos; |
59 prev = ce->hunk->last; | 71 prev = ce->hunk->last; |
60 | 72 |
65 iov->iov_len = ce->hunk->last - ce->hunk->pos; | 77 iov->iov_len = ce->hunk->last - ce->hunk->pos; |
66 prev = ce->hunk->last; | 78 prev = ce->hunk->last; |
67 } | 79 } |
68 | 80 |
69 hsize += ce->hunk->last - ce->hunk->pos; | 81 hsize += ce->hunk->last - ce->hunk->pos; |
70 | 82 } |
71 ce = ce->next; | 83 #if 0 |
72 } | 84 } |
73 } | 85 #endif |
74 | 86 |
75 /* TODO: coalesce the neighbouring file hunks */ | 87 /* TODO: coalesce the neighbouring file hunks */ |
88 | |
76 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { | 89 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { |
77 file = ce->hunk; | 90 file = ce->hunk; |
78 ce = ce->next; | 91 ce = ce->next; |
79 } | 92 } |
80 | 93 |
81 /* create the trailer iovec */ | 94 /* create the trailer iovec */ |
82 if (ce && ngx_hunk_in_memory_only(ce->hunk)) { | 95 |
96 #if 0 | |
97 if (ce | |
98 && (ngx_hunk_in_memory_only(ce->hunk) | |
99 || ngx_hunk_special(ce->hunk))) | |
100 { | |
101 #endif | |
83 prev = NULL; | 102 prev = NULL; |
84 iov = NULL; | 103 iov = NULL; |
85 | 104 |
86 /* create the iovec and coalesce the neighbouring chain entries */ | 105 /* create the iovec and coalesce the neighbouring chain entries */ |
87 while (ce && ngx_hunk_in_memory_only(ce->hunk)) { | 106 |
107 for ( /* void */; ce; ce = ce->next) { | |
108 if (ngx_hunk_special(ce->hunk)) { | |
109 continue; | |
110 } | |
111 | |
112 if (!ngx_hunk_in_memory_only(ce->hunk)) { | |
113 break; | |
114 } | |
88 | 115 |
89 if (prev == ce->hunk->pos) { | 116 if (prev == ce->hunk->pos) { |
90 iov->iov_len += ce->hunk->last - ce->hunk->pos; | 117 iov->iov_len += ce->hunk->last - ce->hunk->pos; |
91 prev = ce->hunk->last; | 118 prev = ce->hunk->last; |
92 | 119 |
95 NGX_CHAIN_ERROR); | 122 NGX_CHAIN_ERROR); |
96 iov->iov_base = ce->hunk->pos; | 123 iov->iov_base = ce->hunk->pos; |
97 iov->iov_len = ce->hunk->last - ce->hunk->pos; | 124 iov->iov_len = ce->hunk->last - ce->hunk->pos; |
98 prev = ce->hunk->last; | 125 prev = ce->hunk->last; |
99 } | 126 } |
100 | 127 } |
101 ce = ce->next; | 128 #if 0 |
102 } | 129 } |
103 } | 130 #endif |
104 | 131 |
105 tail = ce; | 132 tail = ce; |
106 | 133 |
107 if (file) { | 134 if (file) { |
108 | 135 |
153 rc _ file->file_pos _ sent _ | 180 rc _ file->file_pos _ sent _ |
154 (size_t) (file->file_last - file->file_pos) + hsize); | 181 (size_t) (file->file_last - file->file_pos) + hsize); |
155 #endif | 182 #endif |
156 | 183 |
157 } else { | 184 } else { |
158 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts); | 185 if (hsize) { |
159 | 186 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts); |
160 if (rc == -1) { | 187 |
161 err = ngx_errno; | 188 if (rc == -1) { |
162 if (err == NGX_EAGAIN) { | 189 err = ngx_errno; |
163 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN"); | 190 if (err == NGX_EAGAIN) { |
164 | 191 ngx_log_error(NGX_LOG_INFO, c->log, err, |
165 } else if (err == NGX_EINTR) { | 192 "writev() EAGAIN"); |
166 eintr = 1; | 193 |
167 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR"); | 194 } else if (err == NGX_EINTR) { |
168 | 195 eintr = 1; |
169 } else { | 196 ngx_log_error(NGX_LOG_INFO, c->log, err, |
170 ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed"); | 197 "writev() EINTR"); |
171 return NGX_CHAIN_ERROR; | 198 |
172 } | 199 } else { |
173 } | 200 ngx_log_error(NGX_LOG_CRIT, c->log, err, |
174 | 201 "writev() failed"); |
175 sent = rc > 0 ? rc : 0; | 202 return NGX_CHAIN_ERROR; |
203 } | |
204 } | |
205 | |
206 sent = rc > 0 ? rc : 0; | |
176 | 207 |
177 #if (NGX_DEBUG_WRITE_CHAIN) | 208 #if (NGX_DEBUG_WRITE_CHAIN) |
178 ngx_log_debug(c->log, "writev: %qd" _ sent); | 209 ngx_log_debug(c->log, "writev: %qd" _ sent); |
179 #endif | 210 #endif |
211 | |
212 } else { | |
213 sent = 0; | |
214 } | |
180 } | 215 } |
181 | 216 |
182 c->sent += sent; | 217 c->sent += sent; |
183 | 218 |
184 for (ce = in; ce && sent > 0; ce = ce->next) { | 219 for (ce = in; ce && sent > 0; ce = ce->next) { |
219 | 254 |
220 in = ce; | 255 in = ce; |
221 | 256 |
222 } while ((tail && tail == ce) || eintr); | 257 } while ((tail && tail == ce) || eintr); |
223 | 258 |
259 if (ce) { | |
260 c->write->ready = 0; | |
261 } | |
262 | |
224 return ce; | 263 return ce; |
225 } | 264 } |