nginx-0.0.1-2003-11-05-20:03:41 import
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c
index e8e3b52..0bc7c61 100644
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -216,6 +216,30 @@
}
+#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_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);
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 860ba7a..a284956 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -266,7 +266,9 @@
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 @@
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 @@
"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_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 @@
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() */
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 6e4b084..919a0af 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -140,6 +140,7 @@
ngx_hunk_t *header_in;
+ time_t busy_lock_time;
unsigned accel:1;
@@ -188,7 +189,7 @@
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,
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index cee93ee..c66c164 100644
--- 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 @@
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_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 @@
}
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 @@
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 @@
}
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_http_proxy_connect(p);
+ if (p->lcf->busy_lock) {
+ ngx_http_proxy_upstream_busy_lock(p);
+ } else {
+ ngx_http_proxy_connect(p);
+ }
}
diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c
index 8ebedfb..9431a38 100644
--- 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 @@
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 @@
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);
diff --git a/src/http/ngx_http_busy_lock.h b/src/http/ngx_http_busy_lock.h
index 40aa3d2..1ee95c9 100644
--- 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);
diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c
index ffe7ad5..6ae779a 100644
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -26,13 +26,8 @@
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 @@
ctx->buf->last += n;
if (ctx->expires < ngx_time()) {
+ngx_log_debug(r->connection->log, "EXPIRED");
return NGX_HTTP_CACHE_STALE;
}