~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/http/ngx_http_postpone_filter_module.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
9
10
#include <ngx_http.h>
10
11
 
11
12
 
12
 
static ngx_int_t
13
 
    ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r);
 
13
static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r,
 
14
    ngx_chain_t *in);
14
15
static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf);
15
16
 
16
17
 
45
46
};
46
47
 
47
48
 
48
 
static ngx_http_output_body_filter_pt    ngx_http_next_filter;
 
49
static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
49
50
 
50
51
 
51
52
static ngx_int_t
52
53
ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
53
54
{
54
 
    ngx_int_t                      rc;
55
 
    ngx_chain_t                   *out;
56
 
    ngx_http_postponed_request_t  *pr, **ppr;
57
 
 
58
 
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 
55
    ngx_connection_t              *c;
 
56
    ngx_http_postponed_request_t  *pr;
 
57
 
 
58
    c = r->connection;
 
59
 
 
60
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
59
61
                   "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
60
62
 
61
 
    if (r != r->connection->data || (r->postponed && in)) {
62
 
 
63
 
        if (r->postponed) {
64
 
            for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
65
 
 
66
 
            ppr = pr->request ? &pr->next : NULL;
67
 
 
68
 
        } else {
69
 
            ppr = &r->postponed;
70
 
#if (NGX_SUPPRESS_WARN)
71
 
            pr = NULL;
72
 
#endif
73
 
        }
74
 
 
75
 
        if (ppr) {
76
 
            pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
77
 
            if (pr == NULL) {
78
 
                return NGX_ERROR;
79
 
            }
80
 
 
81
 
            *ppr = pr;
82
 
 
83
 
            pr->request = NULL;
84
 
            pr->out = NULL;
85
 
            pr->next = NULL;
86
 
        }
87
 
 
88
 
        if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_ERROR) {
89
 
            return NGX_ERROR;
90
 
        }
91
 
 
92
 
#if 1
93
 
        {
94
 
        ngx_chain_t  *cl;
95
 
        ngx_buf_t    *b = NULL;
96
 
        for (cl = pr->out; cl; cl = cl->next) {
97
 
            if (cl->buf == b) {
98
 
                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
99
 
                              "the same buf was used in postponed %p %p",
100
 
                               b, b->pos);
101
 
                ngx_debug_point();
102
 
                return NGX_ERROR;
103
 
            }
104
 
            b = cl->buf;
105
 
        }
106
 
        }
107
 
#endif
108
 
 
109
 
        if (r != r->connection->data || r->postponed->request) {
110
 
            return NGX_AGAIN;
111
 
        }
112
 
    }
113
 
 
114
 
    if (r->postponed) {
115
 
        out = r->postponed->out;
116
 
        if (out) {
117
 
            r->postponed = r->postponed->next;
118
 
        }
119
 
 
120
 
    } else {
121
 
        out = in;
122
 
    }
123
 
 
124
 
    rc = NGX_OK;
125
 
 
126
 
    if (out
127
 
        || (r->connection->buffered
128
 
            & (NGX_HTTP_LOWLEVEL_BUFFERED|NGX_LOWLEVEL_BUFFERED)))
129
 
    {
130
 
        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
131
 
                       "http postpone filter out \"%V?%V\"", &r->uri, &r->args);
132
 
 
133
 
        if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) {
134
 
 
135
 
            rc = ngx_http_next_filter(r->main, out);
136
 
 
137
 
            if (rc == NGX_ERROR) {
138
 
                /* NGX_ERROR may be returned by any filter */
139
 
                r->connection->error = 1;
140
 
            }
141
 
        }
 
63
    if (r != c->data) {
 
64
 
 
65
        if (in) {
 
66
            ngx_http_postpone_filter_add(r, in);
 
67
            return NGX_OK;
 
68
        }
 
69
 
 
70
#if 0
 
71
        /* TODO: SSI may pass NULL */
 
72
        ngx_log_error(NGX_LOG_ALERT, c->log, 0,
 
73
                      "http postpone filter NULL inactive request",
 
74
                      &r->uri, &r->args);
 
75
#endif
 
76
 
 
77
        return NGX_OK;
142
78
    }
143
79
 
144
80
    if (r->postponed == NULL) {
145
 
        return rc;
146
 
    }
147
 
 
148
 
    rc = ngx_http_postpone_filter_output_postponed_request(r);
149
 
 
150
 
    if (rc == NGX_ERROR) {
151
 
        /* NGX_ERROR may be returned by any filter */
152
 
        r->connection->error = 1;
153
 
    }
154
 
 
155
 
    return rc;
156
 
}
157
 
 
158
 
 
159
 
static ngx_int_t
160
 
ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r)
161
 
