changeset 554:5c576ea5dbd9 NGINX_0_8_29

nginx 0.8.29 *) Change: now the "009" status code is written to an access log for proxied HTTP/0.9 responses. *) Feature: the "addition_types", "charset_types", "gzip_types", "ssi_types", "sub_filter_types", and "xslt_types" directives support an "*" parameter. *) Feature: GCC 4.1+ built-in atomic operations usage. Thanks to W-Mark Kubacki. *) Feature: the --with-libatomic[=DIR] option in the configure. Thanks to W-Mark Kubacki. *) Bugfix: listen unix domain socket had limited access rights. *) Bugfix: cached HTTP/0.9 responses were handled incorrectly. *) Bugfix: regular expression named captures given by "?P<...>" did not work in a "server_name" directive. Thanks to Maxim Dounin.
author Igor Sysoev <http://sysoev.ru>
date Mon, 30 Nov 2009 00:00:00 +0300
parents 63dde5a94756
children f107b2f5d305
files CHANGES CHANGES.ru auto/cc/conf auto/cc/gcc auto/feature auto/lib/conf auto/lib/libatomic/conf auto/lib/libatomic/make auto/lib/make auto/options src/core/nginx.h src/core/ngx_connection.c src/event/ngx_event_connect.c src/http/modules/ngx_http_addition_filter_module.c src/http/modules/ngx_http_charset_filter_module.c src/http/modules/ngx_http_gzip_filter_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_sub_filter_module.c src/http/modules/ngx_http_xslt_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_file_cache.c src/http/ngx_http_upstream.c src/os/unix/ngx_atomic.h src/os/unix/ngx_gcc_atomic_x86.h
diffstat 29 files changed, 303 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES	Mon Nov 23 00:00:00 2009 +0300
+++ b/CHANGES	Mon Nov 30 00:00:00 2009 +0300
@@ -1,4 +1,28 @@
 
+Changes with nginx 0.8.29                                        30 Nov 2009
+
+    *) Change: now the "009" status code is written to an access log for 
+       proxied HTTP/0.9 responses.
+
+    *) Feature: the "addition_types", "charset_types", "gzip_types", 
+       "ssi_types", "sub_filter_types", and "xslt_types" directives support 
+       an "*" parameter.
+
+    *) Feature: GCC 4.1+ built-in atomic operations usage.
+       Thanks to W-Mark Kubacki.
+
+    *) Feature: the --with-libatomic[=DIR] option in the configure.
+       Thanks to W-Mark Kubacki.
+
+    *) Bugfix: listen unix domain socket had limited access rights.
+
+    *) Bugfix: cached HTTP/0.9 responses were handled incorrectly.
+
+    *) Bugfix: regular expression named captures given by "?P<...>" did not 
+       work in a "server_name" directive.
+       Thanks to Maxim Dounin.
+
+
 Changes with nginx 0.8.28                                        23 Nov 2009
 
     *) Bugfix: nginx could not be built with the --without-pcre parameter; 
--- a/CHANGES.ru	Mon Nov 23 00:00:00 2009 +0300
+++ b/CHANGES.ru	Mon Nov 30 00:00:00 2009 +0300
@@ -1,4 +1,29 @@
 
+Изменения в nginx 0.8.29                                          30.11.2009
+
+    *) Изменение: теперь для проксируемых ответов HTTP/0.9 в лог пишется 
+       код ответа "009".
+
+    *) Добавление: директивы addition_types, charset_types, gzip_types, 
+       ssi_types, sub_filter_types и xslt_types поддерживают параметр "*".
+
+    *) Добавление: использование встроенных атомарных операций GCC 4.1+.
+       Спасибо W-Mark Kubacki.
+
+    *) Добавление: параметр --with-libatomic[=DIR] в configure.
+       Спасибо W-Mark Kubacki.
+
+    *) Исправление: listen unix domain сокет имели ограниченные права 
+       доступа.
+
+    *) Исправление: закэшированные ответы ответов HTTP/0.9 неправильно 
+       обрабатывались.
+
+    *) Исправление: именованные выделения в регулярных выражениях, заданные 
+       как "?P<...>", не работали в директиве server_name.
+       Спасибо Максиму Дунину.
+
+
 Изменения в nginx 0.8.28                                          23.11.2009
 
     *) Исправление: nginx не собирался с параметром --without-pcre; ошибка 
