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 }