Mercurial > hg > nginx-quic
comparison src/core/ngx_output_chain.c @ 160:e7e094d34162
nginx-0.0.1-2003-10-27-11:53:49 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 27 Oct 2003 08:53:49 +0000 |
parents | |
children | 96993d4d5067 |
comparison
equal
deleted
inserted
replaced
159:981e4af2a425 | 160:e7e094d34162 |
---|---|
1 | |
2 #include <ngx_config.h> | |
3 #include <ngx_core.h> | |
4 | |
5 | |
6 #define NGX_NONE 1 | |
7 | |
8 | |
9 ngx_inline static int ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx, | |
10 ngx_hunk_t *hunk); | |
11 static int ngx_output_chain_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src, | |
12 int sendfile); | |
13 | |
14 | |
15 int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) | |
16 { | |
17 int rc, last; | |
18 ssize_t size, hsize; | |
19 ngx_chain_t *cl, *out, **last_out; | |
20 | |
21 /* | |
22 * the short path for the case when the chain ctx->in is empty | |
23 * and the incoming chain is empty too or it has the single hunk | |
24 * that does not require the copy | |
25 */ | |
26 | |
27 if (ctx->in == NULL) { | |
28 | |
29 if (in == NULL) { | |
30 return ctx->output_filter(ctx->output_ctx, in); | |
31 } | |
32 | |
33 if (!ctx->copy_chain | |
34 && in->next == NULL | |
35 && (!ngx_output_chain_need_to_copy(ctx, in->hunk))) | |
36 { | |
37 return ctx->output_filter(ctx->output_ctx, in); | |
38 } | |
39 } | |
40 | |
41 /* add the incoming hunk to the chain ctx->in */ | |
42 | |
43 if (in) { | |
44 if (ngx_chain_add_copy(ctx->pool, &ctx->in, in) == NGX_ERROR) { | |
45 return NGX_ERROR; | |
46 } | |
47 } | |
48 | |
49 last = NGX_NONE; | |
50 last_out = &out; | |
51 | |
52 for ( ;; ) { | |
53 | |
54 while (ctx->in) { | |
55 | |
56 if (!ngx_output_chain_need_to_copy(ctx, ctx->in->hunk)) { | |
57 | |
58 /* move the chain link to the chain out */ | |
59 | |
60 cl = ctx->in; | |
61 ctx->in = cl->next; | |
62 | |
63 *last_out = cl; | |
64 last_out = &cl->next; | |
65 cl->next = NULL; | |
66 | |
67 continue; | |
68 } | |
69 | |
70 if (ctx->hunk == NULL) { | |
71 | |
72 /* get the free hunk */ | |
73 | |
74 if (ctx->free) { | |
75 ctx->hunk = ctx->free->hunk; | |
76 ctx->free = ctx->free->next; | |
77 | |
78 } else if (ctx->hunks < ctx->bufs.num) { | |
79 | |
80 size = ctx->bufs.size; | |
81 | |
82 if (ctx->in->hunk->type & NGX_HUNK_LAST) { | |
83 | |
84 hsize = ngx_hunk_size(ctx->in->hunk); | |
85 | |
86 if (hsize < ctx->bufs.size) { | |
87 | |
88 /* | |
89 * allocate small temp hunk for the small last hunk | |
90 * or its small last part | |
91 */ | |
92 | |
93 size = hsize; | |
94 | |
95 } else if (ctx->bufs.num == 1 | |
96 && (hsize < ctx->bufs.size | |
97 + (ctx->bufs.size >> 2))) | |
98 { | |
99 /* | |
100 * allocate a temp hunk that equals | |
101 * to the last hunk if the last hunk size is lesser | |
102 * than 1.25 of bufs.size and a temp hunk is single | |
103 */ | |
104 | |
105 size = hsize; | |
106 } | |
107 } | |
108 | |
109 ngx_test_null(ctx->hunk, | |
110 ngx_create_temp_hunk(ctx->pool, size, 0, 0), | |
111 NGX_ERROR); | |
112 ctx->hunk->tag = ctx->tag; | |
113 ctx->hunk->type |= NGX_HUNK_RECYCLED; | |
114 ctx->hunks++; | |
115 | |
116 } else { | |
117 break; | |
118 } | |
119 } | |
120 | |
121 rc = ngx_output_chain_copy_hunk(ctx->hunk, ctx->in->hunk, | |
122 ctx->sendfile); | |
123 | |
124 if (rc == NGX_ERROR) { | |
125 return rc; | |
126 } | |
127 | |
128 if (rc == NGX_AGAIN) { | |
129 if (out) { | |
130 break; | |
131 } | |
132 return rc; | |
133 } | |
134 | |
135 /* delete the completed hunk from the chain ctx->in */ | |
136 | |
137 if (ngx_hunk_size(ctx->in->hunk) == 0) { | |
138 ctx->in = ctx->in->next; | |
139 } | |
140 | |
141 ngx_alloc_link_and_set_hunk(cl, ctx->hunk, ctx->pool, NGX_ERROR); | |
142 *last_out = cl; | |
143 last_out = &cl->next; | |
144 ctx->hunk = NULL; | |
145 | |
146 if (ctx->free == NULL) { | |
147 break; | |
148 } | |
149 } | |
150 | |
151 if (out == NULL && last != NGX_NONE) { | |
152 return last; | |
153 } | |
154 | |
155 last = ctx->output_filter(ctx->output_ctx, out); | |
156 | |
157 ngx_chain_update_chains(&ctx->free, &ctx->busy, &out, ctx->tag); | |
158 last_out = &out; | |
159 } | |
160 } | |
161 | |
162 | |
163 ngx_inline static int ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx, | |
164 ngx_hunk_t *hunk) | |
165 { | |
166 if (ngx_hunk_special(hunk)) { | |
167 return 0; | |
168 } | |
169 | |
170 if (!ctx->sendfile) { | |
171 return 1; | |
172 } | |
173 | |
174 if (ctx->need_in_memory && (!(hunk->type & NGX_HUNK_IN_MEMORY))) { | |
175 return 1; | |
176 } | |
177 | |
178 | |
179 if (ctx->need_in_temp && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))) { | |
180 return 1; | |
181 } | |
182 | |
183 return 0; | |
184 } | |
185 | |
186 | |
187 static int ngx_output_chain_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src, | |
188 int sendfile) | |
189 { | |
190 ssize_t n, size; | |
191 | |
192 size = ngx_hunk_size(src); | |
193 | |
194 if (size > (dst->end - dst->pos)) { | |
195 size = dst->end - dst->pos; | |
196 } | |
197 | |
198 if (src->type & NGX_HUNK_IN_MEMORY) { | |
199 ngx_memcpy(dst->pos, src->pos, size); | |
200 src->pos += size; | |
201 dst->last += size; | |
202 | |
203 if (src->type & NGX_HUNK_FILE) { | |
204 src->file_pos += size; | |
205 } | |
206 | |
207 if ((src->type & NGX_HUNK_LAST) && src->pos == src->last) { | |
208 dst->type |= NGX_HUNK_LAST; | |
209 } | |
210 | |
211 } else { | |
212 n = ngx_read_file(src->file, dst->pos, size, src->file_pos); | |
213 | |
214 if (n == 0) { | |
215 ngx_log_debug(src->file->log, "READ: %qd:%qd %X:%X %X:%X" _ | |
216 src->file_pos _ src->file_last _ | |
217 dst->pos _ dst->last _ dst->start _ dst->end); | |
218 } | |
219 | |
220 if (n == NGX_ERROR) { | |
221 return n; | |
222 } | |
223 | |
224 #if (NGX_FILE_AIO_READ) | |
225 if (n == NGX_AGAIN) { | |
226 return n; | |
227 } | |
228 #endif | |
229 | |
230 if (n != size) { | |
231 ngx_log_error(NGX_LOG_ALERT, src->file->log, 0, | |
232 ngx_read_file_n " reads only %d of %d from file", | |
233 n, size); | |
234 if (n == 0) { | |
235 return NGX_ERROR; | |
236 } | |
237 } | |
238 | |
239 src->file_pos += n; | |
240 dst->last += n; | |
241 | |
242 if (!sendfile) { | |
243 dst->type &= ~NGX_HUNK_FILE; | |
244 } | |
245 | |
246 if ((src->type & NGX_HUNK_LAST) && src->file_pos == src->file_last) { | |
247 dst->type |= NGX_HUNK_LAST; | |
248 } | |
249 } | |
250 | |
251 return NGX_OK; | |
252 } |