--- a/auto/cc/conf	Mon Nov 23 00:00:00 2009 +0300
+++ b/auto/cc/conf	Mon Nov 30 00:00:00 2009 +0300
@@ -104,7 +104,7 @@
 fi
 
 CFLAGS="$CFLAGS $NGX_CC_OPT"
-
+NGX_TEST_LD_OPT="$NGX_LD_OPT"
 
 if [ "$NGX_PLATFORM" != win32 ]; then
 
@@ -125,6 +125,24 @@
         fi
     fi
 
+
+    ngx_feature="gcc builtin atomic operations"
+    ngx_feature_name=NGX_HAVE_GCC_ATOMIC
+    ngx_feature_run=yes
+    ngx_feature_incs=
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test="long  n = 0;
+                      if (!__sync_bool_compare_and_swap(&n, 0, 1))
+                          return 1;
+                      if (__sync_fetch_and_add(&n, 1) != 1)
+                          return 1;
+                      if (n != 2)
+                          return 1;
+                      __sync_synchronize();"
+    . auto/feature
+
+
     ngx_feature="gcc variadic macros"
     ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
     ngx_feature_run=yes
--- a/auto/cc/gcc	Mon Nov 23 00:00:00 2009 +0300
+++ b/auto/cc/gcc	Mon Nov 30 00:00:00 2009 +0300
@@ -90,7 +90,6 @@
         # build 32-bit UltraSparc binary
         CPU_OPT="-m32"
         CORE_LINK="$CORE_LINK -m32"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m32"
         NGX_CPU_CACHE_LINE=64
     ;;
 
@@ -98,7 +97,6 @@
         # build 64-bit UltraSparc binary
         CPU_OPT="-m64"
         CORE_LINK="$CORE_LINK -m64"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m64"
         NGX_CPU_CACHE_LINE=64
     ;;
 
@@ -108,12 +106,12 @@
         CPU_OPT="$CPU_OPT -falign-functions=32 -falign-labels=32"
         CPU_OPT="$CPU_OPT -falign-loops=32 -falign-jumps=32"
         CORE_LINK="$CORE_LINK -m64"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m64"
         NGX_CPU_CACHE_LINE=128
     ;;
 
 esac
 
+CC_AUX_FLAGS="$CC_AUX_FLAGS $CPU_OPT"
 
 case "$NGX_GCC_VER" in
     2.7*)
--- a/auto/feature	Mon Nov 23 00:00:00 2009 +0300
+++ b/auto/feature	Mon Nov 30 00:00:00 2009 +0300
@@ -39,7 +39,7 @@
 
 
 ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
+          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"
 
 ngx_feature_inc_path=
 
--- a/auto/lib/conf	Mon Nov 23 00:00:00 2009 +0300
+++ b/auto/lib/conf	Mon Nov 30 00:00:00 2009 +0300
@@ -70,6 +70,11 @@
 if [ $HTTP_GEOIP = YES ]; then
     . auto/lib/geoip/conf
 fi
+
 if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then
     . auto/lib/google-perftools/conf
 fi
