nginx-0.1.28-RELEASE import

    *) Bugfix: nginx hogs CPU while proxying the huge files.

    *) Bugfix: nginx could not be built by gcc 4.0 on Linux.
diff --git a/src/core/nginx.h b/src/core/nginx.h
index d097cf7..9fa141a 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.1.27"
+#define NGINX_VER          "nginx/0.1.28"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_NEWPID_EXT     ".newbin"
diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c
index 2f0356f..4c1b1d5 100644
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -44,6 +44,27 @@
 
 
 ngx_chain_t *
+ngx_alloc_chain_link(ngx_pool_t *pool)
+{
+    ngx_chain_t  *cl;
+
+    cl = pool->chain;
+
+    if (cl) {
+        pool->chain = cl->next;
+        return cl;
+    }
+
+    cl = ngx_palloc(pool, sizeof(ngx_chain_t));
+    if (cl == NULL) {
+        return NULL;
+    }
+
+    return cl;
+}
+
+
+ngx_chain_t *
 ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
 {
     u_char       *p;
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index 721b9c2..96394f9 100644
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -55,8 +55,6 @@
 };
 
 
-typedef struct ngx_chain_s       ngx_chain_t;
-
 struct ngx_chain_s {
     ngx_buf_t    *buf;
     ngx_chain_t  *next;
@@ -119,7 +117,11 @@
 #define ngx_alloc_buf(pool)  ngx_palloc(pool, sizeof(ngx_buf_t))
 #define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))
 
-#define ngx_alloc_chain_link(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
+ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
+#define ngx_free_chain(pool, cl)                                             \
+    cl->next = pool->chain;                                                  \
+    pool->chain = cl
+
 
 
 ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in);
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index e8119fc..35ee8b8 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -137,7 +137,7 @@
             }
 
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                         "%s in %s:%d",
+                         "%s in %s:%ui",
                          rv, cf->conf_file->file.name.data,
                          cf->conf_file->line);
             rc = NGX_ERROR;
@@ -207,7 +207,7 @@
 
                 if (!(cmd->type & cf->cmd_type)) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "directive \"%s\" in %s:%d "
+                                  "directive \"%s\" in %s:%ui "
                                   "is not allowed here",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -216,7 +216,7 @@
 
                 if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "directive \"%s\" in %s:%d "
+                                  "directive \"%s\" in %s:%ui "
                                   "is not terminated by \";\"",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -227,7 +227,7 @@
                     && last != NGX_CONF_BLOCK_START)
                 {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "directive \"%s\" in %s:%d "
+                                  "directive \"%s\" in %s:%ui "
                                   "has not the opening \"{\"",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -276,7 +276,7 @@
                 if (!valid) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                                   "invalid number arguments in "
-                                  "directive \"%s\" in %s:%d",
+                                  "directive \"%s\" in %s:%ui",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
                     return NGX_ERROR;
@@ -311,7 +311,7 @@
                 }
 
                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                              "the \"%s\" directive %s in %s:%d",
+                              "the \"%s\" directive %s in %s:%ui",
                               name->data, rv, cf->conf_file->file.name.data,
                               cf->conf_file->line);
 
@@ -323,7 +323,7 @@
     }
 
     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                  "unknown directive \"%s\" in %s:%d",
+                  "unknown directive \"%s\" in %s:%ui",
                   name->data, cf->conf_file->file.name.data,
                   cf->conf_file->line);
 
@@ -360,7 +360,7 @@
             {
                 if (cf->args->nelts > 0) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "unexpected end of file in %s:%d, "
+                                  "unexpected end of file in %s:%ui, "
                                   "expecting \";\" or \"}\"",
                                   cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -423,7 +423,7 @@
             }
 
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "unexpected \"%c\" in %s:%d",
+                          "unexpected \"%c\" in %s:%ui",
                           ch, cf->conf_file->file.name.data,
                           cf->conf_file->line);
 
@@ -443,7 +443,7 @@
             case '{':
                 if (cf->args->nelts == 0) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "unexpected \"%c\" in %s:%d",
+                                  "unexpected \"%c\" in %s:%ui",
                                   ch, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
                     return NGX_ERROR;
