comparison src/http/ngx_http_filter.c @ 4:c5f071d376e5

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