новая реализация подзапросов
Igor Sysoev
is at rambler-co.ru
Fri Dec 5 19:00:14 MSK 2008
On Fri, Dec 05, 2008 at 02:11:40PM +0300, Igor Sysoev wrote:
> В прилагаемом патче новая реализация подзапросов, более простая и надёжная,
> чем имеющаяся на данный момент. Если у кого-то есть тестовые сайты
> с разнообразными SSI, было бы интересно узнать, не сломалось ли что (или
> даже починилось). На продакшн я бы пока не советовал ставить.
Новая версия патча.
--
Игорь Сысоев
http://sysoev.ru
-------------- next part --------------
Index: src/http/ngx_http_copy_filter_module.c
===================================================================
--- src/http/ngx_http_copy_filter_module.c (revision 1689)
+++ src/http/ngx_http_copy_filter_module.c (working copy)
@@ -117,10 +117,6 @@
r->buffered |= NGX_HTTP_COPY_BUFFERED;
}
- if (r != r->main) {
- r->out = ctx->in;
- }
-
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
}
Index: src/http/ngx_http.h
===================================================================
--- src/http/ngx_http.h (revision 1689)
+++ src/http/ngx_http.h (working copy)
@@ -80,11 +80,13 @@
ngx_int_t ngx_http_find_server_conf(ngx_http_request_t *r);
void ngx_http_update_location_config(ngx_http_request_t *r);
void ngx_http_handler(ngx_http_request_t *r);
+ngx_int_t ngx_http_post_request(ngx_http_request_t *r);
void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
void ngx_http_empty_handler(ngx_event_t *wev);
void ngx_http_request_empty_handler(ngx_http_request_t *r);
+
#define NGX_HTTP_LAST 1
#define NGX_HTTP_FLUSH 2
Index: src/http/ngx_http_request.c
===================================================================
--- src/http/ngx_http_request.c (revision 1689)
+++ src/http/ngx_http_request.c (working copy)
@@ -36,8 +36,10 @@
u_char *host, size_t len);
static void ngx_http_request_handler(ngx_event_t *ev);
+static void ngx_http_run_posted_requests(ngx_connection_t *c);
static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
static void ngx_http_writer(ngx_http_request_t *r);
+static void ngx_http_request_finalizer(ngx_http_request_t *r);
static void ngx_http_set_keepalive(ngx_http_request_t *r);
static void ngx_http_keepalive_handler(ngx_event_t *ev);
@@ -1524,7 +1526,7 @@
ngx_http_handler(r);
- return;
+ ngx_http_run_posted_requests(c);
}
@@ -1683,15 +1685,72 @@
} else {
r->read_event_handler(r);
}
+
+ ngx_http_run_posted_requests(c);
}
+static void
+ngx_http_run_posted_requests(ngx_connection_t *c)
+{
+ ngx_http_request_t *r;
+ ngx_http_log_ctx_t *ctx;
+ ngx_http_posted_request_t *pr;
+
+ for ( ;; ) {
+
+ if (c->destroyed) {
+ return;
+ }
+
+ r = c->data;
+ pr = r->main->posted_requests;
+
+ if (pr == NULL) {
+ return;
+ }
+
+ r->main->posted_requests = pr->next;
+
+ r = pr->request;
+
+ ctx = c->log->data;
+ ctx->current_request = r;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http posted request: \"%V?%V\"", &r->uri, &r->args);
+
+ r->write_event_handler(r);
+ }
+}
+
+
+ngx_int_t
+ngx_http_post_request(ngx_http_request_t *r)
+{
+ ngx_http_posted_request_t *pr, **p;
+
+ pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
+ if (pr == NULL) {
+ return NGX_ERROR;
+ }
+
+ pr->request = r;
+ pr->next = NULL;
+
+ for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
+
+ *p = pr;
+
+ return NGX_OK;
+}
+
+
void
ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{
ngx_connection_t *c;
ngx_http_request_t *pr;
- ngx_http_log_ctx_t *ctx;
ngx_http_core_loc_conf_t *clcf;
if (rc == NGX_DONE) {
@@ -1759,89 +1818,94 @@
return;
}
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+ if (r != r->main) {
- if (r != r->main && !r->logged) {
+ if (r->buffered || r->postponed) {
- if (clcf->log_subrequest) {
- ngx_http_log_request(r);
- }
+ if (ngx_http_set_write_handler(r) != NGX_OK) {
+ ngx_http_close_request(r->main, 0);
+ }
- r->logged = 1;
- }
-
- if (r != r->main || rc == NGX_AGAIN) {
- if (ngx_http_set_write_handler(r) != NGX_OK) {
return;
}
- }
- r->done = 1;
+#if (NGX_DEBUG)
+ if (r != c->data) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http finalize non-active request: \"%V?%V\"",
+ &r->uri, &r->args);
+ }
+#endif
- if (r != c->data) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http finalize non-active request: \"%V?%V\"",
- &r->uri, &r->args);
- return;
- }
+ pr = r->parent;
- if (r != r->main) {
+ if (r == c->data) {
- pr = r->parent;
+ if (!r->logged) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- if (rc != NGX_AGAIN) {
- c->data = pr;
- }
+ if (clcf->log_subrequest) {
+ ngx_http_log_request(r);
+ }
- ctx = c->log->data;
- ctx->current_request = pr;
+ r->logged = 1;
- if (pr->postponed) {
+ } else {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "subrequest: \"%V?%V\" logged again",
+ &r->uri, &r->args);
+ }
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http request: \"%V?%V\" has postponed",
- &pr->uri, &pr->args);
+ r->done = 1;
- if (rc != NGX_AGAIN && pr->postponed->request == r) {
+ if (pr->postponed && pr->postponed->request == r) {
pr->postponed = pr->postponed->next;
}
- if (r->fast_subrequest) {
+ c->data = pr;
- if (rc == NGX_AGAIN) {
- r->fast_subrequest = 0;
- }
+ } else {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http fast subrequest: \"%V?%V\" done",
- &r->uri, &r->args);
- return;
- }
+ r->write_event_handler = ngx_http_request_finalizer;
- if (rc != NGX_AGAIN) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http wake parent request: \"%V?%V\"",
- &pr->uri, &pr->args);
-
- pr->write_event_handler(pr);
+ if (r->waited) {
+ r->done = 1;
}
}
+ if (ngx_http_post_request(pr) != NGX_OK) {
+ ngx_http_close_request(r->main, 0);
+ return;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http wake parent request: \"%V?%V\"",
+ &pr->uri, &pr->args);
+
+ ngx_http_run_posted_requests(c);
+
return;
}
- if (rc == NGX_AGAIN) {
+ if (r->buffered || c->buffered || r->postponed) {
+
+ if (ngx_http_set_write_handler(r) != NGX_OK) {
+ ngx_http_close_request(r, 0);
+ }
+
return;
}
- if (c->buffered) {
- (void) ngx_http_set_write_handler(r);
+ if (r != c->data) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "http finalize non-active request: \"%V?%V\"",
+ &r->uri, &r->args);
return;
}
+ r->done = 1;
+
if (!r->post_action) {
r->request_complete = 1;
}
@@ -1868,6 +1932,8 @@
return;
}
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
if (!ngx_terminate
&& !ngx_exiting
&& r->keepalive
@@ -2003,6 +2069,16 @@
}
+static void
+ngx_http_request_finalizer(ngx_http_request_t *r)
+{
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
+
+ ngx_http_finalize_request(r, 0);
+}
+
+
void
ngx_http_block_reading(ngx_http_request_t *r)
{
Index: src/http/ngx_http_core_module.c
===================================================================
--- src/http/ngx_http_core_module.c (revision 1689)
+++ src/http/ngx_http_core_module.c (working copy)
@@ -1831,7 +1831,6 @@
{
ngx_connection_t *c;
ngx_http_request_t *sr;
- ngx_http_log_ctx_t *ctx;
ngx_http_core_srv_conf_t *cscf;
ngx_http_postponed_request_t *pr, *p;
@@ -1896,6 +1895,7 @@
sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
+ sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
sr->unparsed_uri = r->unparsed_uri;
sr->method_name = ngx_http_core_get_method;
@@ -1909,7 +1909,7 @@
sr->parent = r;
sr->post_subrequest = ps;
sr->read_event_handler = ngx_http_request_empty_handler;
- sr->write_event_handler = ngx_http_request_empty_handler;
+ sr->write_event_handler = ngx_http_handler;
if (c->data == r) {
c->data = sr;
@@ -1940,39 +1940,18 @@
r->postponed = pr;
}
- ctx = c->log->data;
- ctx->current_request = sr;
-
sr->internal = 1;
- sr->fast_subrequest = 1;
sr->discard_body = r->discard_body;
sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
- ngx_http_handler(sr);
+ r->main->subrequests++;
- if (!c->destroyed) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http subrequest done \"%V?%V\"", uri, &sr->args);
+ *psr = sr;
- r->main->subrequests++;
-
- *psr = sr;
-
- if (sr->fast_subrequest) {
- sr->fast_subrequest = 0;
-
- if (sr->done) {
- return NGX_OK;
- }
- }
-
- return NGX_AGAIN;
- }
-
- return NGX_DONE;
+ return ngx_http_post_request(sr);
}
Index: src/http/ngx_http_request.h
===================================================================
--- src/http/ngx_http_request.h (revision 1689)
+++ src/http/ngx_http_request.h (working copy)
@@ -58,6 +58,7 @@
#define NGX_HTTP_ZERO_IN_URI 1
#define NGX_HTTP_SUBREQUEST_IN_MEMORY 2
+#define NGX_HTTP_SUBREQUEST_WAITED 4
#define NGX_HTTP_OK 200
@@ -321,6 +322,14 @@
};
+typedef struct ngx_http_posted_request_s ngx_http_posted_request_t;
+
+struct ngx_http_posted_request_s {
+ ngx_http_request_t *request;
+ ngx_http_posted_request_t *next;
+};
+
+
typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
typedef void (*ngx_http_event_handler_pt)(ngx_http_request_t *r);
@@ -373,6 +382,7 @@
ngx_http_request_t *parent;
ngx_http_postponed_request_t *postponed;
ngx_http_post_subrequest_t *post_subrequest;
+ ngx_http_posted_request_t *posted_requests;
uint32_t in_addr;
ngx_uint_t port;
@@ -428,8 +438,8 @@
unsigned request_body_file_group_access:1;
unsigned request_body_file_log_level:3;
- unsigned fast_subrequest:1;
unsigned subrequest_in_memory:1;
+ unsigned waited:1;
unsigned gzip:2;
Index: src/http/ngx_http_upstream.c
===================================================================
--- src/http/ngx_http_upstream.c (revision 1689)
+++ src/http/ngx_http_upstream.c (working copy)
@@ -274,13 +274,16 @@
static ngx_http_variable_t ngx_http_upstream_vars[] = {
{ ngx_string("upstream_addr"), NULL,
- ngx_http_upstream_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
+ ngx_http_upstream_addr_variable, 0,
+ NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
{ ngx_string("upstream_status"), NULL,
- ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
+ ngx_http_upstream_status_variable, 0,
+ NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
{ ngx_string("upstream_response_time"), NULL,
- ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
+ ngx_http_upstream_response_time_variable, 0,
+ NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -2464,17 +2467,8 @@
r->connection->log->action = "sending to client";
- if (rc == 0) {
- if (r == r->main) {
- if (!r->post_action) {
- rc = ngx_http_send_special(r, NGX_HTTP_LAST);
- }
-
- } else {
- if (r->out) {
- rc = NGX_AGAIN;
- }
- }
+ if (rc == 0 && r == r->main && !r->post_action) {
+ rc = ngx_http_send_special(r, NGX_HTTP_LAST);
}
ngx_http_finalize_request(r, rc);
Index: src/http/modules/ngx_http_addition_filter_module.c
===================================================================
--- src/http/modules/ngx_http_addition_filter_module.c (revision 1689)
+++ src/http/modules/ngx_http_addition_filter_module.c (working copy)
@@ -151,10 +151,10 @@
ctx->before_body_sent = 1;
if (conf->before_body.len) {
- rc = ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0);
-
- if (rc == NGX_ERROR || rc == NGX_DONE) {
- return rc;
+ if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
}
}
}
@@ -180,10 +180,10 @@
return rc;
}
- rc = ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0);
-
- if (rc == NGX_ERROR || rc == NGX_DONE) {
- return rc;
+ if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
}
ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
Index: src/http/modules/ngx_http_ssi_filter_module.c
===================================================================
--- src/http/modules/ngx_http_ssi_filter_module.c (revision 1689)
+++ src/http/modules/ngx_http_ssi_filter_module.c (working copy)
@@ -375,7 +375,6 @@
ngx_uint_t i, index;
ngx_chain_t *cl, **ll;
ngx_table_elt_t *param;
- ngx_http_request_t *pr;
ngx_http_ssi_ctx_t *ctx, *mctx;
ngx_http_ssi_block_t *bl;
ngx_http_ssi_param_t *prm;
@@ -403,44 +402,37 @@
}
}
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ssi filter \"%V?%V\"", &r->uri, &r->args);
+
if (ctx->wait) {
- if (r->connection->data != r) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter \"%V\" wait", &r->uri);
+
+ if (r != r->connection->data) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ssi filter wait \"%V?%V\" non-active",
+ &ctx->wait->uri, &ctx->wait->args);
+
return NGX_AGAIN;
}
- for (pr = ctx->wait->parent; pr; pr = pr->parent) {
- if (pr == r) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter \"%V\" flush", &r->uri);
+ if (ctx->wait->done) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ssi filter wait \"%V?%V\" done",
+ &ctx->wait->uri, &ctx->wait->args);
- rc = ngx_http_next_body_filter(r, NULL);
+ ctx->wait = NULL;
- if (ctx->wait->done) {
- ctx->wait = NULL;
- }
+ } else {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ssi filter wait \"%V?%V\"",
+ &ctx->wait->uri, &ctx->wait->args);
- if (rc == NGX_ERROR || rc == NGX_AGAIN) {
- return rc;
- }
-
- break;
- }
+ return ngx_http_next_body_filter(r, NULL);
}
-
- if (ctx->wait == r) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter \"%V\" continue", &r->uri);
- ctx->wait = NULL;
- }
}
slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter \"%V\"", &r->uri);
-
while (ctx->in || ctx->buf) {
if (ctx->buf == NULL ){
@@ -788,16 +780,12 @@
}
}
- if (cmd->flush) {
+ if (cmd->flush && ctx->out) {
- if (ctx->out) {
- rc = ngx_http_ssi_output(r, ctx);
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ssi flush");
- } else {
- rc = ngx_http_next_body_filter(r, NULL);
- }
-
- if (rc == NGX_ERROR) {
+ if (ngx_http_ssi_output(r, ctx) == NGX_ERROR) {
return NGX_ERROR;
}
}
@@ -2001,6 +1989,10 @@
}
}
+ if (wait) {
+ flags |= NGX_HTTP_SUBREQUEST_WAITED;
+ }
+
if (set) {
key = ngx_hash_strlow(set->data, set->data, set->len);
@@ -2033,16 +2025,10 @@
psr->data = &var->value;
}
- flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
+ flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED;
}
- rc = ngx_http_subrequest(r, uri, &args, &sr, psr, flags);
-
- if (rc == NGX_DONE) {
- return NGX_DONE;
- }
-
- if (rc == NGX_ERROR) {
+ if (ngx_http_subrequest(r, uri, &args, &sr, psr, flags) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
@@ -2050,17 +2036,17 @@
return NGX_OK;
}
- if (rc == NGX_AGAIN) {
- if (ctx->wait == NULL) {
- ctx->wait = sr;
+ if (ctx->wait == NULL) {
+ ctx->wait = sr;
- } else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "only one subrequest may be waited at the same time");
- }
+ return NGX_AGAIN;
+
+ } else {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "only one subrequest may be waited at the same time");
}
- return rc;
+ return NGX_OK;
}
Index: src/http/modules/ngx_http_static_module.c
===================================================================
--- src/http/modules/ngx_http_static_module.c (revision 1689)
+++ src/http/modules/ngx_http_static_module.c (working copy)
@@ -217,7 +217,7 @@
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- if (r != r->main && of.size == 0) {
+ if (of.size == 0) {
return ngx_http_send_header(r);
}
Index: src/http/ngx_http_postpone_filter_module.c
===================================================================
--- src/http/ngx_http_postpone_filter_module.c (revision 1689)
+++ src/http/ngx_http_postpone_filter_module.c (working copy)
@@ -9,8 +9,8 @@
#include <ngx_http.h>
-static ngx_int_t
- ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r);
+static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r,
+ ngx_chain_t *in);
static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf);
@@ -51,181 +51,119 @@
static ngx_int_t
ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
- ngx_int_t rc;
- ngx_chain_t *out;
- ngx_http_postponed_request_t *pr, **ppr;
+ ngx_connection_t *c;
+ ngx_http_postponed_request_t *pr;
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ c = r->connection;
+
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
- if (r != r->connection->data || (r->postponed && in)) {
+ if (r != c->data) {
- if (r->postponed) {
- for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
+ if (in) {
+ ngx_http_postpone_filter_add(r, in);
+ return NGX_OK;
+ }
- ppr = pr->request ? &pr->next : NULL;
-
- } else {
- ppr = &r->postponed;
-#if (NGX_SUPPRESS_WARN)
- pr = NULL;
+#if 0
+ /* TODO: SSI may pass NULL */
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "http postpone filter NULL inactive request",
+ &r->uri, &r->args);
#endif
- }
- if (ppr) {
- pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
- if (pr == NULL) {
- return NGX_ERROR;
- }
+ return NGX_OK;
+ }
- *ppr = pr;
+ if (r->postponed == NULL) {
- pr->request = NULL;
- pr->out = NULL;
- pr->next = NULL;
+ if (in || c->buffered) {
+ return ngx_http_next_filter(r->main, in);
}
- if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_ERROR) {
- return NGX_ERROR;
- }
+ return NGX_OK;
+ }
-#if 1
- {
- ngx_chain_t *cl;
- ngx_buf_t *b = NULL;
- for (cl = pr->out; cl; cl = cl->next) {
- if (cl->buf == b) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "the same buf was used in postponed %p %p",
- b, b->pos);
- ngx_debug_point();
- return NGX_ERROR;
- }
- b = cl->buf;
- }
- }
-#endif
-
- if (r != r->connection->data || r->postponed->request) {
- return NGX_AGAIN;
- }
+ if (in) {
+ ngx_http_postpone_filter_add(r, in);
}
- if (r->postponed) {
- out = r->postponed->out;
- if (out) {
- r->postponed = r->postponed->next;
- }
+ do {
+ pr = r->postponed;
- } else {
- out = in;
- }
+ if (pr->request) {
- rc = NGX_OK;
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http postpone filter wake \"%V?%V\"",
+ &pr->request->uri, &pr->request->args);
- if (out
- || (r->connection->buffered
- & (NGX_HTTP_LOWLEVEL_BUFFERED|NGX_LOWLEVEL_BUFFERED)))
- {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http postpone filter out \"%V?%V\"", &r->uri, &r->args);
+ r->postponed = pr->next;
- if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) {
+ c->data = pr->request;
- rc = ngx_http_next_filter(r->main, out);
+ return ngx_http_post_request(pr->request);
+ }
- if (rc == NGX_ERROR) {
- /* NGX_ERROR may be returned by any filter */
- r->connection->error = 1;
+ if (pr->out == NULL) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "http postpone filter NULL output",
+ &r->uri, &r->args);
+
+ } else {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http postpone filter output \"%V?%V\"",
+ &r->uri, &r->args);
+
+ if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) {
+ return NGX_ERROR;
}
}
- }
- if (r->postponed == NULL) {
- return rc;
- }
+ r->postponed = pr->next;
- rc = ngx_http_postpone_filter_output_postponed_request(r);
+ } while (r->postponed);
- if (rc == NGX_ERROR) {
- /* NGX_ERROR may be returned by any filter */
- r->connection->error = 1;
- }
-
- return rc;
+ return NGX_OK;
}
static ngx_int_t
-ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r)
+ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in)
{
- ngx_int_t rc;
- ngx_chain_t *out;
- ngx_http_log_ctx_t *ctx;
- ngx_http_postponed_request_t *pr;
+ ngx_http_postponed_request_t *pr, **ppr;
- for ( ;; ) {
- pr = r->postponed;
+ if (r->postponed) {
+ for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
- if (pr == NULL) {
- break;
+ if (pr->request == NULL) {
+ goto found;
}
- if (pr->request) {
+ ppr = &pr->next;
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http postpone filter handle \"%V?%V\"",
- &pr->request->uri, &pr->request->args);
+ } else {
+ ppr = &r->postponed;
+ }
- ctx = r->connection->log->data;
- ctx->current_request = pr->request;
+ pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
+ if (pr == NULL) {
+ return NGX_ERROR;
+ }
- if (!pr->request->done) {
- r->connection->data = pr->request;
- return NGX_AGAIN;
- }
+ *ppr = pr;
- rc = ngx_http_postpone_filter_output_postponed_request(pr->request);
+ pr->request = NULL;
+ pr->out = NULL;
+ pr->next = NULL;
- if (rc == NGX_AGAIN || rc == NGX_ERROR) {
- return rc;
- }
+found:
- r->postponed = r->postponed->next;
- pr = r->postponed;
- }
-
- if (pr == NULL) {
- break;
- }
-
- out = pr->out;
-
- if (out) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http postpone filter out postponed \"%V?%V\"",
- &r->uri, &r->args);
-
- if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) {
- if (ngx_http_next_filter(r->main, out) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
- }
-
- r->postponed = r->postponed->next;
+ if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) {
+ return NGX_OK;
}
- if (r != r->main && r->out) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http postpone filter out again \"%V?%V\"",
- &r->uri, &r->args);
-
- r->connection->data = r;
- return NGX_AGAIN;
- }
-
- return NGX_OK;
+ return NGX_ERROR;
}
More information about the nginx-ru
mailing list