diff src/http/ngx_http_cache.c @ 201:267ea1d98683

nginx-0.0.1-2003-11-30-23:03:18 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 30 Nov 2003 20:03:18 +0000
parents abeaebe0a33c
children 74994aeef848
line wrap: on
line diff
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -13,13 +13,6 @@
 #endif
 
 
-static int ngx_crc(char *data, size_t len);
-
-static void *ngx_http_cache_create_conf(ngx_conf_t *cf);
-static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
-                                          void *parent, void *child);
-
-
 static ngx_http_module_t  ngx_http_cache_module_ctx = {
     NULL,                                  /* pre conf */
 
@@ -29,8 +22,8 @@ static ngx_http_module_t  ngx_http_cache
     NULL,                                  /* create server configuration */
     NULL,                                  /* merge server configuration */
 
-    ngx_http_cache_create_conf,            /* create location configuration */
-    ngx_http_core_merge_loc_conf           /* merge location configuration */
+    NULL,                                  /* create location configuration */
+    NULL                                   /* merge location configuration */
 };
 
 
@@ -44,6 +37,248 @@ ngx_module_t  ngx_http_cache_module = {
 };
 
 
+ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *hash,
+                                     ngx_http_cleanup_t *cleanup,
+                                     ngx_str_t *key, uint32_t *crc)
+{
+    ngx_uint_t         i;
+    ngx_http_cache_t  *c;
+
+    *crc = ngx_crc(key->data, key->len);
+
+    c = hash->elts + *crc % hash->hash * hash->nelts;
+
+    ngx_mutex_lock(&hash->mutex);
+
+    for (i = 0; i < hash->nelts; i++) {
+        if (c[i].crc == *crc
+            && c[i].key.len == key->len
+            && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0)
+        {
+            c[i].refs++;
+            ngx_mutex_unlock(&hash->mutex);
+
+            if (c[i].notify) {
+                if (!(ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)) {
+                    c[i].valid = 0;
+                }
+
+            } else if (ngx_cached_time - c[i].updated >= hash->update) {
+                c[i].valid = 0;
+            }
+
+            if (cleanup) {
+                cleanup->data.cache.hash = hash;
+                cleanup->data.cache.cache = &c[i];
+                cleanup->valid = 1;
+                cleanup->cache = 1;
+            }
+
+            return &c[i];
+        }
+    }
+
+    ngx_mutex_unlock(&hash->mutex);
+
+    return NULL;
+}
+
+
+ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *hash,
+                                       ngx_http_cache_t *cache,
+                                       ngx_http_cleanup_t *cleanup,
+                                       ngx_str_t *key, uint32_t crc,
+                                       ngx_str_t *value, ngx_log_t *log)
+{
+    time_t             old;
+    ngx_uint_t         i;
+    ngx_http_cache_t  *c;
+
+    old = ngx_cached_time + 1;
+
+    c = hash->elts + crc % hash->hash * hash->nelts;
+
+    ngx_mutex_lock(&hash->mutex);
+
+    if (cache == NULL) {
+
+        /* allocate a new entry */
+
+        for (i = 0; i < hash->nelts; i++) {
+            if (c[i].refs > 0) {
+                /* a busy entry */
+                continue;
+            }
+
+            if (c[i].key.len == 0) {
+                /* a free entry is found */
+                cache = &c[i];
+                break;
+            }
+
+            /* looking for the oldest cache entry */
+
+            if (old > c[i].accessed) {
+
+                old = c[i].accessed;
+                cache = &c[i];
+            }
+        }
+
+        if (cache == NULL) {
+            ngx_mutex_unlock(&hash->mutex);
+            return NULL;
+        }
+
+        ngx_http_cache_free(cache, key, value, log);
+
+        if (cache->key.data == NULL) {
+            cache->key.data = ngx_alloc(key->len, log);
+            if (cache->key.data == NULL) {
+                ngx_http_cache_free(cache, NULL, NULL, log);
+                ngx_mutex_unlock(&hash->mutex);
+                return NULL;
+            }
+        }
+
+        cache->key.len = key->len;
+        ngx_memcpy(cache->key.data, key->data, key->len);
+
+    } else if (value) {
+        ngx_http_cache_free(cache, key, value, log);
+    }
+
+    if (value) {
+        if (cache->data.value.data == NULL) {
+            cache->data.value.data = ngx_alloc(value->len, log);
+            if (cache->data.value.data == NULL) {
+                ngx_http_cache_free(cache, NULL, NULL, log);
+                ngx_mutex_unlock(&hash->mutex);
+                return NULL;
+            }
+        }
+
+        cache->data.value.len = value->len;
+        ngx_memcpy(cache->data.value.data, value->data, value->len);
+    }
+
+    cache->crc = crc;
+    cache->key.len = key->len;
+
+    cache->refs = 1;
+    cache->count = 0;
+
+    cache->valid = 1;
+    cache->deleted = 0;
+    cache->memory = 0;
+    cache->mmap = 0;
+    cache->notify = 0;
+
+    if (cleanup) {
+        cleanup->data.cache.hash = hash;
+        cleanup->data.cache.cache = cache;
+        cleanup->valid = 1;
+        cleanup->cache = 1;
+    }
+
+    ngx_mutex_unlock(&hash->mutex);
+
+    return cache;
+}
+
+
+void ngx_http_cache_free(ngx_http_cache_t *cache,
+                         ngx_str_t *key, ngx_str_t *value, ngx_log_t *log)
+{
+    if (cache->memory) {
+        if (cache->data.value.data
+            && (value == NULL || value->len > cache->data.value.len))
+        {
+            ngx_free(cache->data.value.data);
+            cache->data.value.data = NULL;
+        }
+    }
+
+    /* TODO: mmap */
+
+    cache->data.value.len = 0;
+
+    if (cache->fd != NGX_INVALID_FILE) {
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                       "http cache close fd: %d", cache->fd);
+
+        if (ngx_close_file(cache->fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                          ngx_close_file_n " \"%s\" failed",
+                          cache->key.data);
+        }
+
+        cache->fd = NGX_INVALID_FILE;
+    }
+
+    if (cache->key.data && (key == NULL || key->len > cache->key.len)) {
+        ngx_free(cache->key.data);
+        cache->key.data = NULL;
+    }
+
+    cache->key.len = 0;
+
+    cache->refs = 0;
+}
+
+
+void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash,
+                           ngx_http_cache_t *cache, ngx_log_t *log)
+{
+    ngx_mutex_lock(&hash->mutex);
+
+    cache->refs--;
+
+    if (cache->refs == 0 && cache->deleted) {
+        ngx_http_cache_free(cache, NULL, NULL, log);
+    }
+
+    ngx_mutex_unlock(&hash->mutex);
+}
+
+
+#if 0
+
+ngx_add_file_event(ngx_fd_t, ngx_event_handler_pt *handler, void *data)
+{
+    ngx_event_t  *ev;
+
+    ev = &ngx_cycle->read_events[fd];
+    ngx_memzero(ev, sizeof(ngx_event_t);
+
+    ev->data = data;
+    ev->event_handler = handler;
+
+    return ngx_add_event(ev, NGX_VNODE_EVENT, 0);
+}
+
+
+void ngx_http_cache_invalidate(ngx_event_t *ev)
+{
+    ngx_http_cache_ctx_t  *ctx;
+
+    ctx = ev->data;
+
+    ngx_http_cache_lock(&ctx->hash->mutex);
+
+    if (ctx->cache->refs == 0)
+        ngx_http_cache_free(ctx->cache, NULL, NULL, ctx->log);
+
+    } else {
+        ctx->cache->deleted = 1;
+    }
+
+    ngx_http_cache_unlock(&ctx->hash->mutex);
+}
+
+#endif
+
 
 int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx)
 {
@@ -80,125 +315,6 @@ ngx_log_debug(r->connection->log, "FILE:
 }
 
 
-ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache,
-                                     ngx_str_t *key, uint32_t *crc)
-{
-    ngx_uint_t         i;
-    ngx_http_cache_t  *c;
-
-    *crc = ngx_crc(key->data, key->len);
-
-    c = cache->elts + *crc % cache->hash * cache->nelts;
-
-    ngx_mutex_lock(&cache->mutex);
-
-    for (i = 0; i < cache->nelts; i++) {
-        if (c[i].crc == *crc
-            && c[i].key.len == key->len
-            && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0)
-        {
-            c[i].refs++;
-            ngx_mutex_unlock(&cache->mutex);
-            return &c[i];
-        }
-    }
-
-    ngx_mutex_unlock(&cache->mutex);
-
-    return NULL;
-}
-
-
-ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *cache,
-                                       ngx_str_t *key, uint32_t crc,
-                                       ngx_log_t *log)
-{
-    time_t             old;
-    ngx_uint_t         i;
-    ngx_http_cache_t  *c, *found;
-
-    old = ngx_cached_time + 1;
-    found = NULL;
-
-    c = cache->elts + crc % cache->hash * cache->nelts;
-
-    ngx_mutex_lock(&cache->mutex);
-
-    for (i = 0; i < cache->nelts; i++) {
-        if (c[i].refs > 0) {
-            /* a busy entry */
-            continue;
-        }
-
-        if (c[i].key.data == NULL) {
-            /* a free entry is found */
-            found = &c[i];
-            break;
-        }
-
-        /* looking for the oldest cache entry */
-
-        if (old > c[i].accessed) {
-
-            old = c[i].accessed;
-            found = &c[i];
-        }
-    }
-
-    if (found) {
-        if (found->key.data) {
-            if (key->len > found->key.len) {
-                ngx_free(found->key.data);
-                found->key.data = NULL;
-            }
-        }
-
-        if (found->key.data == NULL) {
-            found->key.data = ngx_alloc(key->len, log);
-            if (found->key.data == NULL) {
-                ngx_mutex_unlock(&cache->mutex);
-                return NULL;
-            }
-        }
-
-        ngx_memcpy(found->key.data, key->data, key->len);
-
-        found->crc = crc;
-        found->key.len = key->len;
-        found->refs = 1;
-        found->count = 0;
-        found->deleted = 0;
-    }
-
-    ngx_mutex_unlock(&cache->mutex);
-
-    return found;
-}
-
-
-void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash,
-                           ngx_http_cache_t *cache, ngx_log_t *log)
-{
-    ngx_mutex_lock(&hash->mutex);
-
-    cache->refs--;
-
-    if (cache->refs == 0 && cache->deleted) {
-ngx_log_debug(log, "CLOSE FILE: %d" _ cache->fd);
-        if (cache->fd != NGX_INVALID_FILE) {
-            if (ngx_close_file(cache->fd) == NGX_FILE_ERROR) {
-                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                              ngx_close_file_n " \"%s\" failed",
-                              cache->key.data);
-            }
-        }
-        cache->key.data = NULL;
-    }
-
-    ngx_mutex_unlock(&hash->mutex);
-}
-
-
 int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq)
 {
     ssize_t                   n;
@@ -331,6 +447,57 @@ int ngx_http_cache_update_file(ngx_http_
 }
 
 
+/* TODO: currently fd only */
+
+ngx_int_t ngx_http_send_cached(ngx_http_request_t *r)
+{
+    ngx_int_t            rc;
+    ngx_hunk_t          *h;
+    ngx_chain_t          out;
+    ngx_http_log_ctx_t  *ctx;
+
+    ctx = r->connection->log->data;
+    ctx->action = "sending response to client";
+
+    r->headers_out.status = NGX_HTTP_OK;
+    r->headers_out.content_length_n = r->cache->data.size;
+    r->headers_out.last_modified_time = r->cache->last_modified;
+
+    if (ngx_http_set_content_type(r) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    /* we need to allocate all before the header would be sent */
+
+    if (!(h = ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)))) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    if (!(h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    rc = ngx_http_send_header(r);
+
+    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+        return rc;
+    }
+
+    h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
+
+    h->file_pos = 0;
+    h->file_last = ngx_file_size(&r->file.info);
+
+    h->file->fd = r->cache->fd;
+    h->file->log = r->connection->log;
+
+    out.hunk = h;
+    out.next = NULL;
+
+    return ngx_http_output_filter(r, &out);
+}
+
+
 int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name,
                                              ngx_dir_t *dir)
 {
@@ -375,85 +542,13 @@ int ngx_garbage_collector_http_cache_han
 }
 
 
