comparison src/http/ngx_http_output_filter.c @ 8:708f8bb772ec

nginx-0.0.1-2002-09-02-18:48:24 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 02 Sep 2002 14:48:24 +0000
parents src/http/ngx_http_filter.c@b5481d6fbbd4
children 6f58641241bb
comparison
equal deleted inserted replaced
7:b5481d6fbbd4 8:708f8bb772ec
1
2
3 #include <ngx_core.h>
4 #include <ngx_files.h>
5 #include <ngx_string.h>
6 #include <ngx_hunk.h>
7 #include <ngx_http.h>
8 #include <ngx_http_output_filter.h>
9
10
11 /* STUB */
12 int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
13
14
15
16 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src);
17
18 ngx_http_module_t ngx_http_output_filter_module;
19
20
21 /* STUB */
22 static ngx_http_output_filter_ctx_t module_ctx;
23
24 void ngx_http_output_filter_init()
25 {
26 module_ctx.hunk_size = 32 * 1024;
27 module_ctx.out.hunk = NULL;
28 module_ctx.out.next = NULL;
29 module_ctx.next_filter = ngx_http_write_filter;
30
31 ngx_http_output_filter_module.ctx = &module_ctx;
32 }
33 /* */
34
35
36 /*
37 flags NGX_HUNK_RECYCLED, NGX_HUNK_FLUSH, NGX_HUNK_LAST
38 */
39
40 int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
41 {
42 int rc, first;
43 size_t size;
44 ssize_t n;
45 ngx_chain_t *ce;
46 ngx_http_output_filter_ctx_t *ctx;
47
48 ctx = (ngx_http_output_filter_ctx_t *)
49 ngx_get_module_ctx(r->main ? r->main : r,
50 &ngx_http_output_filter_module);
51
52 if (hunk && (hunk->type & NGX_HUNK_LAST))
53 ctx->last = 1;
54
55 first = 1;
56
57 while (first || ctx->in) {
58
59 /* input chain is not empty */
60 if (ctx->in) {
61
62 /* add hunk to input chain */
63 if (first && hunk) {
64 for (ce = ctx->in; ce->next; ce = ce->next)
65 /* void */ ;
66
67 ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
68 }
69
70 first = 0;
71
72 /* our hunk is still busy */
73 if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
74 rc = ctx->next_filter(r, NULL);
75
76 /* our hunk is free */
77 } else {
78 ctx->out.hunk = ctx->hunk;
79
80 rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk);
81 #if (NGX_FILE_AIO)
82 if (rc == NGX_AGAIN)
83 return rc;
84 #endif
85 if (rc == NGX_ERROR)
86 return rc;
87
88 /* whole hunk is copied so we send to next filter chain part
89 up to next hunk that need to be copied */
90 if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) {
91 ctx->out.next = ctx->in->next;
92
93 for (ce = ctx->in->next; ce; ce = ce->next) {
94 if (ce->hunk->type & NGX_HUNK_FILE)
95 break;
96
97 if ((ce->hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP)
98 && (r->filter & NGX_HTTP_FILTER_NEED_TEMP))
99 break;
100 }
101
102 ctx->out.next = ce;
103
104 } else {
105 ctx->out.next = NULL;
106 }
107
108 rc = ctx->next_filter(r, &ctx->out);
109 }
110
111 /* delete completed hunks from input chain */
112 for (ce = ctx->in; ce; ce = ce->next) {
113 if (ce->hunk->pos.file == ce->hunk->last.file)
114 ctx->in = ce->next;
115 }
116
117 if (rc == NGX_OK)
118 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
119 else
120 return rc;
121
122 /* input chain is empty */
123 } else {
124
125 first = 0;
126
127 if (hunk == NULL) {
128 rc = ctx->next_filter(r, NULL);
129
130 } else {
131
132 /* we need to copy hunk to our hunk */
133 if (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
134 && (hunk->type & NGX_HUNK_FILE))
135 || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)
136 && (hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP))
137 ) {
138
139 /* out hunk is still busy */
140 if (ctx->hunk && ctx->hunk->pos.mem < ctx->hunk->last.mem) {
141 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
142 NGX_ERROR);
143
144 rc = ctx->next_filter(r, NULL);
145
146 } else {
147 if (ctx->hunk == NULL) {
148
149 if (hunk->type & NGX_HUNK_LAST) {
150 size = hunk->last.mem - hunk->pos.mem;
151 if (size > ctx->hunk_size)
152 size = ctx->hunk_size;
153
154 } else {
155 size = ctx->hunk_size;
156 }
157
158 ngx_test_null(ctx->hunk,
159 ngx_create_temp_hunk(r->pool, size,
160 50, 50),
161 NGX_ERROR);
162 ctx->hunk->type |= NGX_HUNK_RECYCLED;
163
164 rc = ngx_http_output_filter_copy_hunk(ctx->hunk,
165 hunk);
166 #if (NGX_FILE_AIO)
167 if (rc == NGX_AGAIN) {
168 /* add hunk to input chain */
169 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
170 NGX_ERROR);
171
172 return rc;
173 }
174 #endif
175 if (rc == NGX_ERROR)
176 return rc;
177
178 if (hunk->pos.mem < hunk->last.mem)
179 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
180 NGX_ERROR);
181
182 ctx->out.hunk = ctx->hunk;
183 ctx->out.next = NULL;
184
185 rc = ctx->next_filter(r, &ctx->out);
186 }
187 }
188
189 } else {
190 ctx->out.hunk = hunk;
191 ctx->out.next = NULL;
192
193 rc = ctx->next_filter(r, &ctx->out);
194 }
195 }
196 }
197
198 if (rc == NGX_OK && ctx->hunk)
199 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
200 }
201
202 if (rc == NGX_OK && ctx->last)
203 return NGX_OK;
204
205 if (rc == NGX_OK) {
206 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
207 #if level_event
208 ngx_del_event(r->connection->write, NGX_WRITE_EVENT);
209 #endif
210 }
211
212 return rc;
213 }
214
215
216 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
217 {
218 size_t size;
219 ssize_t n;
220
221 size = src->last.mem - src->pos.mem;
222 if (size > dst->end - dst->pos.mem)
223 size = dst->end - dst->pos.mem;
224
225 if (src->type & NGX_HUNK_FILE) {
226 n = ngx_read_file(src->file, dst->pos.mem, size, src->pos.file);
227
228 if (n == NGX_ERROR) {
229 return n;
230
231 #if (NGX_FILE_AIO)
232 } else if (n == NGX_AGAIN) {
233 return n;
234 #endif
235
236 } else {
237 ngx_assert((n == size), /* void */ ; , src->file->log,
238 ngx_read_file_n " reads only %d of %d" _
239 n _ size);
240 }
241
242 src->pos.mem += n;
243 dst->last.mem += n;
244
245 } else {
246 ngx_memcpy(src->pos.mem, dst->pos.mem, size);
247
248 src->pos.mem += size;
249 dst->last.mem += size;
250 }
251
252 return NGX_OK;
253 }