@@ -458,7 +458,7 @@
             case '}':
                 if (cf->args->nelts > 0) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "unexpected \"}\" in %s:%d",
+                                  "unexpected \"}\" in %s:%ui",
                                   cf->conf_file->file.name.data,
                                   cf->conf_file->line);
                     return NGX_ERROR;
@@ -729,7 +729,7 @@
         *buf = '\0';
     }
 
-    ngx_log_error(level, cf->log, 0, "%s in %s:%d",
+    ngx_log_error(level, cf->log, 0, "%s in %s:%ui",
                   errstr, cf->conf_file->file.name.data, cf->conf_file->line);
 }
 
@@ -1065,7 +1065,7 @@
         }
 
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "value must be equal or more than %d", bounds->low);
+                           "value must be equal or more than %i", bounds->low);
 
         return NGX_CONF_ERROR;
     }
@@ -1075,7 +1075,7 @@
     }
 
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                       "value must be between %d and %d",
+                       "value must be between %i and %i",
                        bounds->low, bounds->high);
 
     return NGX_CONF_ERROR;
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index d5a7a66..4fab8c1 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -73,60 +73,60 @@
 
 
 struct ngx_command_s {
-    ngx_str_t     name;
-    int           type;
-    char       *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-    int           conf;
-    int           offset;
-    void         *post;
+    ngx_str_t             name;
+    ngx_uint_t            type;
+    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+    ngx_uint_t            conf;
+    ngx_uint_t            offset;
+    void                 *post;
 };
 
 #define ngx_null_command   { ngx_null_string, 0, NULL, 0, 0, NULL }
 
 
 struct ngx_open_file_s {
-    ngx_fd_t   fd;
-    ngx_str_t  name;
+    ngx_fd_t              fd;
+    ngx_str_t             name;
 #if 0
     /* e.g. append mode, error_log */
-    int        flags;
+    ngx_uint_t            flags;
     /* e.g. reopen db file */
-    int      (*handler)(void *data, ngx_open_file_t *file);
-    void      *data;
+    ngx_uint_t          (*handler)(void *data, ngx_open_file_t *file);
+    void                 *data;
 #endif
 };
 
 
 struct ngx_module_s {
-    ngx_uint_t       ctx_index;
-    ngx_uint_t       index;
-    void            *ctx;
-    ngx_command_t   *commands;
-    ngx_uint_t       type;
-    ngx_int_t      (*init_module)(ngx_cycle_t *cycle);
-    ngx_int_t      (*init_process)(ngx_cycle_t *cycle);
+    ngx_uint_t            ctx_index;
+    ngx_uint_t            index;
+    void                 *ctx;
+    ngx_command_t        *commands;
+    ngx_uint_t            type;
+    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
+    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
 #if 0
-    ngx_int_t      (*init_thread)(ngx_cycle_t *cycle);
+    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
 #endif
 };
 
 
 typedef struct {
-    ngx_str_t       name;
-    void         *(*create_conf)(ngx_cycle_t *cycle);
-    char         *(*init_conf)(ngx_cycle_t *cycle, void *conf);
+    ngx_str_t             name;
+    void               *(*create_conf)(ngx_cycle_t *cycle);
+    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);
 } ngx_core_module_t; 
 
 
 typedef struct {
-    ngx_file_t   file;
-    ngx_buf_t   *buffer;
-    ngx_uint_t   line;
+    ngx_file_t            file;
+    ngx_buf_t            *buffer;
+    ngx_uint_t            line;
 } ngx_conf_file_t;
 
 
 typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf,