+
+if [ $NGX_LIBATOMIC != NO ]; then
+    . auto/lib/libatomic/conf
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auto/lib/libatomic/conf	Mon Nov 30 00:00:00 2009 +0300
@@ -0,0 +1,41 @@
+
+# Copyright (C) Igor Sysoev
+
+
+if [ $NGX_LIBATOMIC != YES ]; then
+
+    have=NGX_HAVE_LIBATOMIC . auto/have
+    CORE_INCS="$CORE_INCS $NGX_LIBATOMIC/src"
+    LINK_DEPS="$LINK_DEPS $NGX_LIBATOMIC/src/libatomic_ops.a"
+    CORE_LIBS="$CORE_LIBS $NGX_LIBATOMIC/src/libatomic_ops.a"
+
+else
+
+    ngx_feature="atomic_ops library"
+    ngx_feature_name=NGX_HAVE_LIBATOMIC
+    ngx_feature_run=yes
+    ngx_feature_incs="#include <atomic_ops.h>"
+    ngx_feature_path=
+    ngx_feature_libs="-latomic_ops"
+    ngx_feature_test="long  n = 0;
+                      if (!AO_compare_and_swap(&n, 0, 1))
+                          return 1;
+                      if (AO_fetch_and_add(&n, 1) != 1)
+                          return 1;
+                      if (n != 2)
+                          return 1;
+                      AO_nop();"
+    . auto/feature
+
+    if [ $ngx_found = yes ]; then
+        CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+    else
+
+cat << END
+
+$0: error: libatomic_ops library was not found.
+
+END
+        exit 1
+    fi
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auto/lib/libatomic/make	Mon Nov 30 00:00:00 2009 +0300
@@ -0,0 +1,13 @@
+
+# Copyright (C) Igor Sysoev
+
+
+    cat << END                                            >> $NGX_MAKEFILE
+
+$NGX_LIBATOMIC/src/libatomic_ops.a:	$NGX_LIBATOMIC/Makefile
+	cd $NGX_LIBATOMIC && make
+
+$NGX_LIBATOMIC/Makefile:	$NGX_MAKEFILE
+	cd $NGX_LIBATOMIC && ./configure
+
+END
--- a/auto/lib/make	Mon Nov 23 00:00:00 2009 +0300
+++ b/auto/lib/make	Mon Nov 30 00:00:00 2009 +0300
@@ -22,6 +22,10 @@
     . auto/lib/zlib/make
 fi
 
+if [ $NGX_LIBATOMIC != NO -a $NGX_LIBATOMIC != YES ]; then
+    . auto/lib/libatomic/make
+fi
+
 if [ $USE_PERL = YES ]; then
     . auto/lib/perl/make
 fi
--- a/auto/options	Mon Nov 23 00:00:00 2009 +0300
+++ b/auto/options	Mon Nov 30 00:00:00 2009 +0300
@@ -132,6 +132,8 @@
 NGX_GOOGLE_PERFTOOLS=NO
 NGX_CPP_TEST=NO
 
+NGX_LIBATOMIC=NO
+
 NGX_CPU_CACHE_LINE=
 
 opt=
@@ -266,6 +268,9 @@
         --with-zlib-opt=*)               ZLIB_OPT="$value"          ;;
         --with-zlib-asm=*)               ZLIB_ASM="$value"          ;;
 
+        --with-libatomic)                NGX_LIBATOMIC=YES          ;;
+        --with-libatomic=*)              NGX_LIBATOMIC="$value"     ;;
+
         --test-build-devpoll)            NGX_TEST_BUILD_DEVPOLL=YES ;;
         --test-build-eventport)          NGX_TEST_BUILD_EVENTPORT=YES ;;
         --test-build-epoll)              NGX_TEST_BUILD_EPOLL=YES   ;;
@@ -400,6 +405,9 @@
                                      for specified CPU, the valid values:
                                      pentium, pentiumpro
 
+  --with-libatomic                   force libatomic_ops library usage
+  --with-libatomic=DIR               set path to libatomic_ops library sources
+
   --with-openssl=DIR                 set path to OpenSSL library sources
   --with-openssl-opt=OPTIONS         set additional options for OpenSSL building
 
--- a/src/core/nginx.h	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/core/nginx.h	Mon Nov 30 00:00:00 2009 +0300
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8028
-#define NGINX_VERSION      "0.8.28"
+#define nginx_version         8029
+#define NGINX_VERSION      "0.8.29"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_connection.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/core/ngx_connection.c	Mon Nov 30 00:00:00 2009 +0300
@@ -374,12 +374,23 @@
 
 #if (NGX_HAVE_UNIX_DOMAIN)
 
