Mercurial > hg > nginx
comparison src/os/unix/ngx_linux_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 | e366ba5db8f8 |
children | f209f3391020 |
comparison
equal
deleted
inserted
replaced
361:446782c909b3 | 362:7650aea1816f |
---|---|
17 * | 17 * |
18 * Linux 2.4.21 has a new sendfile64() syscall #239. | 18 * Linux 2.4.21 has a new sendfile64() syscall #239. |
19 */ | 19 */ |
20 | 20 |
21 | 21 |
22 ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) | 22 ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, |
23 off_t limit) | |
23 { | 24 { |
24 int rc; | 25 int rc; |
25 u_char *prev; | 26 u_char *prev; |
26 off_t fprev; | 27 off_t fprev, send, sprev, aligned; |
27 size_t size, fsize, sent; | 28 size_t fsize; |
28 ngx_int_t eintr; | 29 ssize_t size, sent; |
30 ngx_uint_t eintr, complete; | |
29 struct iovec *iov; | 31 struct iovec *iov; |
30 ngx_err_t err; | 32 ngx_err_t err; |
31 ngx_buf_t *file; | 33 ngx_buf_t *file; |
32 ngx_array_t header; | 34 ngx_array_t header; |
33 ngx_event_t *wev; | 35 ngx_event_t *wev; |
34 ngx_chain_t *cl, *tail; | 36 ngx_chain_t *cl; |
35 #if (HAVE_SENDFILE64) | 37 #if (HAVE_SENDFILE64) |
36 off_t offset; | 38 off_t offset; |
37 #else | 39 #else |
38 int32_t offset; | 40 int32_t offset; |
39 #endif | 41 #endif |
42 | 44 |
43 if (!wev->ready) { | 45 if (!wev->ready) { |
44 return in; | 46 return in; |
45 } | 47 } |
46 | 48 |
47 do { | 49 send = 0; |
50 | |
51 for ( ;; ) { | |
48 file = NULL; | 52 file = NULL; |
49 fsize = 0; | 53 fsize = 0; |
50 eintr = 0; | 54 eintr = 0; |
55 complete = 0; | |
56 sprev = send; | |
51 | 57 |
52 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), | 58 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), |
53 NGX_CHAIN_ERROR); | 59 NGX_CHAIN_ERROR); |
54 | 60 |
55 prev = NULL; | 61 prev = NULL; |
56 iov = NULL; | 62 iov = NULL; |
57 | 63 |
58 /* create the iovec and coalesce the neighbouring bufs */ | 64 /* create the iovec and coalesce the neighbouring bufs */ |
59 | 65 |
60 for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) { | 66 for (cl = in; |
67 cl && header.nelts < IOV_MAX && send < limit; | |
68 cl = cl->next) | |
69 { | |
61 if (ngx_buf_special(cl->buf)) { | 70 if (ngx_buf_special(cl->buf)) { |
62 continue; | 71 continue; |
63 } | 72 } |
64 | 73 |
65 if (!ngx_buf_in_memory_only(cl->buf)) { | 74 if (!ngx_buf_in_memory_only(cl->buf)) { |
66 break; | 75 break; |
67 } | 76 } |
68 | 77 |
78 size = cl->buf->last - cl->buf->pos; | |
79 | |
80 if (send + size > limit) { | |
81 size = limit - send; | |
82 } | |
83 | |
69 if (prev == cl->buf->pos) { | 84 if (prev == cl->buf->pos) { |
70 iov->iov_len += cl->buf->last - cl->buf->pos; | 85 iov->iov_len += size; |
71 | 86 |
72 } else { | 87 } else { |
73 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); | 88 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); |
74 iov->iov_base = (void *) cl->buf->pos; | 89 iov->iov_base = (void *) cl->buf->pos; |
75 iov->iov_len = cl->buf->last - cl->buf->pos; | 90 iov->iov_len = size; |
76 } | 91 } |
77 | 92 |
78 prev = cl->buf->last; | 93 prev = cl->buf->pos + size; |
94 send += size; | |
79 } | 95 } |
80 | 96 |
81 /* set TCP_CORK if there is a header before a file */ | 97 /* set TCP_CORK if there is a header before a file */ |
82 | 98 |
83 if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET | 99 if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET |
105 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | 121 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, |
106 "tcp_nopush"); | 122 "tcp_nopush"); |
107 } | 123 } |
108 } | 124 } |
109 | 125 |
110 if (header.nelts == 0 && cl && cl->buf->in_file) { | 126 /* get the file buf */ |
111 | 127 |
112 /* get the file buf */ | 128 if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) { |
113 | |
114 file = cl->buf; | 129 file = cl->buf; |
115 fsize = (size_t) (file->file_last - file->file_pos); | 130 fsize = 0; |
116 fprev = file->file_last; | |
117 cl = cl->next; | |
118 | 131 |
119 /* coalesce the neighbouring file bufs */ | 132 /* coalesce the neighbouring file bufs */ |
120 | 133 |
121 while (cl && (cl->buf->in_file)) { | 134 do { |
122 if (file->file->fd != cl->buf->file->fd | 135 size = (size_t) (cl->buf->file_last - cl->buf->file_pos); |
123 || fprev != cl->buf->file_pos) | 136 |
124 { | 137 if (send + size > limit) { |
125 break; | 138 size = limit - send; |
126 } | 139 |
127 | 140 aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) |
128 fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos); | 141 & ~(ngx_pagesize - 1); |
129 fprev = cl->buf->file_last; | 142 |
143 if (aligned <= cl->buf->file_last) { | |
144 size = aligned - cl->buf->file_pos; | |
145 } | |
146 } | |
147 | |
148 fsize += size; | |
149 send += size; | |
150 fprev = cl->buf->file_pos + size; | |
130 cl = cl->next; | 151 cl = cl->next; |
131 } | 152 |
132 } | 153 } while (cl |
133 | 154 && cl->buf->in_file |
134 /* | 155 && send < limit |
135 * the tail is the rest of the chain that exceedes | 156 && file->file->fd == cl->buf->file->fd |
136 * a single sendfile() capability | 157 && fprev == cl->buf->file_pos); |
137 */ | 158 } |
138 | 159 |
139 tail = cl; | 160 if (file) { |
140 | |
141 if (fsize) { | |
142 #if (HAVE_SENDFILE64) | 161 #if (HAVE_SENDFILE64) |
143 offset = file->file_pos; | 162 offset = file->file_pos; |
144 #else | 163 #else |
145 offset = (int32_t) file->file_pos; | 164 offset = (int32_t) file->file_pos; |
146 #endif | 165 #endif |
194 sent = rc > 0 ? rc : 0; | 213 sent = rc > 0 ? rc : 0; |
195 | 214 |
196 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent); | 215 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent); |
197 } | 216 } |
198 | 217 |
218 if (send - sprev == sent) { | |
219 complete = 1; | |
220 } | |
221 | |
199 c->sent += sent; | 222 c->sent += sent; |
200 | 223 |
201 for (cl = in; cl; cl = cl->next) { | 224 for (cl = in; cl; cl = cl->next) { |
202 | 225 |
203 if (ngx_buf_special(cl->buf)) { | 226 if (ngx_buf_special(cl->buf)) { |
233 } | 256 } |
234 | 257 |
235 break; | 258 break; |
236 } | 259 } |
237 | 260 |
261 if (eintr) { | |
262 continue; | |
263 } | |
264 | |
265 if (!complete) { | |
266 wev->ready = 0; | |
267 return cl; | |
268 } | |
269 | |
270 if (send >= limit || cl == NULL) { | |
271 return cl; | |
272 } | |
273 | |
238 in = cl; | 274 in = cl; |
239 | |
240 /* "tail == in" means that a single sendfile() is complete */ | |
241 | |
242 } while ((tail && tail == in) || eintr); | |
243 | |
244 if (in) { | |
245 wev->ready = 0; | |
246 } | 275 } |
247 | |
248 return in; | |
249 } | 276 } |