-                                     ngx_command_t *dummy, void *conf);
+    ngx_command_t *dummy, void *conf);
 
 
 struct ngx_conf_s {
@@ -157,22 +157,22 @@
 
 typedef struct {
     ngx_conf_post_handler_pt  post_handler;
-    int                       low;
-    int                       high;
+    ngx_int_t                 low;
+    ngx_int_t                 high;
 } ngx_conf_num_bounds_t;
 
 
 typedef struct {
-    ngx_str_t   name;
-    ngx_uint_t  value;
+    ngx_str_t                 name;
+    ngx_uint_t                value;
 } ngx_conf_enum_t;
 
 
 #define NGX_CONF_BITMASK_SET  1
 
 typedef struct {
-    ngx_str_t   name;
-    ngx_uint_t  mask;
+    ngx_str_t                 name;
+    ngx_uint_t                mask;
 } ngx_conf_bitmask_t;
 
 
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 13053f2..9646f6c 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -12,6 +12,7 @@
 typedef struct ngx_conf_s        ngx_conf_t;
 typedef struct ngx_cycle_s       ngx_cycle_t;
 typedef struct ngx_pool_s        ngx_pool_t;
+typedef struct ngx_chain_s       ngx_chain_t; 
 typedef struct ngx_log_s         ngx_log_t;
 typedef struct ngx_array_s       ngx_array_t;
 typedef struct ngx_open_file_s   ngx_open_file_t;
@@ -51,7 +52,7 @@
 #include <ngx_buf.h>
 #include <ngx_array.h>
 #include <ngx_list.h>
-#include <ngx_table.h>
+#include <ngx_hash.h>
 #include <ngx_file.h>
 #include <ngx_files.h>
 #include <ngx_crc.h>
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 51864e3..5104205 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -54,7 +54,7 @@
 
     log = old_cycle->log;
 
-    pool = ngx_create_pool(16 * 1024, log);
+    pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
     if (pool == NULL) {
         return NULL;
     }
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index face67f..b1b5348 100644
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -12,6 +12,11 @@
 #include <ngx_core.h>
 
 
+#ifndef NGX_CYCLE_POOL_SIZE
+#define NGX_CYCLE_POOL_SIZE     16384
+#endif
+
+
 #define NGX_DEBUG_POINTS_STOP   1
 #define NGX_DEBUG_POINTS_ABORT  2
 
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
new file mode 100644
index 0000000..2c062b7
--- /dev/null
+++ b/src/core/ngx_hash.c
@@ -0,0 +1,160 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+ngx_int_t
+ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
+{
+    u_char      *p;
+    ngx_str_t   *n, *bucket;
+    ngx_uint_t   i, key, size, best, *test, buckets, min_buckets;
+
+    test = ngx_alloc(hash->max_size * sizeof(ngx_uint_t), pool->log);
+    if (test == NULL) {
+        return NGX_ERROR;
+    }
+
+    min_buckets = hash->bucket_limit + 1;
+
+#if (NGX_SUPPRESS_WARN)
+    best = 0;
+#endif
+
+    for (size = 1; size < hash->max_size; size++) {
+
+        buckets = 0;
+
+        for (i = 0; i < size; i++) {
+            test[i] = 0;
+        }
+
+        for (n = (ngx_str_t *) names;
+             n->len;
+             n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+        {
+            key = 0;
+
+            for (i = 0; i < n->len; i++) {
+                key += ngx_tolower(n->data[i]);
+            }
+
+            key %= size;
+
+            if (test[key] == hash->bucket_limit) {
+                break;
+            }
+
+            test[key]++;
+
+            if (buckets < test[key]) {
+                buckets = test[key];
+            }
+        }
+
+        if (n->len == 0) {
+            if (min_buckets > buckets) {
+                min_buckets = buckets;
+                best = size;
+            }
+
+            if (hash->bucket_limit == 1) {
+                break;
+            }
+        }
+    }
+
+    if (min_buckets == hash->bucket_limit + 1) {
+        ngx_log_error(NGX_LOG_EMERG, pool->log, 0,
+                      "could not build the %s hash, you should increase "
+                      "either %s_size: %i or %s_bucket_limit: %i",
+                      hash->name, hash->name, hash->max_size,
+                      hash->name, hash->bucket_limit);
+        ngx_free(test);
+        return NGX_ERROR;
+    }
+
+    hash->buckets = ngx_pcalloc(pool, best * hash->bucket_size);
+    if (hash->buckets == NULL) {
+        ngx_free(test);
+        return NGX_ERROR;
+    }
+
+    if (hash->bucket_limit != 1) {
+
+        for (i = 0; i < best; i++) {
+            test[i] = 0;
+        }
+
+        for (n = (ngx_str_t *) names;
+             n->len;
+             n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+        {
+            key = 0;
+
+            for (i = 0; i < n->len; i++) {
+                key += ngx_tolower(n->data[i]);
+            }
+
+            key %= best;
+
+            test[key]++;
+        }
+
+        for (i = 0; i < best; i++) {
+            if (test[i] == 0) {
+                continue;
+            }
+
+            bucket = ngx_palloc(pool, test[i] * hash->bucket_size);
+            if (bucket == NULL) {
+                ngx_free(test);
+                return NGX_ERROR;
+            }
+
+            hash->buckets[i] = bucket;
+            bucket->len = 0;
+        }
+    }
+
+    for (n = (ngx_str_t *) names;
+         n->len;
+         n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+    {
+        key = 0;
+
+        for (i = 0; i < n->len; i++) {
+            key += ngx_tolower(n->data[i]);
+        }
+
+        key %= best;
+
+        if (hash->bucket_limit == 1) {
+            p = (u_char *) hash->buckets + key * hash->bucket_size;
+            ngx_memcpy(p, n, hash->bucket_size);
+            continue;
+        }
+
+        for (bucket = hash->buckets[key];
+             bucket->len;
+             bucket = (ngx_str_t *) ((char *) bucket + hash->bucket_size))
+        {
+            bucket->len &= 0x7fffffff;
+        }
+
+        ngx_memcpy(bucket, n, hash->bucket_size);
+        bucket->len |= 0x80000000;
+    }
+
+    ngx_free(test);
+
+    hash->hash_size = best;
+    hash->min_buckets = min_buckets;
+
+    return NGX_OK;
+}
diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h
new file mode 100644
index 0000000..5a4bf5f
--- /dev/null
+++ b/src/core/ngx_hash.h
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_HASH_H_INCLUDED_
+#define _NGX_HASH_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct {
+    void        **buckets;
+    ngx_uint_t    hash_size;
+
+    ngx_uint_t    max_size;
+    ngx_uint_t    bucket_limit;
+    size_t        bucket_size;
+    char         *name;
+    ngx_uint_t    min_buckets;
+} ngx_hash_t;
+
+
+typedef struct {
+    ngx_uint_t  hash;
+    ngx_str_t   key;
+    ngx_str_t   value;
+} ngx_table_elt_t;
+
+
+ngx_int_t ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names);
+
+
+#endif /* _NGX_HASH_H_INCLUDED_ */
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c
index 313557d..fc8a0bf 100644
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -119,8 +119,10 @@
                 /* get the free buf */
 
                 if (ctx->free) {
-                    ctx->buf = ctx->free->buf;
-                    ctx->free = ctx->free->next;
+                    cl = ctx->free;
+                    ctx->buf = cl->buf;
+                    ctx->free = cl->next;
+                    ngx_free_chain(ctx->pool, cl);
 
                 } else if (out || ctx->allocated == ctx->bufs.num) {
 
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 8faf9a7..2804dd0 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -22,6 +22,7 @@
     p->end = (u_char *) p + size;
     p->next = NULL;
     p->large = NULL;
+    p->chain = NULL;
     p->log = log;
 
     return p;
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index b310082..bd256e8 100644
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -33,6 +33,7 @@
 struct ngx_pool_s {
     u_char            *last;
     u_char            *end;
+    ngx_chain_t       *chain;
     ngx_pool_t        *next;
     ngx_pool_large_t  *large;
     ngx_log_t         *log;
diff --git a/src/core/ngx_table.h b/src/core/ngx_table.h
deleted file mode 100644
index 5e2f3a9..0000000
--- a/src/core/ngx_table.h
+++ /dev/null
@@ -1,27 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_TABLE_H_INCLUDED_
-#define _NGX_TABLE_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-
-
-typedef ngx_array_t  ngx_table_t;
-
-typedef struct {
-    ngx_str_t  key;
-    ngx_str_t  value;
-} ngx_table_elt_t;
-
-
-#define ngx_create_table(p, n)  ngx_create_array(p, n, 2 * sizeof(ngx_str_t))
-#define ngx_push_table(t)       ngx_push_array(t)
-
-
-#endif /* _NGX_TABLE_H_INCLUDED_ */