comparison src/event/ngx_event_proxy.c @ 75:869b10be682f

nginx-0.0.1-2003-04-14-21:04:58 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 14 Apr 2003 17:04:58 +0000
parents
children 6127d7075471
comparison
equal deleted inserted replaced
74:17ab1af8c3dd 75:869b10be682f
1
2 #include <ngx_event_proxy.h>
3
4
5 int ngx_event_proxy_read_upstream(ngx_event_proxy_t *p)
6 {
7 int n, rc, size;
8 ngx_hunk_t *h, *nh;
9 ngx_chain_t *chain, *temp, *entry, *next;
10
11 p->level++;
12
13 ngx_log_debug(p->log, "read upstream");
14
15 for ( ;; ) {
16
17 /* use the free hunks if they exist */
18
19 if (p->free_hunks) {
20 chain = p->free_hunks;
21 p->free_hunks = NULL;
22
23 ngx_log_debug(p->log, "free hunk: %08X:%d" _ chain->hunk _
24 chain->hunk->end - chain->hunk->last);
25
26 /* allocate a new hunk if it's still allowed */
27
28 } else if (p->allocated < p->max_block_size) {
29 ngx_test_null(h,
30 ngx_create_temp_hunk(p->pool, p->block_size, 20, 20),
31 NGX_ERROR);
32
33 p->allocated += p->block_size;
34
35 ngx_test_null(temp, ngx_alloc_chain_entry(p->pool), NGX_ERROR);
36 temp->hunk = h;
37 temp->next = NULL;
38 chain = temp;
39
40 ngx_log_debug(p->log, "new hunk: %08X" _ chain->hunk);
41
42 /* use the shadow hunks if they exist */
43
44 } else if (p->shadow_hunks) {
45 chain = p->shadow_hunks;
46 p->shadow_hunks = NULL;
47
48 ngx_log_debug(p->log, "shadow hunk: %08X" _ chain->hunk);
49
50 /* if it's allowed then save the incoming hunks to a temporary file,
51 move the saved hunks to a shadow chain,
52 and add the file hunks to an outgoing chain */
53
54 } else if (p->temp_offset < p->max_temp_size) {
55 rc = ngx_event_proxy_write_chain_to_temp_file(p);
56
57 ngx_log_debug(p->log, "temp offset: %d" _ p->temp_offset);
58
59 if (rc != NGX_OK) {
60 return rc;
61 }
62
63 chain = p->shadow_hunks;
64 p->shadow_hunks = NULL;
65
66 ngx_log_debug(p->log, "new shadow hunk: %08X" _ chain->hunk);
67
68 /* if there're no hunks to read in then disable a level event */
69
70 } else {
71 if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
72 p->block_upstream = 1;
73 }
74
75 break;
76 }
77
78 n = ngx_recv_chain(p->upstream, chain);
79
80 ngx_log_debug(p->log, "recv_chain: %d" _ n);
81
82 if (n == NGX_ERROR) {
83 p->upstream_error = 1;
84 return NGX_ERROR;
85 }
86
87 if (n == NGX_AGAIN) {
88 if (p->upstream->read->blocked) {
89 if (ngx_add_event(p->upstream->read, NGX_READ_EVENT,
90 NGX_LEVEL_EVENT) == NGX_ERROR) {
91 return NGX_ERROR;
92 }
93 p->upstream->read->blocked = 0;
94 }
95
96 return NGX_AGAIN;
97 }
98
99 if (n == 0) {
100 p->free_hunks = chain;
101 p->upstream_eof = 1;
102 p->block_upstream = 0;
103 break;
104 }
105
106 /* move the full hunks to a read chain
107 and the partial filled hunk to a free chain
108 and remove the shadow links for these hunks */
109
110 for (entry = chain; entry && n > 0; entry = next) {
111 next = entry->next;
112 entry->next = NULL;
113
114 if (entry->hunk->shadow) {
115 for (h = entry->hunk->shadow;
116 (h->type & NGX_HUNK_LAST_SHADOW) == 0;
117 h = nh)
118 {
119 nh = h->shadow;
120 h->shadow = NULL;
121 h->type &= ~(NGX_HUNK_TEMP
122 |NGX_HUNK_IN_MEMORY
123 |NGX_HUNK_RECYCLED);
124 }
125
126 h->shadow = NULL;
127 h->type &= ~(NGX_HUNK_TEMP
128 |NGX_HUNK_IN_MEMORY
129 |NGX_HUNK_RECYCLED
130 |NGX_HUNK_LAST_SHADOW);
131 entry->hunk->shadow = NULL;
132 }
133
134 size = entry->hunk->end - entry->hunk->last;
135
136 if (n >= size) {
137 entry->hunk->last = entry->hunk->end;
138
139 if (p->read_hunks) {
140 p->last_read_hunk->next = entry;
141
142 } else {
143 p->read_hunks = entry;
144 }
145
146 p->last_read_hunk = entry;
147
148 n -= size;
149
150 /* the copy input filter */
151
152 if (p->input_filter == NULL) {
153 ngx_test_null(h, ngx_alloc_hunk(p->pool), NGX_ERROR);
154 ngx_memcpy(h, entry->hunk, sizeof(ngx_hunk_t));
155 h->shadow = entry->hunk;
156 h->type |= NGX_HUNK_LAST_SHADOW;
157
158 ngx_test_null(temp, ngx_alloc_chain_entry(p->pool),
159 NGX_ERROR);
160 temp->hunk = h;
161 temp->next = NULL;
162
163 if (p->in_hunks) {
164 p->last_in_hunk->next = temp;
165
166 } else {
167 p->in_hunks = temp;
168 }
169
170 p->last_in_hunk = temp;
171 }
172
173 } else {
174 entry->hunk->last += n;
175 p->free_hunks = entry;
176
177 n = 0;
178 }
179 }
180
181 ngx_log_debug(p->log, "rest chain: %08X" _ entry);
182
183 /* if the rest hunks are shadow then move them to a shadow chain
184 otherwise add them to a free chain */
185
186 if (entry) {
187 if (entry->hunk->shadow) {
188 p->shadow_hunks = entry;
189
190 } else {
191 if (p->free_hunks) {
192 p->free_hunks->next = entry;
193
194 } else {
195 p->free_hunks = entry;
196 }
197 }
198
199 p->block_upstream = 0;
200 break;
201 }
202
203 /* the input filter i.e. that moves HTTP/1.1 chunks
204 from a read chain to an incoming chain */
205
206 if (p->input_filter) {
207 if (p->input_filter(p) == NGX_ERROR) {
208 return NGX_ERROR;
209 }
210 }
211 }
212
213 ngx_log_debug(p->log, "eof: %d block: %d" _
214 p->upstream_eof _ p->block_upstream);
215
216 /* if there's the end of upstream response then move
217 the partially filled hunk from a free chain to an incoming chain */
218
219 if (p->upstream_eof) {
220 p->upstream->read->ready = 0;
221
222 if (p->free_hunks
223 && p->free_hunks->hunk->pos < p->free_hunks->hunk->last)
224 {
225 if (p->input_filter) {
226 if (p->input_filter(p) == NGX_ERROR) {
227 return NGX_ERROR;
228 }
229
230 } else {
231 entry = p->free_hunks;
232
233 if (p->in_hunks) {
234 p->last_in_hunk->next = entry;
235
236 } else {
237 p->in_hunks = entry;
238 }
239
240 p->last_in_hunk = entry;
241 }
242
243 p->free_hunks = entry->next;
244 entry->next = NULL;
245 }
246
247 #if 0
248 /* free the unneeded hunks */
249
250 for (entry = p->free_hunks; entry; entry = ce->next) {
251 ngx_free_hunk(p->pool, entry->hunk);
252 }
253 #endif
254
255 if (p->in_hunks) {
256 p->last_in_hunk->hunk->type |= NGX_HUNK_LAST;
257
258 } else if (p->out_hunks) {
259 p->last_out_hunk->hunk->type |= NGX_HUNK_LAST;
260 }
261 }
262
263 if (p->cachable) {
264 if (p->in_hunks) {
265 rc = ngx_event_proxy_write_chain_to_temp_file(p);
266 if (rc != NGX_OK) {
267 return rc;
268 }
269 }
270
271 if (p->out_hunks && p->client->write->ready) {
272 rc = ngx_event_proxy_write_to_client(p);
273 }
274
275 } else if ((p->out_hunks || p->in_hunks) && p->client->write->ready) {
276 rc = ngx_event_proxy_write_to_client(p);
277 }
278
279 p->level--;
280
281 ngx_log_debug(p->log, "level: %d" _ p->level);
282
283 if (p->level == 0 && p->block_upstream) {
284 p->upstream->read->blocked = 1;
285 if (ngx_del_event(p->upstream->read, NGX_READ_EVENT, 0) == NGX_ERROR) {
286 return NGX_ERROR;
287 }
288
289 return NGX_AGAIN;
290 }
291
292 if (p->upstream_eof) {
293 return NGX_OK;
294 } else {
295 return NGX_AGAIN;
296 }
297 }
298
299
300 int ngx_event_proxy_write_to_client(ngx_event_proxy_t *p)
301 {
302 int rc;
303 ngx_hunk_t *h;
304 ngx_chain_t *entry;
305
306 ngx_log_debug(p->log, "write to client");
307
308 h = p->busy_hunk;
309
310 for ( ;; ) {
311
312 if (h == NULL) {
313 if (p->out_hunks) {
314 entry = p->out_hunks;
315 p->out_hunks = entry->next;
316 h = entry->hunk;
317
318 if (p->shadow_hunks) {
319 if (p->shadow_hunks->hunk == h->shadow) {
320 p->shadow_hunks = p->shadow_hunks->next;
321 }
322 }
323
324 entry->next = NULL;
325
326 } else if (p->cachable == 0 && p->in_hunks) {
327 entry = p->in_hunks;
328 p->in_hunks = entry->next;
329 h = entry->hunk;
330 entry->next = NULL;
331 }
332
333 ngx_log_debug(p->log, "event proxy write hunk: %08X:%08X" _ h _ h->pos);
334
335 if (h == NULL) {
336 if (p->upstream->read->ready) {
337 rc = ngx_event_proxy_read_upstream(p);
338 }
339
340 return NGX_OK;
341 }
342 }
343
344 ngx_log_debug(p->log, "event proxy write: %d" _ h->last - h->pos);
345
346 rc = p->output_filter(p->output_data, h);
347
348 ngx_log_debug(p->log, "event proxy: %d" _ rc);
349
350 if (rc == NGX_ERROR) {
351 return NGX_ERROR;
352 }
353
354 if (rc == NGX_AGAIN
355 || (h->type & NGX_HUNK_IN_MEMORY && h->pos < h->last)
356 || (h->type & NGX_HUNK_FILE && h->file_pos < h->file_last))
357 {
358 if (p->busy_hunk == NULL) {
359 p->busy_hunk = h;
360 }
361 return NGX_AGAIN;
362 }
363
364 p->busy_hunk = NULL;
365
366 /* if the complete hunk is the file hunk and it has a shadow hunk
367 then add a shadow hunk to a free chain */
368
369 if (h->type & NGX_HUNK_FILE) {
370 if (p->cachable == 0 && p->out_hunks == NULL) {
371 p->temp_offset = 0;
372 }
373 }
374
375 if ((h->type & NGX_HUNK_LAST_SHADOW) == 0) {
376 h = NULL;
377 continue;
378 }
379
380
381 h->shadow->shadow = NULL;
382 h = h->shadow;
383
384 #if 0
385 /* free the unneeded hunk */
386
387 if (p->upstream_eof) {
388 ngx_free_hunk(p->pool, h);
389 continue;
390 }
391 #endif
392
393 h->pos = h->last = h->start;
394
395 entry->hunk = h;
396
397 /* if the first hunk in a free chain is partially filled
398 then add the complete hunk after the first free hunk */
399
400 if (p->free_hunks
401 && p->free_hunks->hunk->start != p->free_hunks->hunk->last)
402 {
403 entry->next = p->free_hunks->next;
404 p->free_hunks->next = entry;
405
406 } else {
407 entry->next = p->free_hunks;
408 p->free_hunks = entry;
409 }
410
411 h = NULL;
412 }
413 }
414
415
416 int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p)
417 {
418 int i, rc, size;
419 ngx_hunk_t *h;
420 ngx_chain_t *entry, *next, *saved_in, *saved_read;
421
422 ngx_log_debug(p->log, "write to file");
423
424 if (p->temp_file->fd == NGX_INVALID_FILE) {
425 rc = ngx_create_temp_file(p->temp_file, p->temp_path, p->pool,
426 p->number, p->random, p->cachable);
427
428 if (rc != NGX_OK) {
429 return rc;
430 }
431
432 if (p->cachable == 0 && p->temp_file_warn) {
433 ngx_log_error(NGX_LOG_WARN, p->log, 0, p->temp_file_warn);
434 }
435 }
436
437 if (p->cachable == 0) {
438
439 entry = p->read_hunks;
440 size = 0;
441
442 do {
443 size += entry->hunk->last - entry->hunk->pos;
444 if (size >= p->file_block_size) {
445 break;
446 }
447 entry = entry->next;
448
449 } while (entry);
450
451 saved_read = entry->next;
452 entry->next = NULL;
453
454 if (saved_read) {
455 for (entry = p->in_hunks; entry->next; entry = entry->next) {
456 if (entry->next->hunk->shadow == saved_read->hunk) {
457 break;
458 }
459 }
460 saved_in = entry->next;
461 entry->next = NULL;
462
463 } else {
464 saved_in = NULL;
465 }
466
467 } else {
468 saved_read = NULL;
469 saved_in = NULL;
470 }
471
472 if (ngx_write_chain_to_file(p->temp_file, p->in_hunks, p->temp_offset,
473 p->pool) == NGX_ERROR) {
474 return NGX_ERROR;
475 }
476
477 for (entry = p->in_hunks; entry; entry = next) {
478 next = entry->next;
479 entry->next = NULL;
480
481 h = entry->hunk;
482 h->type |= NGX_HUNK_FILE;
483 h->file = p->temp_file;
484 h->file_pos = p->temp_offset;
485 p->temp_offset += h->last - h->pos;
486 h->file_last = p->temp_offset;
487
488 ngx_log_debug(p->log, "event proxy file hunk: %08X:%08X" _ h _ h->pos);
489
490 if (entry->hunk->type & NGX_HUNK_LAST_SHADOW) {
491 entry->hunk->shadow->last = entry->hunk->shadow->pos;
492 }
493
494 if (p->out_hunks) {
495 p->last_out_hunk->next = entry;
496
497 } else {
498 p->out_hunks = entry;
499 }
500
501 p->last_out_hunk = entry;
502 }
503
504 p->shadow_hunks = p->read_hunks;
505
506 p->read_hunks = saved_read;
507 p->in_hunks = saved_in;
508
509 return NGX_OK;
510 }