nginx-0.3.2-RELEASE import

    *) Feature: the Sun Studio 10 C compiler support.

    *) Feature: the "proxy_upstream_max_fails",
       "proxy_upstream_fail_timeout", "fastcgi_upstream_max_fails", and
       "fastcgi_upstream_fail_timeout" directives.
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index c541807..d58c7c6 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -151,10 +151,6 @@
 static ngx_conf_post_t  ngx_http_fastcgi_lowat_post =
     { ngx_http_fastcgi_lowat_check };
 
-static ngx_conf_enum_t  ngx_http_fastcgi_set_methods[] = {
-    { ngx_string("get"), NGX_HTTP_GET },
-    { ngx_null_string, 0 }
-};
 
 static ngx_conf_bitmask_t  ngx_http_fastcgi_next_upstream_masks[] = {
     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
@@ -210,13 +206,6 @@
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.header_buffer_size),
       NULL },
 
-    { ngx_string("fastcgi_method"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_enum_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.method),
-      ngx_http_fastcgi_set_methods },
-
     { ngx_string("fastcgi_pass_request_headers"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -294,6 +283,20 @@
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
       &ngx_http_fastcgi_next_upstream_masks },
 
+    { ngx_string("fastcgi_upstream_max_fails"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_fails),
+      NULL },
+
+    { ngx_string("fastcgi_upstream_fail_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_sec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.fail_timeout),
+      NULL },
+
     { ngx_string("fastcgi_param"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
       ngx_conf_set_table_elt_slot,
@@ -1443,7 +1446,9 @@
     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; 
     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
 
-    conf->upstream.method = NGX_CONF_UNSET_UINT;
+    conf->upstream.max_fails = NGX_CONF_UNSET_UINT;
+    conf->upstream.fail_timeout = NGX_CONF_UNSET;
+
     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
     conf->upstream.pass_request_body = NGX_CONF_UNSET;
 
@@ -1591,15 +1596,25 @@
                                |NGX_HTTP_UPSTREAM_FT_ERROR
                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
 
+    ngx_conf_merge_unsigned_value(conf->upstream.max_fails,
+                              prev->upstream.max_fails, 1);
+
+    ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
+                              prev->upstream.fail_timeout, 10);
+
+    if (conf->peers && conf->peers->number > 1) {
+        for (i = 0; i < conf->peers->number; i++) {
+            conf->peers->peer[i].weight = 1;
+            conf->peers->peer[i].max_fails = conf->upstream.max_fails;
+            conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+        }
+    }
+
     ngx_conf_merge_path_value(conf->upstream.temp_path,
                               prev->upstream.temp_path,
                               NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0,
                               ngx_garbage_collector_temp_handler, cf);
 
-    if (conf->upstream.method == NGX_CONF_UNSET_UINT) {
-        conf->upstream.method = prev->upstream.method; 
-    }
-
     ngx_conf_merge_value(conf->upstream.pass_request_headers,
                               prev->upstream.pass_request_headers, 1);
     ngx_conf_merge_value(conf->upstream.pass_request_body,
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index e1ee7b4..8c4231a 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -46,6 +46,7 @@
 
     ngx_array_t                 *redirects;
 
+    ngx_str_t                    method;
     ngx_str_t                    host_header;
     ngx_str_t                    port_text;
 
@@ -100,10 +101,6 @@
 static ngx_conf_post_t  ngx_http_proxy_lowat_post =
     { ngx_http_proxy_lowat_check };
 
-static ngx_conf_enum_t  ngx_http_proxy_set_methods[] = {
-    { ngx_string("get"), NGX_HTTP_GET },
-    { ngx_null_string, 0 }
-};
 
 static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
@@ -168,10 +165,10 @@
 
     { ngx_string("proxy_method"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_enum_slot,
+      ngx_conf_set_str_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_proxy_loc_conf_t, upstream.method),
-      ngx_http_proxy_set_methods },
+      offsetof(ngx_http_proxy_loc_conf_t, method),
+      NULL },
 
     { ngx_string("proxy_pass_request_headers"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
@@ -243,6 +240,20 @@
       offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
       &ngx_http_proxy_next_upstream_masks },
 
+    { ngx_string("proxy_upstream_max_fails"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.max_fails),
+      NULL },
+
+    { ngx_string("proxy_upstream_fail_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_sec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.fail_timeout),
+      NULL },
+
     { ngx_string("proxy_pass_x_powered_by"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -299,13 +310,6 @@
 };
 
 
-static ngx_str_t ngx_http_proxy_methods[] = {
-    ngx_string("GET "),
-    ngx_string("HEAD "),
-    ngx_string("POST ")
-};
-
-
 static char  ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
 
 
@@ -394,7 +398,7 @@
     ngx_uint_t                    i, key;
     uintptr_t                     escape;
     ngx_buf_t                    *b;
-    ngx_str_t                    *hh;
+    ngx_str_t                    *hh, method;
     ngx_chain_t                  *cl, *body;
     ngx_list_part_t              *part;
     ngx_table_elt_t              *header;
@@ -410,12 +414,21 @@
 
     len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
 
-    if (u->method) {
-        len += ngx_http_proxy_methods[u->method - 1].len + u->conf->uri.len;
+    if (u->method.len) {
+        /* HEAD was changed to GET to cache response */
+        method = u->method;
+        method.len++;
+
+    } else if (plcf->method.len) {
+        method = plcf->method;
+
     } else {
-        len += r->method_name.len + 1 + u->conf->uri.len;
+        method = r->method_name;
+        method.len++;
     }
 
+    len += method.len + u->conf->uri.len;
+
     escape = 0;
 
     loc_len = r->valid_location ? u->conf->location->len : 0;
@@ -493,14 +506,7 @@
 
     /* the request line */
 
-    if (u->method) {
-        b->last = ngx_cpymem(b->last,
-                             ngx_http_proxy_methods[u->method - 1].data,
-                             ngx_http_proxy_methods[u->method - 1].len);
-    } else {
-        b->last = ngx_cpymem(b->last, r->method_name.data,
-                             r->method_name.len + 1);
-    }
+    b->last = ngx_cpymem(b->last, method.data, method.len);
 
     u->uri.data = b->last;
 
@@ -1288,6 +1294,7 @@
      *     conf->upstream.uri = { 0, NULL };
      *     conf->upstream.location = NULL;
      *
+     *     conf->method = NULL;
      *     conf->headers_source = NULL;
      *     conf->headers_set_len = NULL;
      *     conf->headers_set = NULL;
@@ -1306,10 +1313,12 @@
     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;  
     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
 
-    conf->upstream.method = NGX_CONF_UNSET_UINT;
+    conf->upstream.max_fails = NGX_CONF_UNSET_UINT;
+    conf->upstream.fail_timeout = NGX_CONF_UNSET;
+
     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
     conf->upstream.pass_request_body = NGX_CONF_UNSET;
-    
+
     conf->upstream.redirect_errors = NGX_CONF_UNSET;
 
     /* "proxy_cyclic_temp_file" is disabled */
@@ -1440,10 +1449,10 @@
         && conf->upstream.max_temp_file_size < size)
     {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-             "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
+             "\"proxy_max_temp_file_size\" must be equal to zero to disable "
              "the temporary files usage or must be equal or bigger than "
-             "maximum of the value of \"fastcgi_header_buffer_size\" and "
-             "one of the \"fastcgi_buffers\"");
+             "maximum of the value of \"proxy_header_buffer_size\" and "
+             "one of the \"proxy_buffers\"");
 
         return NGX_CONF_ERROR;
     }
@@ -1455,13 +1464,31 @@
                                |NGX_HTTP_UPSTREAM_FT_ERROR
                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
 
+    ngx_conf_merge_unsigned_value(conf->upstream.max_fails,
+                              prev->upstream.max_fails, 1);
+
+    ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
+                              prev->upstream.fail_timeout, 10);
+
+    if (conf->peers && conf->peers->number > 1) {
+        for (i = 0; i < conf->peers->number; i++) {
+            conf->peers->peer[i].weight = 1;
+            conf->peers->peer[i].max_fails = conf->upstream.max_fails;
+            conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+        }
+    }
+
     ngx_conf_merge_path_value(conf->upstream.temp_path,
                               prev->upstream.temp_path,
                               NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
                               ngx_garbage_collector_temp_handler, cf);
 
-    if (conf->upstream.method == NGX_CONF_UNSET_UINT) {
-        conf->upstream.method = prev->upstream.method;
+    if (conf->method.len == 0) {
+        conf->method = prev->method;
+
+    } else {
+        conf->method.data[conf->method.len] = ' ';
+        conf->method.len++;
     }
 
     ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 54702cc..dcb3956 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -721,10 +721,10 @@
         }
     }
 
-#if (NGX_DEBUG)
+#if (NGX_DEBUG0)
     {
     u_char      address[20];
-    ngx_uint_t  p, a, n;
+    ngx_uint_t  p, a, nn;
 
     in_port = in_ports.elts;
     for (p = 0; p < in_ports.nelts; p++) {
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 19bc239..2fb1764 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -174,13 +174,13 @@
             ngx_mutex_unlock(ngx_posted_events_mutex);
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_inc(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
             return;
         }
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_inc(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
 
         ngx_http_init_request(rev);
@@ -195,7 +195,7 @@
     }
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_inc(ngx_stat_reading);
+    ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
 
 }
@@ -226,7 +226,7 @@
         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_dec(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
         ngx_http_close_connection(c);
@@ -238,7 +238,7 @@
     if (hc) {
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_inc(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
 
     } else {
@@ -246,7 +246,7 @@
         if (hc == NULL) {
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_dec(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
             ngx_http_close_connection(c);
@@ -270,7 +270,7 @@
         if (r == NULL) {
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_dec(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
             ngx_http_close_connection(c);
@@ -281,7 +281,7 @@
     }
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_dec(ngx_stat_reading);
+    ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
     c->data = r;
@@ -439,9 +439,9 @@
     r->log_handler = ngx_http_log_error_handler;
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_inc(ngx_stat_reading);
+    ngx_atomic_fetch_add(ngx_stat_reading, 1);
     r->stat_reading = 1;
-    ngx_atomic_inc(ngx_stat_requests);
+    ngx_atomic_fetch_add(ngx_stat_requests, 1);
 #endif
 
     rev->handler(rev);
@@ -669,9 +669,9 @@
                 }
 
 #if (NGX_STAT_STUB)
-                ngx_atomic_dec(ngx_stat_reading);
+                ngx_atomic_fetch_add(ngx_stat_reading, -1);
                 r->stat_reading = 0;
-                ngx_atomic_inc(ngx_stat_writing);
+                ngx_atomic_fetch_add(ngx_stat_writing, 1);
                 r->stat_writing = 1;
 #endif
 
@@ -899,9 +899,9 @@
             }
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_dec(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, -1);
             r->stat_reading = 0;
-            ngx_atomic_inc(ngx_stat_writing);
+            ngx_atomic_fetch_add(ngx_stat_writing, 1);
             r->stat_writing = 1;
 #endif
 
@@ -2396,11 +2396,11 @@
 
 #if (NGX_STAT_STUB)
     if (r->stat_reading) {
-        ngx_atomic_dec(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, -1);
     }
 
     if (r->stat_writing) {
-        ngx_atomic_dec(ngx_stat_writing);
+        ngx_atomic_fetch_add(ngx_stat_writing, -1);
     }
 #endif
 
@@ -2457,7 +2457,7 @@
 #endif
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_dec(ngx_stat_active);
+    ngx_atomic_fetch_add(ngx_stat_active, -1);
 #endif
 
     pool = c->pool;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index dd32f63..a1c6a2e 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -251,13 +251,6 @@
         u->request_bufs = r->request_body->bufs;
     }
 
-    if (u->conf->method == NGX_CONF_UNSET_UINT) {
-        u->method = r->method;
-
-    } else {
-        u->method = u->conf->method;
-    }
-
     if (u->create_request(r) != NGX_OK) {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 6d96737..dd7b3c1 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -62,7 +62,9 @@
     size_t                          temp_file_write_size_conf;
 
     ngx_uint_t                      next_upstream;
-    ngx_uint_t                      method;
+    ngx_uint_t                      max_fails;
+
+    time_t                          fail_timeout;
 
     ngx_bufs_t                      bufs;
 
@@ -156,7 +158,7 @@
 
     ngx_msec_t                      timeout;
 
-    ngx_uint_t                      method;
+    ngx_str_t                       method;
 
     ngx_http_log_handler_pt         saved_log_handler;
 
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 7b0d231..7e4a79f 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -33,6 +33,8 @@
 static ngx_http_variable_value_t *
     ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data);
 static ngx_http_variable_value_t *
+    ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
     ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data);
 
 
@@ -107,8 +109,7 @@
     { ngx_string("server_name"), ngx_http_variable_request,
       offsetof(ngx_http_request_t, server_name), 0, 0 },
 
-    { ngx_string("request_method"), ngx_http_variable_request,
-      offsetof(ngx_http_request_t, method_name), 0, 0 },
+    { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 },
 
     { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 },
 
@@ -641,6 +642,33 @@
 
 
 static ngx_http_variable_value_t *
+ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_http_variable_value_t  *vv;
+
+    if (r->method_name.data == NULL) {
+        return NGX_HTTP_VAR_NOT_FOUND;
+    }
+
+    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (vv == NULL) {
+        return NULL;
+    }
+
+    vv->value = 0;
+
+    if (r->upstream && r->upstream->method.len) {
+        vv->text = r->upstream->method;
+
+    } else {
+        vv->text = r->method_name;
+    }
+
+    return vv;
+}
+
+
+static ngx_http_variable_value_t *
 ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data)
 {
     ngx_int_t                   rc;