-/* 32-bit crc16 */
-
-static int ngx_crc(char *data, size_t len)
-{
-    uint32_t  sum;
-
-    for (sum = 0; len; len--) {
-        /*
-         * gcc 2.95.2 x86 and icc 7.1.006 compile that operator
-         *                                into the single rol opcode.
-         * msvc 6.0sp2 compiles it into four opcodes.
-         */
-        sum = sum >> 1 | sum << 31;
-
-        sum += *data++;
-    }
-
-    return sum;
-}
-
-
-static void *ngx_http_cache_create_conf(ngx_conf_t *cf)
-{
-    ngx_http_cache_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    return conf;
-}
-
-
-static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
-                                          void *parent, void *child)
-{
-    ngx_http_cache_conf_t *prev = parent;
-    ngx_http_cache_conf_t *conf = child;
-
-    if (conf->open_files == NULL) {
-        conf->open_files = prev->open_files;
-    }
-
-#if 0
-    if (conf->open_files == NULL) {
-        if (prev->open_files) {
-            conf->open_files = prev->open_files;
-
-        } else {
-            conf->open_files = ngx_pcalloc(cf->pool,
-                                           sizeof(ngx_http_cache_hash_t));
-            if (conf->open_files == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            conf->open_files->hash = NGX_HTTP_CACHE_HASH;
-            conf->open_files->nelts = NGX_HTTP_CACHE_NELTS;
-
-            conf->open_files->elts = ngx_pcalloc(cf->pool,
-                                                 NGX_HTTP_CACHE_HASH
-                                                 * NGX_HTTP_CACHE_NELTS
-                                                 * sizeof(ngx_http_cache_t));
-            if (conf->open_files->elts == NULL) {
-                return NGX_CONF_ERROR;
-            }
-        }
-    }
-#endif
-
-    return NGX_CONF_OK;
-}
-
-
 char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char  *p = conf;
 
-    ngx_int_t              i, dup, invalid;
+    ngx_int_t              i, j, dup, invalid;
     ngx_str_t              *value, line;
+    ngx_http_cache_t       *c;
     ngx_http_cache_hash_t  *ch, **chp;
 
     chp = (ngx_http_cache_hash_t **) (p + cmd->offset);
@@ -566,5 +661,13 @@ char *ngx_http_set_cache_slot(ngx_conf_t
         return NGX_CONF_ERROR;
     }
 
+    for (i = 0; i < (ngx_int_t) ch->hash; i++) {
+        c = ch->elts + i * ch->nelts;
+
+        for (j = 0; j < (ngx_int_t) ch->nelts; j++) {
+            c[j].fd = NGX_INVALID_FILE;
+        }
+    }
+
     return NGX_CONF_OK;
 }