mirror of https://github.com/nginx/nginx
parent
1af7090b50
commit
52859f2f13
@ -1,217 +0,0 @@ |
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev |
||||
*/ |
||||
|
||||
|
||||
#include <ngx_config.h> |
||||
#include <ngx_core.h> |
||||
|
||||
|
||||
|
||||
ngx_int_t ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, ngx_int_t level) |
||||
{ |
||||
int rc; |
||||
u_char *last; |
||||
size_t len; |
||||
ngx_err_t err; |
||||
ngx_str_t fname, buf; |
||||
ngx_dir_t dir; |
||||
|
||||
buf.len = 0; |
||||
#if (NGX_SUPPRESS_WARN) |
||||
buf.data = NULL; |
||||
fname.data = NULL; |
||||
#endif |
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0, |
||||
"gc dir \"%s\":%d", dname->data, dname->len); |
||||
|
||||
if (ngx_open_dir(dname, &dir) == NGX_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_open_dir_n " \"%s\" failed", dname->data); |
||||
return NGX_ERROR; |
||||
} |
||||
|
||||
for ( ;; ) { |
||||
ngx_set_errno(0); |
||||
if (ngx_read_dir(&dir) == NGX_ERROR) { |
||||
err = ngx_errno; |
||||
|
||||
if (err != NGX_ENOMOREFILES) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, err, |
||||
ngx_read_dir_n " \"%s\" failed", dname->data); |
||||
rc = NGX_ERROR; |
||||
|
||||
} else { |
||||
rc = NGX_OK; |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
len = ngx_de_namelen(&dir); |
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0, |
||||
"gc name \"%s\":%d", ngx_de_name(&dir), len); |
||||
|
||||
if (len == 1 && ngx_de_name(&dir)[0] == '.') { |
||||
continue; |
||||
} |
||||
|
||||
if (len == 2 |
||||
&& ngx_de_name(&dir)[0] == '.' |
||||
&& ngx_de_name(&dir)[1] == '.') |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
fname.len = dname->len + 1+ len; |
||||
|
||||
if (fname.len + NGX_DIR_MASK_LEN > buf.len) { |
||||
|
||||
if (buf.len) { |
||||
ngx_free(buf.data); |
||||
} |
||||
|
||||
buf.len = dname->len + 1 + len + NGX_DIR_MASK_LEN; |
||||
|
||||
buf.data = ngx_alloc(buf.len + 1, ctx->log); |
||||
if (buf.data == NULL) { |
||||
return NGX_ABORT; |
||||
} |
||||
} |
||||
|
||||
last = ngx_cpymem(buf.data, dname->data, dname->len); |
||||
*last++ = '/'; |
||||
ngx_memcpy(last, ngx_de_name(&dir), len + 1); |
||||
fname.data = buf.data; |
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, |
||||
"gc path: \"%s\"", fname.data); |
||||
|
||||
if (!dir.valid_info) { |
||||
if (ngx_de_info(fname.data, &dir) == NGX_FILE_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_de_info_n " \"%s\" failed", fname.data); |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
if (ngx_de_is_dir(&dir)) { |
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, |
||||
"gc enter dir \"%s\"", fname.data); |
||||
|
||||
if (level == -1 |
||||
/* there can not be directory on the last level */ |
||||
|| level == NGX_MAX_PATH_LEVEL |
||||
/* an directory from the old path hierarchy */ |
||||
|| len != ctx->path->level[level]) |
||||
{ |
||||
if (ngx_collect_garbage(ctx, &fname, -1) == NGX_ABORT) { |
||||
return NGX_ABORT; |
||||
} |
||||
|
||||
fname.data[fname.len] = '\0'; |
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0, |
||||
"delete old hierachy directory \"%s\"", |
||||
fname.data); |
||||
|
||||
if (ngx_delete_dir(fname.data) == NGX_FILE_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_delete_dir_n " \"%s\" failed", |
||||
fname.data); |
||||
} else { |
||||
ctx->deleted++; |
||||
ctx->freed += ngx_de_size(&dir); |
||||
} |
||||
|
||||
continue; |
||||
} |
||||
|
||||
if (ngx_collect_garbage(ctx, &fname, level + 1) == NGX_ABORT) { |
||||
return NGX_ABORT; |
||||
} |
||||
|
||||
} else if (ngx_de_is_file(&dir)) { |
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, |
||||
"gc file \"%s\"", fname.data); |
||||
|
||||
if (level == -1 |
||||
|| (level < NGX_MAX_PATH_LEVEL && ctx->path->level[level] != 0)) |
||||
{ |
||||
if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_delete_file_n " \"%s\" failed", |
||||
fname.data); |
||||
} else { |
||||
ctx->deleted++; |
||||
ctx->freed += ngx_de_size(&dir); |
||||
} |
||||
|
||||
continue; |
||||
} |
||||
|
||||
if (ctx->handler(ctx, &fname, &dir) == NGX_ABORT) { |
||||
return NGX_ABORT; |
||||
} |
||||
|
||||
} else { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
"the file \"%s\" has unknown type, deleting", |
||||
fname.data); |
||||
|
||||
if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_delete_file_n " \"%s\" failed", fname.data); |
||||
} else { |
||||
ctx->deleted++; |
||||
ctx->freed += ngx_de_size(&dir); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (buf.len) { |
||||
ngx_free(buf.data); |
||||
} |
||||
|
||||
if (ngx_close_dir(&dir) == NGX_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_close_dir_n " \"%s\" failed", fname.data); |
||||
} |
||||
|
||||
return rc; |
||||
} |
||||
|
||||
|
||||
ngx_int_t ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name, |
||||
ngx_dir_t *dir) |
||||
{ |
||||
/*
|
||||
* We use mtime only and do not use atime because: |
||||
* on NTFS access time has a resolution of 1 hour, |
||||
* on NT FAT access time has a resolution of 1 day, |
||||
* Unices have the mount option "noatime". |
||||
*/ |
||||
|
||||
if (ngx_time() - ngx_de_mtime(dir) < 3600) { |
||||
return NGX_OK; |
||||
} |
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0, |
||||
"delete the stale temporary file \"%s\"", name->data); |
||||
|
||||
if (ngx_delete_file(name->data) == NGX_FILE_ERROR) { |
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, |
||||
ngx_delete_file_n " \"%s\" failed", name->data); |
||||
return NGX_ERROR; |
||||
} |
||||
|
||||
ctx->deleted++; |
||||
ctx->freed += ngx_de_size(dir); |
||||
|
||||
return NGX_OK; |
||||
} |
||||
@ -1,31 +0,0 @@ |
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev |
||||
*/ |
||||
|
||||
|
||||
#ifndef _NGX_GARBAGE_COLLECTOR_H_INCLUDED_ |
||||
#define _NGX_GARBAGE_COLLECTOR_H_INCLUDED_ |
||||
|
||||
|
||||
typedef struct ngx_gc_s ngx_gc_t; |
||||
|
||||
typedef ngx_int_t (*ngx_gc_handler_pt) (ngx_gc_t *ctx, ngx_str_t *name, |
||||
ngx_dir_t *dir); |
||||
|
||||
|
||||
struct ngx_gc_s { |
||||
ngx_path_t *path; |
||||
u_int deleted; |
||||
off_t freed; |
||||
ngx_gc_handler_pt handler; |
||||
ngx_log_t *log; |
||||
}; |
||||
|
||||
|
||||
ngx_int_t ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, ngx_int_t level); |
||||
ngx_int_t ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name, |
||||
ngx_dir_t *dir); |
||||
|
||||
|
||||
#endif /* _NGX_GARBAGE_COLLECTOR_H_INCLUDED_ */ |
||||
@ -1,576 +0,0 @@ |
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev |
||||
*/ |
||||
|
||||
|
||||
#include <ngx_config.h> |
||||
#include <ngx_core.h> |
||||
#include <ngx_http.h> |
||||
|
||||
|
||||
#if 0 |
||||
|
||||
static ngx_http_module_t ngx_http_cache_module_ctx = { |
||||
NULL, /* pre conf */ |
||||
|
||||
NULL, /* create main configuration */ |
||||
NULL, /* init main configuration */ |
||||
|
||||
NULL, /* create server configuration */ |
||||
NULL, /* merge server configuration */ |
||||
|
||||
NULL, /* create location configuration */ |
||||
NULL /* merge location configuration */ |
||||
}; |
||||
|
||||
|
||||
ngx_module_t ngx_http_cache_module = { |
||||
NGX_MODULE, |
||||
&ngx_http_cache_module_ctx, /* module context */ |
||||
NULL, /* module directives */ |
||||
NGX_HTTP_MODULE, /* module type */ |
||||
NULL, /* init module */ |
||||
NULL /* init process */ |
||||
}; |
||||
|
||||
#endif |
||||
|
||||
|
||||
static ngx_int_t ngx_http_cache_create(ngx_http_request_t *r) |
||||
{ |
||||
ngx_str_t *key; |
||||
|
||||
if (!(r->cache = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t)))) { |
||||
return NGX_ERROR; |
||||
} |
||||
|
||||
if (ngx_array_init(&r->cache->key, r->pool, 5, sizeof(ngx_str_t)) |
||||
== NGX_ERROR) |
||||
{ |
||||
return NGX_ERROR; |
||||
} |
||||
|
||||
/* preallocate the primary key */ |
||||
|
||||
if (!(key = ngx_array_push(&r->cache->key))) { |
||||
return NGX_ERROR; |
||||
} |
||||
|
||||
key->len = 0; |
||||
key->data = NULL; |
||||
|
||||
/*
|
||||
* we use offsetof() because sizeof() pads the struct size to the int size |
||||
*/ |
||||
|
||||
r->cache->header_size = offsetof(ngx_http_cache_header_t, key); |
||||
|
||||
r->cache->log = r->connection->log; |
||||
r->cache->file.log = r->connection->log; |
||||
|
||||
return NGX_OK; |
||||
} |
||||
|
||||
|
||||
ngx_int_t ngx_http_cache_get(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) |
||||
{ |
||||
ngx_str_t *key; |
||||
ngx_http_cache_t *c; |
||||
|
||||
if (r->cache == NULL) { |
||||
if (ngx_http_cache_create(r) == NGX_ERROR) { |
||||
return NGX_ABORT; |
||||
} |
||||
} |
||||
|
||||
c = r->cache; |
||||
key = c->key.elts; |
||||
|
||||
if (ctx->primary) { |
||||
key[0] = ctx->key; |
||||
c->header_size += ctx->key.len; |
||||
c->key_len += ctx->key.len; |
||||
c->buf = ctx->buf; |
||||
|
||||
} else { |
||||
if (key[0].len == 0) { |
||||
key[0] = r->uri; |
||||
c->header_size += r->uri.len; |
||||
c->key_len += ctx->key.len; |
||||
} |
||||
|
||||
if (!(key = ngx_array_push(&r->cache->key))) { |
||||
return NGX_ABORT; |
||||
} |
||||
|
||||
c->header_size += ctx->key.len; |
||||
c->key_len += ctx->key.len; |
||||
} |
||||
|
||||
#if 0 |
||||
|
||||
if (ctx->memory) { |
||||
ngx_http_memory_cache_get(r, ctx); |
||||
} |
||||
|
||||
#endif |
||||
|
||||
if (ctx->file) { |
||||
return ngx_http_file_cache_get(r, ctx); |
||||
} |
||||
|
||||
return NGX_DECLINED; |
||||
} |
||||
|
||||
|
||||
#if 0 |
||||
|
||||
|
||||
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; |
||||
|
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { |
||||
return (void *) NGX_ERROR; |
||||
} |
||||
|
||||
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) |
||||
{ |
||||
#if 0 |
||||
if (c[i].expired) { |
||||
ngx_mutex_unlock(&hash->mutex); |
||||
return (void *) NGX_AGAIN; |
||||
} |
||||
#endif |
||||
|
||||
c[i].refs++; |
||||
|
||||
if ((!(c[i].notify && (ngx_event_flags & NGX_USE_KQUEUE_EVENT))) |
||||
&& (ngx_cached_time - c[i].updated >= hash->update)) |
||||
{ |
||||
c[i].expired = 1; |
||||
} |
||||
|
||||
ngx_mutex_unlock(&hash->mutex); |
||||
|
||||
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; |
||||
|
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { |
||||
return (void *) NGX_ERROR; |
||||
} |
||||
|
||||
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->deleted = 0; |
||||
cache->expired = 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_lock(ngx_http_cache_hash_t *hash, ngx_http_cache_t *cache) |
||||
{ |
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { |
||||
return; |
||||
} |
||||
} |
||||
|
||||
|
||||
void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash, |
||||
ngx_http_cache_t *cache, ngx_log_t *log) |
||||
{ |
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { |
||||
return; |
||||
} |
||||
|
||||
cache->refs--; |
||||
|
||||
if (cache->refs == 0 && cache->deleted) { |
||||
ngx_http_cache_free(cache, NULL, NULL, log); |
||||
} |
||||
|
||||
ngx_mutex_unlock(&hash->mutex); |
||||
} |
||||
|
||||
|
||||
#if 0 |
||||
|
||||
ngx_http_cache_add_file_event(ngx_http_cache_hash_t *hash, |
||||
ngx_http_cache_t *cache) |
||||
{ |
||||
ngx_event_t *ev; |
||||
ngx_http_cache_event_ctx_t *ctx; |
||||
|
||||
ev = &ngx_cycle->read_events[fd]; |
||||
ngx_memzero(ev, sizeof(ngx_event_t); |
||||
|
||||
ev->data = data; |
||||
ev->event_handler = ngx_http_cache_invalidate; |
||||
|
||||
return ngx_add_event(ev, NGX_VNODE_EVENT, 0); |
||||
} |
||||
|
||||
|
||||
void ngx_http_cache_invalidate(ngx_event_t *ev) |
||||
{ |
||||
ngx_http_cache_event_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 |
||||
|
||||
|
||||
/* 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 = r->cache->data.size; |
||||
|
||||
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); |
||||
} |
||||
|
||||
|
||||
char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
||||
{ |
||||
char *p = conf; |
||||
|
||||
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); |
||||
if (*chp) { |
||||
return "is duplicate"; |
||||
} |
||||
|
||||
if (!(ch = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_hash_t)))) { |
||||
return NGX_CONF_ERROR; |
||||
} |
||||
*chp = ch; |
||||
|
||||
dup = 0; |
||||
invalid = 0; |
||||
|
||||
value = cf->args->elts; |
||||
|
||||
for (i = 1; i < cf->args->nelts; i++) { |
||||
|
||||
if (value[i].data[1] != '=') { |
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
||||
"invalid value \"%s\"", value[i].data); |
||||
return NGX_CONF_ERROR; |
||||
} |
||||
|
||||
switch (value[i].data[0]) { |
||||
|
||||
case 'h': |
||||
if (ch->hash) { |
||||
dup = 1; |
||||
break; |
||||
} |
||||
|
||||
ch->hash = ngx_atoi(value[i].data + 2, value[i].len - 2); |
||||
if (ch->hash == (size_t) NGX_ERROR || ch->hash == 0) { |
||||
invalid = 1; |
||||
break; |
||||
} |
||||
|
||||
continue; |
||||
|
||||
case 'n': |
||||
if (ch->nelts) { |
||||
dup = 1; |
||||
break; |
||||
} |
||||
|
||||
ch->nelts = ngx_atoi(value[i].data + 2, value[i].len - 2); |
||||
if (ch->nelts == (size_t) NGX_ERROR || ch->nelts == 0) { |
||||
invalid = 1; |
||||
break; |
||||
} |
||||
|
||||
continue; |
||||
|
||||
case 'l': |
||||
if (ch->life) { |
||||
dup = 1; |
||||
break; |
||||
} |
||||
|
||||
line.len = value[i].len - 2; |
||||
line.data = value[i].data + 2; |
||||
|
||||
ch->life = ngx_parse_time(&line, 1); |
||||
if (ch->life == NGX_ERROR || ch->life == 0) { |
||||
invalid = 1; |
||||
break; |
||||
} |
||||
|
||||
continue; |
||||
|
||||
case 'u': |
||||
if (ch->update) { |
||||
dup = 1; |
||||
break; |
||||
} |
||||
|
||||
line.len = value[i].len - 2; |
||||
line.data = value[i].data + 2; |
||||
|
||||
ch->update = ngx_parse_time(&line, 1); |
||||
if (ch->update == NGX_ERROR || ch->update == 0) { |
||||
invalid = 1; |
||||
break; |
||||
} |
||||
|
||||
continue; |
||||
|
||||
default: |
||||
invalid = 1; |
||||
} |
||||
|
||||
if (dup) { |
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
||||
"duplicate value \"%s\"", value[i].data); |
||||
return NGX_CONF_ERROR; |
||||
} |
||||
|
||||
if (invalid) { |
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
||||
"invalid value \"%s\"", value[i].data); |
||||
return NGX_CONF_ERROR; |
||||
} |
||||
} |
||||
|
||||
ch->elts = ngx_pcalloc(cf->pool, |
||||
ch->hash * ch->nelts * sizeof(ngx_http_cache_t)); |
||||
if (ch->elts == NULL) { |
||||
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; |
||||
} |
||||
|
||||
|
||||
#endif |
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue