diff src/http/modules/proxy/ngx_http_proxy_upstream.c @ 175:e92c2c647c57

nginx-0.0.1-2003-11-05-20:03:41 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 05 Nov 2003 17:03:41 +0000
parents ea464a6c0581
children c0552e5ab567
line wrap: on
line diff
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -11,6 +11,8 @@
 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p);
 static void ngx_http_proxy_init_upstream(void *data);
 static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p);
+static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
+static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev);
 static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p);
 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
@@ -264,7 +266,11 @@ ngx_log_debug(r->connection->log, "timer
 
     wctx->pool = r->pool;
 
-    ngx_http_proxy_connect(p);
+    if (p->lcf->busy_lock) {
+        ngx_http_proxy_upstream_busy_lock(p);
+    } else {
+        ngx_http_proxy_connect(p);
+    }
 }
 
 
@@ -306,6 +312,109 @@ static void ngx_http_proxy_reinit_upstre
 }
 
 
+static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
+{
+    int  ft_type;
+
+    if (p->lcf->busy_lock->conn_n < p->lcf->busy_lock->max_conn) {
+        p->lcf->busy_lock->conn_n++;
+
+        if (p->busy_lock_time) {
+            p->busy_lock_time = 0;
+            p->lcf->busy_lock->waiting_n--;
+        }
+
+        ngx_http_proxy_connect(p);
+        return;
+    }
+
+    if (p->busy_lock_time) {
+        if (p->busy_lock_time < p->lcf->busy_lock->timeout) {
+            ngx_add_timer(p->request->connection->read, 1000);
+            return;
+        }
+
+        p->lcf->busy_lock->waiting_n--;
+        ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
+
+    } else {
+        if (p->lcf->busy_lock->waiting_n < p->lcf->busy_lock->max_waiting) {
+            p->lcf->busy_lock->waiting_n++;
+            ngx_add_timer(p->request->connection->read, 1000);
+            p->request->connection->read->event_handler =
+                                     ngx_http_proxy_upstream_busy_lock_handler;
+            /* TODO: ngx_handle_level_read_event() */
+            return;
+        }
+
+        ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
+    }
+
+    if (p->stale && (p->lcf->use_stale & ft_type)) {
+        ngx_http_proxy_finalize_request(p,
+                                        ngx_http_proxy_send_cached_response(p));
+        return;
+    }
+
+    ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
+    return;
+}
+
+
+static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev)
+{
+    ngx_connection_t      *c;
+    ngx_http_request_t    *r;
+    ngx_http_proxy_ctx_t  *p;
+
+    ngx_log_debug(rev->log, "busy lock");
+
+    c = rev->data;
+    r = c->data;
+    p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+    p->action = "waiting upstream in busy lock";
+
+    if (rev->timedout) {
+        rev->timedout = 0;
+        p->busy_lock_time++;
+        ngx_http_proxy_upstream_busy_lock(p);
+        return;
+    }
+
+    ngx_log_debug(rev->log, "client sent while busy lock");
+
+    /*
+     * TODO: kevent() notify about error, otherwise we need to
+     * call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio
+     * if there's no error we need to disable event.
+     */
+
+#if (HAVE_KQUEUE)
+
+    if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) {
+        p->lcf->busy_lock->waiting_n--;
+
+        ngx_del_timer(rev);
+
+        ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno,
+                      "client() closed connection");
+
+        if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) {
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        /* we have not HTTP code for the case when a client cancels a request */
+
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
+
+#endif
+
+}
+
+
 static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
 {
     int                      rc;
@@ -1011,8 +1120,7 @@ static void ngx_http_proxy_process_body(
         }
 
         if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) {
-            ngx_http_proxy_close_connection(p->upstream->peer.connection);
-            p->upstream->peer.connection = NULL;
+            ngx_http_proxy_close_connection(p);
         }
     }
 
@@ -1024,8 +1132,7 @@ static void ngx_http_proxy_process_body(
 
     if (ep->downstream_error) {
         if (!p->cachable && p->upstream->peer.connection) {
-            ngx_http_proxy_close_connection(p->upstream->peer.connection);
-            p->upstream->peer.connection = NULL;
+            ngx_http_proxy_close_connection(p);
         }
  
         if (p->upstream->peer.connection == NULL) {
@@ -1080,8 +1187,7 @@ ngx_log_debug(p->request->connection->lo
     }
 
     if (p->upstream->peer.connection) {
-        ngx_http_proxy_close_connection(p->upstream->peer.connection);
-        p->upstream->peer.connection = NULL;
+        ngx_http_proxy_close_connection(p);
     }
 
     if (status) {
@@ -1100,5 +1206,9 @@ ngx_log_debug(p->request->connection->lo
         }
     }
 
-    ngx_http_proxy_connect(p);
+    if (p->lcf->busy_lock) {
+        ngx_http_proxy_upstream_busy_lock(p);
+    } else {
+        ngx_http_proxy_connect(p);
+    }
 }