{
162
 
    ngx_int_t                      rc;
163
 
    ngx_chain_t                   *out;
164
 
    ngx_http_log_ctx_t            *ctx;
165
 
    ngx_http_postponed_request_t  *pr;
166
 
 
167
 
    for ( ;; ) {
 
81
 
 
82
        if (in || c->buffered) {
 
83
            return ngx_http_next_body_filter(r->main, in);
 
84
        }
 
85
 
 
86
        return NGX_OK;
 
87
    }
 
88
 
 
89
    if (in) {
 
90
        ngx_http_postpone_filter_add(r, in);
 
91
    }
 
92
 
 
93
    do {
168
94
        pr = r->postponed;
169
95
 
170
 
        if (pr == NULL) {
171
 
            break;
172
 
        }
173
 
 
174
96
        if (pr->request) {
175
97
 
176
 
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
177
 
                           "http postpone filter handle \"%V?%V\"",
 
98
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
99
                           "http postpone filter wake \"%V?%V\"",
178
100
                           &pr->request->uri, &pr->request->args);
179
101
 
180
 
            ctx = r->connection->log->data;
181
 
            ctx->current_request = pr->request;
182
 
 
183
 
            if (!pr->request->done) {
184
 
                r->connection->data = pr->request;
185
 
                return NGX_AGAIN;
186
 
            }
187
 
 
188
 
            rc = ngx_http_postpone_filter_output_postponed_request(pr->request);
189
 
 
190
 
            if (rc == NGX_AGAIN || rc == NGX_ERROR) {
191
 
                return rc;
192
 
            }
193
 
 
194
 
            r->postponed = r->postponed->next;
195
 
            pr = r->postponed;
196
 
        }
197
 
 
198
 
        if (pr == NULL) {
199
 
            break;
200
 
        }
201
 
 
202
 
        out = pr->out;
203
 
 
204
 
        if (out) {
205
 
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
206
 
                           "http postpone filter out postponed \"%V?%V\"",
 
102
            r->postponed = pr->next;
 
103
 
 
104
            c->data = pr->request;
 
105
 
 
106
            return ngx_http_post_request(pr->request, NULL);
 
107
        }
 
108
 
 
109
        if (pr->out == NULL) {
 
110
            ngx_log_error(NGX_LOG_ALERT, c->log, 0,
 
111
                          "http postpone filter NULL output",
 
112
                          &r->uri, &r->args);
 
113
 
 
114
        } else {
 
115
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
116
                           "http postpone filter output \"%V?%V\"",
207
117
                           &r->uri, &r->args);
208
118
 
209
 
            if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) {
210
 
                if (ngx_http_next_filter(r->main, out) == NGX_ERROR) {
211
 
                    return NGX_ERROR;
212
 
                }
 
119
            if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
 
120
                return NGX_ERROR;
213
121
            }
214
122
        }
215
123
 
216
 
        r->postponed = r->postponed->next;
217
 
    }
218
 
 
219
 
    if (r->out) {
220
 
        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
221
 
                       "http postpone filter out again \"%V?%V\"",
222
 
                       &r->uri, &r->args);
223
 
 
224
 
        r->connection->data = r;
225
 
        return NGX_AGAIN;
226
 
    }
 
124
        r->postponed = pr->next;
 
125
 
 
126
    } while (r->postponed);
227
127
 
228
128
    return NGX_OK;
229
129
}
230
130
 
231
131
 
232
132
static ngx_int_t
 
133
ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in)
 
134
{
 
135
    ngx_http_postponed_request_t  *pr, **ppr;
 
136
 
 
137
    if (r->postponed) {
 
138
        for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
 
139
 
 
140
        if (pr->request == NULL) {
 
141
            goto found;
 
142
        }
 
143
 
 
144
        ppr = &pr->next;
 
145
 
 
146
    } else {
 
147
        ppr = &r->postponed;
 
148
    }
 
149
 
 
150
    pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
 
151
    if (pr == NULL) {
 
152
        return NGX_ERROR;
 
153
    }
 
154
 
 
155
    *ppr = pr;
 
156
 
 
157
    pr->request = NULL;
 
158
    pr->out = NULL;
 
159
    pr->next = NULL;
 
160
 
 
161
found:
 
162
 
 
163
    if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) {
 
164
        return NGX_OK;
 
165
    }
 
166
 
 
167
    return NGX_ERROR;
 
168
}
 
169
 
 
170
 
 
171
static ngx_int_t
233
172
ngx_http_postpone_filter_init(ngx_conf_t *cf)
234
173
{
235
 
    ngx_http_next_filter = ngx_http_top_body_filter;
 
174
    ngx_http_next_body_filter = ngx_http_top_body_filter;
236
175
    ngx_http_top_body_filter = ngx_http_postpone_filter;
237
176
 
238
177
    return NGX_OK;