changeset 61:4f3e2abcc2c4

nginx-0.0.1-2003-02-11-19:42:23 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 11 Feb 2003 16:42:23 +0000
parents 50186b49f2ad
children 8ccba41a678e
files src/core/ngx_hunk.h src/http/modules/ngx_http_static_handler.c src/http/ngx_http_output_filter.c src/http/ngx_http_output_filter.h src/http/ngx_http_write_filter.c
diffstat 5 files changed, 154 insertions(+), 351 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_hunk.h
+++ b/src/core/ngx_hunk.h
@@ -55,6 +55,8 @@ struct ngx_hunk_s {
     ngx_file_t  *file;
 };
 
+
+
 typedef struct ngx_chain_s  ngx_chain_t;
 struct ngx_chain_s {
     ngx_hunk_t  *hunk;
@@ -62,6 +64,9 @@ struct ngx_chain_s {
 };
 
 
+#define NGX_CHAIN_ERROR     (ngx_chain_t *) NGX_ERROR
+
+
 ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
                                  int before, int after);
 
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -141,6 +141,8 @@ int ngx_http_static_handler(ngx_http_req
     if (r->header_only)
         return rc;
 
+#if 0
+
     h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
     h->pos.file = 0;
     h->last.file = ngx_file_size(r->file.info);
@@ -152,5 +154,42 @@ int ngx_http_static_handler(ngx_http_req
 
     ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc);
 
+#else
+
+#define BLK 10000
+
+    {
+    int  i, s;
+    s = ngx_file_size(r->file.info);
+
+    for (i = 0; i < s; i += BLK) {
+        ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)),
+                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+        ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)),
+                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+        h->type = NGX_HUNK_FILE;
+        if (s - i <= BLK) {
+            h->type |= NGX_HUNK_LAST;
+        }
+
+        h->pos.file = i;
+        h->last.file = i + BLK;
+        if (h->last.file > s) {
+            h->last.file = s;
+        }
+
+        h->file->fd = r->file.fd;
+        h->file->log = r->connection->log;
+
+        rc = ngx_http_output_filter(r, h);
+
+        ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc);
+    }
+    }
+
+#endif
+
     return rc;
 }
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -57,7 +57,6 @@ ngx_module_t  ngx_http_output_filter_mod
 };
 
 
-#if 1
 
 #define next_filter  ngx_http_output_filter_module_ctx.next_output_body_filter
 
@@ -67,6 +66,7 @@ ngx_module_t  ngx_http_output_filter_mod
             || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)                   \
                && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))
 
+
 int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
 {
     int                             rc;
@@ -84,8 +84,9 @@ int ngx_http_output_filter(ngx_http_requ
                             sizeof(ngx_http_output_filter_ctx_t));
     }
 
