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 }