changeset 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
files src/core/ngx_file.c src/core/ngx_string.c src/core/ngx_string.h src/event/ngx_event.h src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h src/event/ngx_event_timer.c src/http/modules/proxy/ngx_http_proxy_cache.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/modules/proxy/ngx_http_proxy_upstream.c src/http/ngx_http_busy_lock.c src/http/ngx_http_busy_lock.h src/http/ngx_http_cache.c
diffstat 14 files changed, 288 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -119,7 +119,7 @@ void ngx_create_hashed_filename(ngx_file
             break;
         }
 
-        ngx_log_debug(file->log, "temp: %s" _ file->name.data);
+        ngx_log_debug(file->log, "hashed path: %s" _ file->name.data);
 
         name -= level;
         file->name.data[pos - 1] = '/';
@@ -127,7 +127,7 @@ void ngx_create_hashed_filename(ngx_file
         pos += level + 1;
     }
 
-    ngx_log_debug(file->log, "temp: %s" _ file->name.data);
+    ngx_log_debug(file->log, "hashed path: %s" _ file->name.data);
 }
 
 
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -69,12 +69,15 @@ int ngx_atoi(char *line, size_t n)
 }
 
 
-void ngx_print_md5(char *text, u_char *md5)
+void ngx_md5_text(char *text, u_char *md5)
 {
-    ngx_snprintf(text, 33, "%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x",
-                 md5[0], md5[1], md5[2], md5[3], md5[4], md5[5],
-                 md5[6], md5[7], md5[8], md5[9], md5[10], md5[11],
-                 md5[12], md5[13], md5[14], md5[15]);
+    /* STUB */
+
+    ngx_snprintf(text, 33,
+            "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+            md5[0], md5[1], md5[2], md5[3], md5[4], md5[5],
+            md5[6], md5[7], md5[8], md5[9], md5[10], md5[11],
+            md5[12], md5[13], md5[14], md5[15]);
 }
 
 
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -61,7 +61,7 @@ char *ngx_cpystrn(char *dst, char *src, 
 int ngx_rstrncmp(char *s1, char *s2, size_t n);
 int ngx_atoi(char *line, size_t n);
 
-void ngx_print_md5(char *text, u_char *md5);
+void ngx_md5_text(char *text, u_char *md5);
 
 
 #define  ngx_qsort                qsort
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -371,7 +371,8 @@ ngx_inline static int ngx_handle_read_ev
 
         if (!rev->active && !rev->ready) {
             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
-                                                                == NGX_ERROR) {
+                                                                  == NGX_ERROR)
+            {
                 return NGX_ERROR;
             }
 
@@ -380,7 +381,8 @@ ngx_inline static int ngx_handle_read_ev
 
         if (rev->active && (rev->ready || close)) {
             if (ngx_del_event(rev, NGX_READ_EVENT, close ? NGX_CLOSE_EVENT : 0)
-                                                                == NGX_ERROR) {
+                                                                  == NGX_ERROR)
+            {
                 return NGX_ERROR;
             }
 
@@ -399,7 +401,8 @@ ngx_inline static int ngx_handle_level_r
     if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
         if (!rev->active && !rev->ready) {
             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
-                                                                == NGX_ERROR) {
+                                                                  == NGX_ERROR)
+            {
                 return NGX_ERROR;
             }
 
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -245,8 +245,10 @@ int ngx_event_pipe_read_upstream(ngx_eve
                 p->upstream_eof = 1;
                 break;
             }
+
         }
 
+        p->read_length += n;
         cl = chain;
 
         while (cl && n > 0) {
@@ -402,6 +404,18 @@ int ngx_event_pipe_write_to_downstream(n
 
         for (cl = p->free; cl; cl = cl->next) {
 
+            if (cl->hunk->type & NGX_HUNK_TEMP_FILE) {
+                if (p->cachable || !p->cyclic_temp_file) {
+                    continue;
+                }
+
+                /* reset p->temp_offset if all hunks had been sent */
+
+                if (cl->hunk->file_last == p->temp_file->offset) {
+                    p->temp_file->offset = 0;
+                }
+            }
+
             /* TODO: free hunk if p->free_bufs && upstream done */
             /* add the free shadow raw hunk to p->free_raw_hunks */
 
@@ -416,6 +430,7 @@ int ngx_event_pipe_write_to_downstream(n
             }
             cl->hunk->shadow = NULL;
 
+#if 0
             if (p->cyclic_temp_file && (cl->hunk->type & NGX_HUNK_TEMP_FILE)) {
 
                 /* reset p->temp_offset if all hunks had been sent */
@@ -424,6 +439,7 @@ int ngx_event_pipe_write_to_downstream(n
                     p->temp_file->offset = 0;
                 }
             }
+#endif
         }
     }
 
@@ -518,11 +534,15 @@ ngx_log_debug(p->log, "size: %d" _ size)
         p->temp_file->offset += h->last - h->pos;
         h->file_last = p->temp_file->offset;
 
+        h->type |= NGX_HUNK_FILE|NGX_HUNK_TEMP_FILE;
+
+#if 0
         if (p->cachable) {
             h->type |= NGX_HUNK_FILE;
         } else {
             h->type |= NGX_HUNK_FILE|NGX_HUNK_TEMP_FILE;
         }
+#endif
 
         ngx_chain_add_link(p->out, p->last_out, cl);
 
--- a/src/event/ngx_event_pipe.h
+++ b/src/event/ngx_event_pipe.h
@@ -54,6 +54,8 @@ struct ngx_event_pipe_s {
 
     size_t             busy_size;
 
+    off_t              read_length;
+
     off_t              max_temp_file_size;
     int                temp_file_write_size;
 
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -173,7 +173,6 @@ void ngx_event_expire_timers(ngx_msec_t 
             delta -= ev->timer_delta;
 
             ngx_del_timer(ev);
-            ev->timer_set = 0;
 
             if (ev->delayed) {
                 ev->delayed = 0;
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -216,6 +216,30 @@ static int ngx_http_proxy_process_cached
 }
 
 
+#if 0
+
+static void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p)
+{
+    rc = ngx_http_busy_lock(p->lcf->busy_lock, p->cache->ctx.md5);
+
+    if (rc == NGX_OK) {
+        ngx_http_proxy_request_upstream(p);
+    }
+
+    if (rc == NGX_AGAIN) {
+        if (p->busy_lock_time) {
+            ngx_add_timer(p->request->connection->read, 1000);
+            return;
+        }
+    }
+
+    rc == NGX_ERROR
+    check waitn
+}
+
+#endif
+
+
 int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
 {
     int                  rc, len, i;
@@ -428,10 +452,21 @@ int ngx_http_proxy_is_cachable(ngx_http_
 
 int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p)
 {
+    ngx_event_pipe_t  *ep;
+
     if (p->cache == NULL) {
         return NGX_OK;
     }
 
+    ep = p->upstream->event_pipe;
+
+    if (p->cache->ctx.length == -1) {
+        /* TODO: test rc */
+        ngx_write_file(&ep->temp_file->file,
+                       (char *) &ep->read_length, sizeof(off_t),
+                       offsetof(ngx_http_cache_header_t, length));
+    }
+
     return ngx_http_cache_update_file(p->request, &p->cache->ctx,
-                               &p->upstream->event_pipe->temp_file->file.name);
+                                      &ep->temp_file->file.name);
 }
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -266,7 +266,9 @@ static int ngx_http_proxy_handler(ngx_ht
     ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
 
 
-    if (!p->lcf->cache) {
+    if (!p->lcf->cache
+        || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD))
+    {
         p->state->cache = NGX_HTTP_PROXY_CACHE_PASS;
 
     } else if (r->bypass_cache) {
@@ -290,16 +292,16 @@ static int ngx_http_proxy_handler(ngx_ht
 
     rc = ngx_http_proxy_get_cached_response(p);
 
+    if (rc == NGX_DONE || rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
+        return rc;
+    }
+
     p->valid_header_in = 1;
 
     if (rc == NGX_OK) {
         return ngx_http_proxy_send_cached_response(p);
     }
 
-    if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
-        return rc;
-    }
-
     /* rc == NGX_DECLINED || NGX_HTTP_CACHE_STALE || NGX_HTTP_CACHE_AGED */
 
     return ngx_http_proxy_request_upstream(p);
@@ -312,8 +314,7 @@ void ngx_http_proxy_finalize_request(ngx
                   "finalize http proxy request");
 
     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 (p->header_sent
@@ -329,8 +330,17 @@ void ngx_http_proxy_finalize_request(ngx
 }
 
 
-void ngx_http_proxy_close_connection(ngx_connection_t *c)
+void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p)
 {
+    ngx_connection_t  *c;
+
+    c = p->upstream->peer.connection;
+    p->upstream->peer.connection = NULL;
+
+    if (p->lcf->busy_lock) {
+        p->lcf->busy_lock->conn_n--;
+    }
+
     ngx_log_debug(c->log, "proxy close connection: %d" _ c->fd);
 
     if (c->fd == -1) {
@@ -505,6 +515,13 @@ static char *ngx_http_proxy_merge_loc_co
 
     if (conf->busy_lock && conf->cache && conf->busy_lock->busy == NULL) {
 
+        /* ngx_alloc_shared() */
+        conf->busy_lock->busy_mask =
+                     ngx_palloc(cf->pool, (conf->busy_lock->max_conn + 7) / 8);
+        if (conf->busy_lock->busy_mask == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
         /* 16 bytes are 128 bits of the md5 */
 
         /* ngx_alloc_shared() */
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -140,6 +140,7 @@ struct ngx_http_proxy_ctx_s {
 
     ngx_hunk_t                   *header_in;
 
+    time_t                        busy_lock_time;
 
     unsigned                      accel:1;
 
@@ -188,7 +189,7 @@ int ngx_http_proxy_update_cache(ngx_http
 
 size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len);
 void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
-void ngx_http_proxy_close_connection(ngx_connection_t *c);
+void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p);
 
 int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
 int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
--- 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);
+    }
 }
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -4,6 +4,61 @@
 #include <ngx_http.h>
 
 
+int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5)
+{
+    int    i, b, busy, free;
+    u_int  mask;
+
+    b = 0;
+    busy = 0;
+    free = -1;
+
+#if (NGX_SUPPRESS_WARN)
+    mask = 0;
+#endif
+
+    for (i = 0; i < bl->max_conn; i++) {
+
+        if ((b & 7) == 0) {
+            mask = bl->busy_mask[i / 8];
+        }
+
+        if (mask & 1) {
+            if (ngx_memcmp(&bl->busy[i * 16], md5, 16) == 0) {
+                return NGX_AGAIN;
+            }
+            busy++;
+
+        } else if (free == -1) {
+            free = i;
+        }
+
+        if (busy == bl->busy_n) {
+            if (busy < bl->max_conn) {
+                free = i + 1;
+            }
+
+            break;
+        }
+
+        mask >>= 1;
+        b++;
+    }
+
+    if (free == -1) {
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(&bl->busy[free * 16], md5, 16);
+    bl->busy_mask[free / 8] |= free % 8;
+
+    bl->busy_n++;
+    bl->conn_n++;
+
+    return NGX_OK;
+}
+
+
 char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
                                   void *conf)
 {
@@ -26,7 +81,7 @@ char *ngx_http_set_busy_lock_slot(ngx_co
 
     value = (ngx_str_t *) cf->args->elts;
 
-    for (i = 1; i < 3; i++) {
+    for (i = 1; i < 4; i++) {
 
         if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "c:", 2) == 0) {
             if (bl->max_conn) {
@@ -68,7 +123,7 @@ char *ngx_http_set_busy_lock_slot(ngx_co
             return NGX_CONF_ERROR;
         }
 
-        bl->timeout = ngx_parse_time(&value[1], 0);
+        bl->timeout = ngx_parse_time(&value[1], 1);
         if (bl->timeout == NGX_ERROR) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "invalid timeout \"%s\"", value[i].data);
--- a/src/http/ngx_http_busy_lock.h
+++ b/src/http/ngx_http_busy_lock.h
@@ -8,22 +8,24 @@
 
 
 typedef struct {
-    char  *busy;
-    int    busy_n;
+    u_char  *busy_mask;
+    char    *busy;
+    int      busy_n;
 
-    int    waiting_n;
-    int    max_waiting;
+    int      waiting_n;
+    int      max_waiting;
 
-    int    conn_n;
-    int    max_conn;
+    int      conn_n;
+    int      max_conn;
 
-    int    timeout;
+    time_t   timeout;
 
  /* ngx_mutex_t  mutex; */
 
 } ngx_http_busy_lock_t;
 
 
+int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5);
 char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
                                   void *conf);
 
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -26,13 +26,8 @@ int ngx_http_cache_get_file(ngx_http_req
     MD5Update(&md5, (u_char *) ctx->key.data, ctx->key.len);
     MD5Final(ctx->md5, &md5);
 
-    ngx_print_md5(
-                 ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len,
+    ngx_md5_text(ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len,
                  ctx->md5);
-#if 0
-    MD5End(&md5,
-           ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
-#endif
 
 ngx_log_debug(r->connection->log, "URL: %s, md5: %s" _ ctx->key.data _
               ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
@@ -90,6 +85,7 @@ ngx_log_debug(r->connection->log, "FILE:
     ctx->buf->last += n;
 
     if (ctx->expires < ngx_time()) {
+ngx_log_debug(r->connection->log, "EXPIRED");
         return NGX_HTTP_CACHE_STALE;
     }