-            if (ngx_test_config && ls[i].sockaddr->sa_family == AF_UNIX) {
-                u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
+            if (ls[i].sockaddr->sa_family == AF_UNIX) {
+                mode_t   mode;
+                u_char  *name;
+
+                name = ls[i].addr_text.data + sizeof("unix:") - 1;
+                mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
 
-                if (ngx_delete_file(name) == -1) {
-                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
-                                  ngx_delete_file_n " %s failed", name);
+                if (chmod((char *) name, mode) == -1) {
+                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                                  "chmod() \"%s\" failed", name);
+                }
+
+                if (ngx_test_config) {
+                    if (ngx_delete_file(name) == -1) {
+                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                                      ngx_delete_file_n " %s failed", name);
+                    }
                 }
             }
 #endif
--- a/src/event/ngx_event_connect.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/event/ngx_event_connect.c	Mon Nov 30 00:00:00 2009 +0300
@@ -101,22 +101,17 @@
 
     pc->connection = c;
 
-    /*
-     * TODO: MT: - ngx_atomic_fetch_add()
-     *             or protection by critical section or mutex
-     *
-     * TODO: MP: - allocated in a shared memory
-     *           - ngx_atomic_fetch_add()
-     *             or protection by critical section or mutex
-     */
-
     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
 
 #if (NGX_THREADS)
+
+    /* TODO: lock event when call completion handler */
+
     rev->lock = pc->lock;
     wev->lock = pc->lock;
     rev->own_lock = &c->lock;
     wev->own_lock = &c->lock;
+
 #endif
 
     if (ngx_add_conn) {
--- a/src/http/modules/ngx_http_addition_filter_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_addition_filter_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -237,8 +237,8 @@
     ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
     ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_charset_filter_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_charset_filter_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -1550,8 +1550,8 @@
     ngx_http_charset_recode_t     *recode;
     ngx_http_charset_main_conf_t  *mcf;
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_charset_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_gzip_filter_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_gzip_filter_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -1123,8 +1123,8 @@
                               MAX_MEM_LEVEL - 1);
     ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_log_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_log_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -542,8 +542,25 @@
 static u_char *
 ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
 {
-    return ngx_sprintf(buf, "%ui",
-                       r->err_status ? r->err_status : r->headers_out.status);
+    ngx_uint_t  status;
+
+    if (r->err_status) {
+        status = r->err_status;
+
+    } else if (r->headers_out.status) {
+        status = r->headers_out.status;
+
+    } else if (r->http_version == NGX_HTTP_VERSION_9) {
+        *buf++ = '0';
+        *buf++ = '0';
+        *buf++ = '9';
+        return buf;
+
+    } else {
+        status = 0;
+    }
+
+    return ngx_sprintf(buf, "%ui", status);
 }
 
 
--- a/src/http/modules/ngx_http_proxy_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_proxy_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -1230,7 +1230,6 @@
 
         if (r->cache) {
             r->http_version = NGX_HTTP_VERSION_9;
-            u->headers_in.status_n = NGX_HTTP_OK;
             return NGX_OK;
         }
 
@@ -1246,7 +1245,6 @@
 #endif
 
         r->http_version = NGX_HTTP_VERSION_9;
-        u->headers_in.status_n = NGX_HTTP_OK;
         u->state->status = NGX_HTTP_OK;
 
         return NGX_OK;
--- a/src/http/modules/ngx_http_ssi_filter_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_ssi_filter_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -2773,8 +2773,8 @@
     ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024);
     ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256);
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_sub_filter_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_sub_filter_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -671,8 +671,8 @@
         conf->value = prev->value;
     }
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_xslt_filter_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_xslt_filter_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -1230,8 +1230,8 @@
         conf->sheets = prev->sheets;
     }
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_xslt_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/perl/nginx.pm	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/modules/perl/nginx.pm	Mon Nov 30 00:00:00 2009 +0300
@@ -47,7 +47,7 @@
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.8.28';
+our $VERSION = '0.8.29';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/ngx_http.c	Mon Nov 30 00:00:00 2009 +0300
@@ -1854,6 +1854,10 @@
 
     types = (ngx_array_t **) (p + cmd->offset);
 