-    /* the incoming chain ctx->in is empty */
-    if (ctx->in == NULL) {
+    /* the short path for the case when the chain ctx->incoming is empty
+       and there is no hunk or the hunk does not require the copy */
+    if (ctx->incoming == NULL) {
 
         if (hunk == NULL) {
             return next_filter(r, NULL);
@@ -98,91 +99,53 @@ int ngx_http_output_filter(ngx_http_requ
 
             return next_filter(r, &ctx->out);
         }
+    }
 
-        /* we need to copy the incoming hunk to our hunk */
+    /* add the incoming hunk to the chain ctx->incoming */
+    if (hunk) {
 
-        /* allocate ctx->hunk if it's needed */
-        if (ctx->hunk == NULL) {
+        /* the output of the only hunk is common case so we have
+           special chain entry ctx->in for it */
+        if (ctx->incoming == NULL) {
+            ctx->in.hunk = hunk;
+            ctx->in.next = NULL;
+            ctx->incoming = &ctx->in;
 
-            conf = (ngx_http_output_filter_conf_t *)
-                   ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                                ngx_http_output_filter_module);
+        } else {
+            for (ce = ctx->incoming; ce->next; ce = ce->next) {
+                /* void */ ;
+            }
+
+            ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
+        }
+    }
 
-            if (hunk->type & NGX_HUNK_LAST) {
-                size = hunk->last.mem - hunk->pos.mem;
-                if (size > conf->hunk_size) {
-                    size = conf->hunk_size;
-                }
+    /* allocate our hunk if it's needed */
+    if (ctx->hunk == NULL) {
 
-            } else {
+        conf = (ngx_http_output_filter_conf_t *)
+               ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                            ngx_http_output_filter_module);
+
+        if (hunk->type & NGX_HUNK_LAST) {
+            size = hunk->last.mem - hunk->pos.mem;
+            if (size > conf->hunk_size) {
                 size = conf->hunk_size;
             }
 
-            ngx_test_null(ctx->hunk,
-                          ngx_create_temp_hunk(r->pool, size, 50, 50),
-                          NGX_ERROR);
-
-            ctx->hunk->type |= NGX_HUNK_RECYCLED;
+        } else {
+            size = conf->hunk_size;
         }
 
-        /* copy the incoming hunk or its part to our hunk
-           and pass it to the next filter */
-
-        do {
-            rc = ngx_http_output_filter_copy_hunk(ctx->hunk, hunk);
-
-            if (rc == NGX_ERROR) {
-                return rc;
-            }
-
-#if (NGX_FILE_AIO_READ)
-
-            if (rc == NGX_AGAIN) {
-                /* add the incoming hunk to the incoming chain */
-                ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR);
-                return rc;
-            }
-
-#endif
-            ctx->out.hunk = ctx->hunk;
-            ctx->out.next = NULL;
-
-            rc = next_filter(r, &ctx->out);
-
-            if (rc == NGX_ERROR) {
-                return rc;
-            }
+        ngx_test_null(ctx->hunk,
+                      ngx_create_temp_hunk(r->pool, size, 50, 50),
+                      NGX_ERROR);
 
-            if (rc == NGX_AGAIN) {
-                /* add the incoming hunk to the incoming chain */
-                ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR);
-                return rc;
-            }
-
-            /* NGX_OK */
-
-            /* set our hunk free */
-            ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
-
-        /* repeat until we will have copied the whole incoming hunk */
-        } while (hunk->pos.mem < hunk->last.mem);
+        ctx->hunk->type |= NGX_HUNK_RECYCLED;
 
-        return NGX_OK;
-    }
-
-    /* the incoming chain ctx->in is not empty */
-
-    /* add the incoming hunk to the incoming chain */
-    if (hunk) {
-        for (ce = ctx->in; ce->next; ce = ce->next) {
-            /* void */ ;
-        }
-
-        ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
-    }
 
     /* our hunk is still busy */
-    if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
+    } else if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
         rc = next_filter(r, NULL);
 
         if (rc == NGX_ERROR || rc == NGX_AGAIN) {
@@ -190,6 +153,8 @@ int ngx_http_output_filter(ngx_http_requ
         }
 
         /* NGX_OK */
+
+        /* set our hunk free */
         ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
     }
 
