Mercurial > hg > nginx-quic
comparison src/core/ngx_write_chain.c @ 62:8ccba41a678e
nginx-0.0.1-2003-02-12-09:55:42 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 12 Feb 2003 06:55:42 +0000 |
parents | |
children | 36d2c25cc9bb |
comparison
equal
deleted
inserted
replaced
61:4f3e2abcc2c4 | 62:8ccba41a678e |
---|---|
1 | |
2 #include <ngx_config.h> | |
3 | |
4 #include <ngx_core.h> | |
5 #include <ngx_types.h> | |
6 #include <ngx_alloc.h> | |
7 #include <ngx_array.h> | |
8 #include <ngx_hunk.h> | |
9 #include <ngx_connection.h> | |
10 #include <ngx_sendv.h> | |
11 #include <ngx_sendfile.h> | |
12 | |
13 #include <ngx_write_chain.h> | |
14 | |
15 | |
16 ngx_chain_t *ngx_write_chain(ngx_connection_t *c, ngx_chain_t *in, off_t flush) | |
17 { | |
18 int rc, i, last; | |
19 u_int flags; | |
20 char *prev; | |
21 off_t sent; | |
22 ngx_iovec_t *iov; | |
23 ngx_array_t header, trailer; | |
24 ngx_hunk_t *file; | |
25 ngx_chain_t *ce; | |
26 | |
27 ch = in; | |
28 file = NULL; | |
29 last = 0; | |
30 | |
31 ngx_init_array(header, c->pool, 10, sizeof(ngx_iovec_t), NGX_CHAIN_ERROR); | |
32 ngx_init_array(trailer, c->pool, 10, sizeof(ngx_iovec_t), NGX_CHAIN_ERROR); | |
33 | |
34 do { | |
35 header.nelts = 0; | |
36 trailer.nelts = 0; | |
37 | |
38 if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { | |
39 prev = NULL; | |
40 iov = NULL; | |
41 | |
42 /* create iovec and coalesce the neighbouring chain entries */ | |
43 while (ce && (ce->hunk->type & NGX_HUNK_IN_MEMORY)) | |
44 { | |
45 if (prev == ce->hunk->pos.mem) { | |
46 iov->ngx_iov_len += ce->hunk->last.mem - ce->hunk->pos.mem; | |
47 | |
48 } else { | |
49 ngx_test_null(iov, ngx_push_array(&header), | |
50 NGX_CHAIN_ERROR); | |
51 iov->ngx_iov_base = ce->hunk->pos.mem; | |
52 iov->ngx_iov_len = ce->hunk->last.mem - ce->hunk->pos.mem; | |
53 prev = ce->hunk->last.mem; | |
54 } | |
55 | |
56 if (ce->hunk->type & NGX_HUNK_LAST) { | |
57 last = 1; | |
58 } | |
59 | |
60 ce = ce->next; | |
61 } | |
62 } | |
63 | |
64 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { | |
65 file = ce->hunk; | |
66 ce = ce->next; | |
67 | |
68 if (ce->hunk->type & NGX_HUNK_LAST) { | |
69 last = 1; | |
70 } | |
71 } | |
72 | |
73 #if (HAVE_MAX_SENDFILE_IOVEC) | |
74 if (file && header->nelts > HAVE_MAX_SENDFILE_IOVEC) { | |
75 rc = ngx_sendv(c->fd, (ngx_iovec_t *) header->elts, header->nelts, | |
76 &sent); | |
77 } else { | |
78 #endif | |
79 if (ch && ch->hunk->type & NGX_HUNK_IN_MEMORY) { | |
80 prev = NULL; | |
81 iov = NULL; | |
82 | |
83 while (ch && (ch->hunk->type & NGX_HUNK_IN_MEMORY)) { | |
84 | |
85 if (prev == ch->hunk->pos.mem) { | |
86 iov->ngx_iov_len += | |
87 ch->hunk->last.mem - ch->hunk->pos.mem; | |
88 | |
89 } else { | |
90 ngx_test_null(iov, ngx_push_array(trailer), | |
91 NGX_CHAIN_ERROR); | |
92 iov->ngx_iov_base = ch->hunk->pos.mem; | |
93 iov->ngx_iov_len = | |
94 ch->hunk->last.mem - ch->hunk->pos.mem; | |
95 prev = ch->hunk->last.mem; | |
96 } | |
97 | |
98 if (ch->hunk->type & NGX_HUNK_LAST) { | |
99 last = 1; | |
100 } | |
101 | |
102 ch = ch->next; | |
103 } | |
104 } | |
105 | |
106 if (file) { | |
107 flags = ngx_sendfile_flags; | |
108 #if (HAVE_SENDFILE_DISCONNECT) | |
109 if (last && c->close) { | |
110 flags |= NGX_SENDFILE_DISCONNECT; | |
111 } | |
112 #endif | |
113 rc = ngx_sendfile(c, | |
114 (ngx_iovec_t *) header->elts, header->nelts, | |
115 file->file->fd, file->pos.file, | |
116 (size_t) (file->last.file - file->pos.file), | |
117 (ngx_iovec_t *) trailer->elts, trailer->nelts, | |
118 &sent, flags); | |
119 | |
120 #if (HAVE_AIO_EVENT) && !(HAVE_IOCP_EVENT) | |
121 } else if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | |
122 | |
123 sent = 0; | |
124 rc = NGX_AGAIN; | |
125 iov = (ngx_iovec_t *) header->elts; | |
126 for (i = 0; i < header->nelts; i++) { | |
127 rc = ngx_event_aio_write(c, iov[i].ngx_iov_base, | |
128 iov[i].ngx_iov_len); | |
129 | |
130 if (rc > 0) { | |
131 sent += rc; | |
132 } else { | |
133 break; | |
134 } | |
135 | |
136 if (rc < (int) iov->ngx_iov_len) { | |
137 break; | |
138 } | |
139 } | |
140 #endif | |
141 } else { | |
142 rc = ngx_sendv(c, (ngx_iovec_t *) header->elts, header->nelts); | |
143 | |
144 sent = rc > 0 ? rc: 0; | |
145 | |
146 #if (NGX_DEBUG_EVENT_WRITE) | |
147 ngx_log_debug(c->log, "sendv: " OFF_FMT _ sent); | |
148 #endif | |
149 } | |
150 #if (HAVE_MAX_SENDFILE_IOVEC) | |
151 } | |
152 #endif | |
153 if (rc == NGX_ERROR) | |
154 return (ngx_chain_t *) NGX_ERROR; | |
155 | |
156 c->sent += sent; | |
157 flush -= sent; | |
158 | |
159 for (ch = in; ch; ch = ch->next) { | |
160 | |
161 #if (NGX_DEBUG_EVENT_WRITE) | |
162 ngx_log_debug(c->log, "event write: %x " QX_FMT " " OFF_FMT _ | |
163 ch->hunk->type _ | |
164 ch->hunk->pos.file _ | |
165 ch->hunk->last.file - ch->hunk->pos.file); | |
166 #endif | |
167 | |
168 if (sent >= ch->hunk->last.file - ch->hunk->pos.file) { | |
169 sent -= ch->hunk->last.file - ch->hunk->pos.file; | |
170 ch->hunk->pos.file = ch->hunk->last.file; | |
171 | |
172 #if (NGX_DEBUG_EVENT_WRITE) | |
173 ngx_log_debug(c->log, "event write: " QX_FMT " 0 " OFF_FMT _ | |
174 ch->hunk->pos.file _ sent); | |
175 #endif | |
176 | |
177 /* | |
178 if (ch->hunk->type & NGX_HUNK_LAST) | |
179 break; | |
180 */ | |
181 | |
182 continue; | |
183 } | |
184 | |
185 ch->hunk->pos.file += sent; | |
186 | |
187 #if (NGX_DEBUG_EVENT_WRITE) | |
188 ngx_log_debug(c->log, "event write: " QX_FMT " " OFF_FMT _ | |
189 ch->hunk->pos.file _ | |
190 ch->hunk->last.file - ch->hunk->pos.file); | |
191 #endif | |
192 | |
193 break; | |
194 } | |
195 | |
196 /* flush hunks if threaded state */ | |
197 } while (c->write->context && flush > 0); | |
198 | |
199 ngx_destroy_array(&trailer); | |
200 ngx_destroy_array(&header); | |
201 | |
202 return ch; | |
203 } |