+    if (*types == (void *) -1) {
+        return NGX_CONF_OK;
+    }
+
     default_type = cmd->post;
 
     if (*types == NULL) {
@@ -1879,6 +1883,11 @@
 
     for (i = 1; i < cf->args->nelts; i++) {
 
+        if (value[i].len == 1 && value[i].data[0] == '*') {
+            *types = (void *) -1;
+            return NGX_CONF_OK;
+        }
+
         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
         value[i].data[value[i].len] = '\0';
 
@@ -1907,13 +1916,17 @@
 
 
 char *
-ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
-    ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
+ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
+    ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
     ngx_str_t *default_types)
 {
     ngx_hash_init_t  hash;
 
-    if (keys) {
+    if (*keys) {
+
+        if (*keys == (void *) -1) {
+            return NGX_CONF_OK;
+        }
 
         hash.hash = types_hash;
         hash.key = NULL;
@@ -1923,7 +1936,7 @@
         hash.pool = cf->pool;
         hash.temp_pool = NULL;
 
-        if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
+        if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
 
@@ -1932,13 +1945,17 @@
 
     if (prev_types_hash->buckets == NULL) {
 
-        if (prev_keys == NULL) {
+        if (*prev_keys == NULL) {
 
-            if (ngx_http_set_default_types(cf, &prev_keys, default_types)
+            if (ngx_http_set_default_types(cf, prev_keys, default_types)
                 != NGX_OK)
             {
                 return NGX_CONF_ERROR;
             }
+
+        } else if (*prev_keys == (void *) -1) {
+            *keys = *prev_keys;
+            return NGX_CONF_OK;
         }
 
         hash.hash = prev_types_hash;
@@ -1949,7 +1966,9 @@
         hash.pool = cf->pool;
         hash.temp_pool = NULL;
 
-        if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
+        if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
+            != NGX_OK)
+        {
             return NGX_CONF_ERROR;
         }
     }
--- a/src/http/ngx_http.h	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/ngx_http.h	Mon Nov 30 00:00:00 2009 +0300
@@ -126,9 +126,9 @@
 
 
 char *ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-char *ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys,
-    ngx_hash_t *types_hash, ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
-    ngx_str_t *default_types);
+char *ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys,
+    ngx_hash_t *types_hash, ngx_array_t **prev_keys,
+    ngx_hash_t *prev_types_hash, ngx_str_t *default_types);
 ngx_int_t ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
     ngx_str_t *default_type);
 
--- a/src/http/ngx_http_core_module.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/ngx_http_core_module.c	Mon Nov 30 00:00:00 2009 +0300
@@ -1572,6 +1572,10 @@
     size_t      len;
     ngx_uint_t  i, hash;
 
+    if (types_hash->size == 0) {
+        return (void *) 4;
+    }
+
     if (r->headers_out.content_type.len == 0) {
         return NULL;
     }
@@ -3507,16 +3511,16 @@
         sn->server = cscf;
         sn->name = value[i];
 
-        ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
-
         if (value[i].data[0] != '~') {
+            ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
             continue;
         }
 
 #if (NGX_PCRE)
         {
-        ngx_regex_compile_t  rc;
-        u_char               errstr[NGX_MAX_CONF_ERRSTR];
+        u_char               *p;
+        ngx_regex_compile_t   rc;
+        u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
         if (value[i].len == 1) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -3533,6 +3537,13 @@
         rc.err.len = NGX_MAX_CONF_ERRSTR;
         rc.err.data = errstr;
 
+        for (p = value[i].data; p < value[i].data + value[i].len; p++) {
+            if (*p >= 'A' && *p <= 'Z') {
+                rc.options = NGX_REGEX_CASELESS;
+                break;
+            }
+        }
+
         sn->regex = ngx_http_regex_compile(cf, &rc);
         if (sn->regex == NULL) {
             return NGX_CONF_ERROR;
--- a/src/http/ngx_http_file_cache.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/ngx_http_file_cache.c	Mon Nov 30 00:00:00 2009 +0300
@@ -338,7 +338,7 @@
         return n;
     }
 
-    if ((size_t) n <= c->header_start) {
+    if ((size_t) n < c->header_start) {
         ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
                       "cache file \"%s\" is too small", c->file.name.data);
         return NGX_ERROR;
--- a/src/http/ngx_http_upstream.c	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/http/ngx_http_upstream.c	Mon Nov 30 00:00:00 2009 +0300
@@ -752,6 +752,11 @@
     r->cached = 1;
     c = r->cache;
 
+    if (c->header_start == c->body_start) {
+        r->http_version = NGX_HTTP_VERSION_9;
+        return ngx_http_cache_send(r);
+    }
+
     /* TODO: cache stack */
 
     u->buffer = *c->buf;
--- a/src/os/unix/ngx_atomic.h	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/os/unix/ngx_atomic.h	Mon Nov 30 00:00:00 2009 +0300
@@ -12,7 +12,31 @@
 #include <ngx_core.h>
 
 
-#if (NGX_DARWIN_ATOMIC)
+#if (NGX_HAVE_LIBATOMIC)
+
+#include <atomic_ops.h>
+
+#define NGX_HAVE_ATOMIC_OPS  1
+
+typedef long                        ngx_atomic_int_t;
+typedef AO_t                        ngx_atomic_uint_t;
+typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
+
+#if (NGX_PTR_SIZE == 8)
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
+#else
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
+#endif
+
+#define ngx_atomic_cmp_set(lock, old, new)                                    \
+    AO_compare_and_swap(lock, old, new)
+#define ngx_atomic_fetch_add(value, add)                                      \
+    AO_fetch_and_add(value, add)
+#define ngx_memory_barrier()        AO_nop()
+#define ngx_cpu_pause()
+
+
+#elif (NGX_DARWIN_ATOMIC)
 
 /*
  * use Darwin 8 atomic(3) and barrier(3) operations
@@ -60,10 +84,40 @@
 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
 
 
-#else /* !(NGX_DARWIN) */
+#elif (NGX_HAVE_GCC_ATOMIC)
+
+/* GCC 4.1 builtin atomic operations */
+
+#define NGX_HAVE_ATOMIC_OPS  1
+
+typedef long                        ngx_atomic_int_t;
+typedef unsigned long               ngx_atomic_uint_t;
+
+#if (NGX_PTR_SIZE == 8)
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
+#else
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
+#endif
+
+typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
 
 
-#if ( __i386__ || __i386 )
+#define ngx_atomic_cmp_set(lock, old, set)                                    \
+    __sync_bool_compare_and_swap(lock, old, set)
+
+#define ngx_atomic_fetch_add(value, add)                                      \
+    __sync_fetch_and_add(value, add)
+
+#define ngx_memory_barrier()        __sync_synchronize()
+
+#if ( __i386__ || __i386 || __amd64__ || __amd64 )
+#define ngx_cpu_pause()             __asm__ ("pause")
+#else
+#define ngx_cpu_pause()
+#endif
+
+
+#elif ( __i386__ || __i386 )
 
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;
@@ -203,9 +257,6 @@
 
 #include "ngx_gcc_atomic_ppc.h"
 
-
-#endif
-
 #endif
 
 
--- a/src/os/unix/ngx_gcc_atomic_x86.h	Mon Nov 23 00:00:00 2009 +0300
+++ b/src/os/unix/ngx_gcc_atomic_x86.h	Mon Nov 30 00:00:00 2009 +0300
@@ -122,5 +122,5 @@
 
 #define ngx_memory_barrier()    __asm__ volatile ("" ::: "memory")
 
-/* old as does not support "pause" opcode */
+/* old "as" does not support "pause" opcode */
 #define ngx_cpu_pause()         __asm__ (".byte 0xf3, 0x90")