@@ -197,10 +162,10 @@ int ngx_http_output_filter(ngx_http_requ
     pe = NULL;
 #endif
 
-    /* process the incoming chain ctx->in */
+    /* process the chain ctx->incoming */
     do {
         /* find the hunks that do not need to be copied ... */
-        for (ce = ctx->in; ce; ce = ce->next) {
+        for (ce = ctx->incoming; ce; ce = ce->next) {
             if (need_to_copy(r, ce->hunk)) {
                 break;
             }
@@ -208,11 +173,11 @@ int ngx_http_output_filter(ngx_http_requ
         }
 
         /* ... and pass them to the next filter */
-        if (ctx->in != ce) {
+        if (ctx->incoming != ce) {
 
-            ctx->out.hunk = ctx->in->hunk;
-            ctx->out.next = ctx->in->next;
-            ctx->in = ce;
+            ctx->out.hunk = ctx->incoming->hunk;
+            ctx->out.next = ctx->incoming->next;
+            ctx->incoming = ce;
             pe->next = NULL;
 
             rc = next_filter(r, &ctx->out);
@@ -222,16 +187,16 @@ int ngx_http_output_filter(ngx_http_requ
             }
 
             /* NGX_OK */
-            if (ctx->in == NULL) {
+            if (ctx->incoming == NULL) {
                 return rc;
             }
         }
 
-
-        /* copy the first hunk or its part from the incoming chain ctx->in
+        /* copy the first hunk or its part from the chain ctx->incoming
            to our hunk and pass it to the next filter */
         do {
-            rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk);
+            rc = ngx_http_output_filter_copy_hunk(ctx->hunk,
+                                                  ctx->incoming->hunk);
 
             if (rc == NGX_ERROR) {
                 return rc;
@@ -259,243 +224,19 @@ int ngx_http_output_filter(ngx_http_requ
             ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
 
         /* repeat until we will have copied the whole first hunk from
-           the incoming chain ctx->in */
-        } while (ctx->in->hunk->pos.mem < ctx->in->hunk->last.mem);
+           the chain ctx->incoming */
+        } while (ctx->incoming->hunk->pos.mem < ctx->incoming->hunk->last.mem);
 
     /* delete the completed hunk from the incoming chain */
-    ctx->in = ctx->in->next;
+    ctx->incoming = ctx->incoming->next;
 
-    /* repeat until we will have processed the whole incoming chain ctx->in */
-    } while (ctx->in);
+    /* repeat until we will have processed the whole chain ctx->incoming */
+    } while (ctx->incoming);
 
     return NGX_OK;
 }
 
 
-#else
-
-
-int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
-{
-    int                             rc, once;
-    u_int                           flags;
-    size_t                          size;
-    ngx_chain_t                    *ce;
-    ngx_http_output_filter_ctx_t   *ctx;
-    ngx_http_output_filter_conf_t  *conf;
-
-    ctx = (ngx_http_output_filter_ctx_t *)
-                    ngx_http_get_module_ctx(r->main ? r->main : r,
-                                            ngx_http_output_filter_module);
-
-    if (ctx == NULL) {
-        ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module,
-                            sizeof(ngx_http_output_filter_ctx_t));
-    }
-
-    if (hunk && (hunk->type & NGX_HUNK_LAST)) {
-        ctx->last = 1;
-    }
-
-#if (NGX_SUPPRESS_WARN)
-    rc = NGX_ALERT;
-#endif
-
-    for (once = 1; once || ctx->in; once = 0) {
-
-         /* input chain is not empty */
-        if (ctx->in) {
-
-            /* add hunk to input chain */
-            if (once && hunk) {
-                for (ce = ctx->in; ce->next; ce = ce->next) {
-                    /* void */ ;
-                }
-
-                ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
-            }
-
-            /* our hunk is still busy */
-            if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
-                rc = ngx_http_output_filter_module_ctx.
-                                              next_output_body_filter(r, NULL);
-
-            /* our hunk is free */
-            } else {
-                ctx->out.hunk = ctx->hunk;
-
-                /* XXX: should we check hunk type before copy it ? */
-                rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk);
-#if (NGX_FILE_AIO_READ)
-                if (rc == NGX_AGAIN) {
-                    return rc;
-                }
-#endif
-                if (rc == NGX_ERROR) {
-                    return rc;
-                }
-
-                /* NGX_OK */
-
-                /* whole hunk is copied so we send to next filter chain part
-                   up to next hunk that need to be copied */
-                if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) {
-                    ctx->out.next = ctx->in->next;
-
-                    for (ce = ctx->in->next; ce; ce = ce->next) {
-                        if (ce->hunk->type & NGX_HUNK_FILE) {
-                            break;
-                        }
-
-                        if ((ce->hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))
-                            && (r->filter & NGX_HTTP_FILTER_NEED_TEMP))
-                        {
-                            break;
-                        }
-                    }
-
-                    ctx->out.next = ce;
-
-                } else {
-                    ctx->out.next = NULL;
-                }
-
-                rc = ngx_http_output_filter_module_ctx.
-                                         next_output_body_filter(r, &ctx->out);
-            }
-
-            /* delete completed hunks from input chain */
-            for (ce = ctx->in; ce; ce = ce->next) {
-                 if (ce->hunk->pos.file == ce->hunk->last.file) {
-                     ctx->in = ce->next;
-                 }
-            }
-
-            if (rc == NGX_OK && ctx->hunk) {
-                ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
-            } else {
-                return rc;
-            }
-
-        /* input chain is empty */
-        } else {
-
-            if (hunk == NULL) {
-                rc = ngx_http_output_filter_module_ctx.
-                                              next_output_body_filter(r, NULL);
-
-            } else {
-
-                /* we need to copy hunk to our hunk */
-                if (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
-                        && (hunk->type & NGX_HUNK_FILE))
-                    || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)
-                        && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))
-                   ) {
-
-                    /* out hunk is still busy */
-                    if (ctx->hunk && ctx->hunk->pos.mem < ctx->hunk->last.mem) {
-                        ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
-                                              NGX_ERROR);
-
-                        rc = ngx_http_output_filter_module_ctx.
-                                              next_output_body_filter(r, NULL);
-
-                    } else {
-                        if (ctx->hunk == NULL) {
-
-                            conf = (ngx_http_output_filter_conf_t *)
-                                            ngx_http_get_module_loc_conf(
-                                                r->main ? r->main : r,
-                                                ngx_http_output_filter_module);
-
-                            if (hunk->type & NGX_HUNK_LAST) {
-                                size = hunk->last.mem - hunk->pos.mem;
-                                if (size > conf->hunk_size) {
-                                    size = conf->hunk_size;
-                                }
-
-                            } else {
-                                size = conf->hunk_size;
-                            }
-
-                            ngx_test_null(ctx->hunk,
-                                          ngx_create_temp_hunk(r->pool, size,
-                                                               50, 50),
-                                          NGX_ERROR);
-                            ctx->hunk->type |= NGX_HUNK_RECYCLED;
-
-                            rc = ngx_http_output_filter_copy_hunk(ctx->hunk,
-                                                                  hunk);
-#if (NGX_FILE_AIO_READ)
-                            if (rc == NGX_AGAIN) {
-                                /* add hunk to input chain */
-                                ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
-                                                      NGX_ERROR);
-
-                                return rc;
-                            }
-#endif
-                            if (rc == NGX_ERROR) {
-                                return rc;
-                            }
-
-                            if (hunk->pos.mem < hunk->last.mem) {
-                                ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
-                                                      NGX_ERROR);
-                            }
-
-                            ctx->out.hunk = ctx->hunk;
-                            ctx->out.next = NULL;
-
-                            rc = ngx_http_output_filter_module_ctx.
-                                         next_output_body_filter(r, &ctx->out);
-                        }
-                    }
-
-                } else {
-                    ctx->out.hunk = hunk;
-                    ctx->out.next = NULL;
-
-                    rc = ngx_http_output_filter_module_ctx.
-                                         next_output_body_filter(r, &ctx->out);
-                }
-            }
-        }
-
-        /* set free our hunk if operation has completed */
-        if (rc == NGX_OK && ctx->hunk) {
-            ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
-        }
-    }
-
-#if (NGX_SUPPRESS_WARN)
-    if (rc == NGX_ALERT) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "ngx_http_output_filter: rc == NGX_ALERT");
-        return NGX_ERROR;
-    }
-#endif
-
-    if (rc == NGX_OK && ctx->last) {
-        return NGX_OK;
-    }
-
-    if (rc == NGX_OK) {
-        if (ctx->hunk) { /* XXX: double upper code ? */
-            ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
-        }
-#if (NGX_LEVEL_EVENT)
-        ngx_del_event(r->connection->write, NGX_WRITE_EVENT);
-#endif
-    }
-
-    return rc;
-}
-
-#endif
-
-
 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
 {
     ssize_t  n, size;
@@ -510,16 +251,23 @@ static int ngx_http_output_filter_copy_h
 
         if (n == NGX_ERROR) {
             return n;
+        }
 
 #if (NGX_FILE_AIO_READ)
-        } else if (n == NGX_AGAIN) {
+
+        if (n == NGX_AGAIN) {
             return n;
+        }
+
 #endif
 
-        } else {
-            ngx_assert((n == size), /* void */ ; , src->file->log,
-                       ngx_read_file_n " reads only %d of %d" _
-                       n _ size);
+        if (n != size) {
+            ngx_log_error(NGX_LOG_ALERT, src->file->log, 0,
+                          ngx_read_file_n " reads only %d of %d from file",
+                          n, size);
+            if (n == 0) {
+                return NGX_ERROR;
+            }
         }
 
         src->pos.mem += n;
--- a/src/http/ngx_http_output_filter.h
+++ b/src/http/ngx_http_output_filter.h
@@ -18,9 +18,10 @@ typedef struct {
 
 
 typedef struct {
-    ngx_hunk_t   *hunk;
-    ngx_chain_t  *in;
-    ngx_chain_t   out;
+    ngx_hunk_t   *hunk;         /* the temporary hunk to copy */
+    ngx_chain_t  *incoming;
+    ngx_chain_t   in;           /* one chain entry for input */
+    ngx_chain_t   out;          /* one chain entry for output */
 } ngx_http_output_filter_ctx_t;
 
 
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -57,9 +57,9 @@ ngx_module_t  ngx_http_write_filter_modu
 
 int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
-    int    last;
-    off_t  size, flush;
-    ngx_chain_t  *ch, **prev, *chain;
+    int                           last;
+    off_t                         size, flush;
+    ngx_chain_t                  *ce, **le, *chain;
     ngx_http_write_filter_ctx_t  *ctx;
     ngx_http_write_filter_conf_t *conf;
 
@@ -74,51 +74,51 @@ int ngx_http_write_filter(ngx_http_reque
 
     size = flush = 0;
     last = 0;
-    prev = &ctx->out;
+    le = &ctx->out;
 
-    /* find size, flush point and last link of saved chain */
-    for (ch = ctx->out; ch; ch = ch->next) {
-        prev = &ch->next;
-        size += ch->hunk->last.file - ch->hunk->pos.file;
+    /* find the size, the flush point and the last entry of saved chain */
+    for (ce = ctx->out; ce; ce = ce->next) {
+        le = &ce->next;
+        size += ce->hunk->last.file - ce->hunk->pos.file;
 
-#if (NGX_DEBUG_WRITE_FILTER)
+#if (NGX_DEBUG_WRITE_FILTER0)
         ngx_log_debug(r->connection->log, "write filter: old chunk: %x "
                       QX_FMT " " QD_FMT _
-                      ch->hunk->type _ ch->hunk->pos.file _
-                      ch->hunk->last.file - ch->hunk->pos.file);
+                      ce->hunk->type _ ce->hunk->pos.file _
+                      ce->hunk->last.file - ce->hunk->pos.file);
 #endif
 
-        if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
+        if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
             flush = size;
         }
 
-        if (ch->hunk->type & NGX_HUNK_LAST) {
+        if (ce->hunk->type & NGX_HUNK_LAST) {
             last = 1;
         }
     }
 
-    /* add new chain to existent one */
+    /* add the new chain to the existent one */
     for (/* void */; in; in = in->next) {
-        ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR);
+        ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR);
 
-        ch->hunk = in->hunk;
-        ch->next = NULL;
-        *prev = ch;
-        prev = &ch->next;
-        size += ch->hunk->last.file - ch->hunk->pos.file;
+        ce->hunk = in->hunk;
+        ce->next = NULL;
+        *le = ce;
+        le = &ce->next;
+        size += ce->hunk->last.file - ce->hunk->pos.file;
 
-#if (NGX_DEBUG_WRITE_FILTER)
-        ngx_log_debug(r->connection->log, "write filter: new chunk: %x "
+#if (NGX_DEBUG_WRITE_FILTER0)
+        ngx_log_debug(r->connection->log, "write filter: new hunk: %x "
                       QX_FMT " " QD_FMT _
-                      ch->hunk->type _ ch->hunk->pos.file _
-                      ch->hunk->last.file - ch->hunk->pos.file);
+                      ce->hunk->type _ ce->hunk->pos.file _
+                      ce->hunk->last.file - ce->hunk->pos.file);
 #endif
 
-        if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
+        if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
             flush = size;
         }
 
-        if (ch->hunk->type & NGX_HUNK_LAST) {
+        if (ce->hunk->type & NGX_HUNK_LAST) {
             last = 1;
         }
     }
@@ -127,25 +127,35 @@ int ngx_http_write_filter(ngx_http_reque
                 ngx_http_get_module_loc_conf(r->main ? r->main : r,
                                              ngx_http_write_filter_module);
 
-#if (NGX_DEBUG_WRITE_FILTER)
+#if (NGX_DEBUG_WRITE_FILTER0)
     ngx_log_debug(r->connection->log, "write filter: last:%d flush:%d" _
                   last _ flush);
 #endif
 
+    /* avoid the output if there is no last hunk, no flush point and
+       size of the hunks is smaller then 'write_buffer' */
     if (!last && flush == 0 && size < conf->buffer_output) {
         return NGX_OK;
     }
 
     chain = ngx_event_write(r->connection, ctx->out, flush);
-    if (chain == (ngx_chain_t *) -1) {
+
+#if (NGX_DEBUG_WRITE_FILTER)
+    ngx_log_debug(r->connection->log, "write filter %x" _ chain);
+#endif
+
+    if (chain == NGX_CHAIN_ERROR) {
         return NGX_ERROR;
     }
 
     ctx->out = chain;
 
-    ngx_log_debug(r->connection->log, "write filter %x" _ chain);
+    if (chain == NULL) {
+        return NGX_OK;
 
-    return (chain ? NGX_AGAIN : NGX_OK);
+    } else {
+        return NGX_AGAIN;
+    }
 }