Mercurial > hg > nginx-ranges
view src/http/ngx_http_file_cache.c @ 196:8759b346e431 NGINX_0_3_45
nginx 0.3.45
*) Feature: the "ssl_verify_client", "ssl_verify_depth", and
"ssl_client_certificate" directives.
*) Change: the $request_method variable now returns the main request
method.
*) Change: the ° symbol codes were changed in koi-win conversion
table.
*) Feature: the euro и N symbols were added to koi-win conversion table.
*) Bugfix: if nginx distributed the requests among several backends and
some backend failed, then requests intended for this backend was
directed to one live backend only instead of being distributed among
the rest.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Sat, 06 May 2006 00:00:00 +0400 |
parents | 13710a1813ad |
children | c8cfb6c462ef |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> #if (NGX_HAVE_OPENSSL_MD5_H) #include <openssl/md5.h> #else #include <md5.h> #endif #if (NGX_OPENSSL_MD5) #define MD5Init MD5_Init #define MD5Update MD5_Update #define MD5Final MD5_Final #endif ngx_int_t ngx_http_file_cache_get(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) { ngx_uint_t i; ngx_str_t *key; ngx_http_cache_t *c; MD5_CTX md5; c = r->cache; c->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32; if (!(c->file.name.data = ngx_palloc(r->pool, c->file.name.len + 1))) { return NGX_ABORT; } MD5Init(&md5); key = c->key.elts; for (i = 0; i < c->key.nelts; i++) { MD5Update(&md5, key[i].data, key[i].len); } MD5Update(&md5, ctx->key.data, ctx->key.len); MD5Final(c->md5, &md5); ngx_memcpy(c->file.name.data, ctx->path->name.data, ctx->path->name.len); ngx_md5_text(c->file.name.data + ctx->path->name.len + 1 + ctx->path->len, c->md5); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "file cache key: %V, md5: %s", &ctx->key, c->file.name.data + ctx->path->name.len + 1 + ctx->path->len); ngx_create_hashed_filename(&c->file, ctx->path); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "file cache name: %s", c->file.name.data); return ngx_http_file_cache_open(r->cache); } ngx_int_t ngx_http_file_cache_open(ngx_http_cache_t *c) { ssize_t n; ngx_err_t err; ngx_http_cache_header_t *h; c->file.fd = ngx_open_file(c->file.name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); if (c->file.fd == NGX_INVALID_FILE) { err = ngx_errno; if (err == NGX_ENOENT || err == NGX_ENOTDIR) { return NGX_DECLINED; } ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno, ngx_open_file_n " \"%s\" failed", c->file.name.data); return NGX_ERROR; } if (c->uniq) { if (ngx_fd_info(c->file.fd, &c->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", c->file.name.data); return NGX_ERROR; } if (ngx_file_uniq(&c->file.info) == c->uniq) { if (ngx_close_file(c->file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, ngx_close_file_n " \"%s\" failed", c->file.name.data); } return NGX_HTTP_CACHE_THE_SAME; } } n = ngx_read_file(&c->file, c->buf->pos, c->buf->end - c->buf->last, 0); if (n == NGX_ERROR || n == NGX_AGAIN) { return n; } if (n <= c->header_size) { ngx_log_error(NGX_LOG_CRIT, c->log, 0, "cache file \"%s\" is too small", c->file.name.data); return NGX_ERROR; } h = (ngx_http_cache_header_t *) c->buf->pos; c->expires = h->expires; c->last_modified= h->last_modified; c->date = h->date; c->length = h->length; if (h->key_len > (size_t) (c->buf->end - c->buf->pos)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "cache file \"%s\" is probably invalid", c->file.name.data); return NGX_DECLINED; } #if 0 /* TODO */ if (c->key_len && h->key_len != c->key_len) { ngx_strncmp(h->key, c->key_data, h->key_len) != 0)) h->key[h->key_len] = '\0'; ngx_log_error(NGX_LOG_ALERT, c->log, 0, "md5 collision: \"%s\" and \"%s\"", h->key, c->key.data); return NGX_DECLINED; } #endif c->buf->last += n; if (c->expires < ngx_time()) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http file cache expired"); return NGX_HTTP_CACHE_STALE; } /* TODO: NGX_HTTP_CACHE_AGED */ /* STUB */ return NGX_DECLINED; return NGX_OK; } #if 0 int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx, ngx_str_t *temp_file) { int retry; ngx_err_t err; retry = 0; for ( ;; ) { if (ngx_rename_file(temp_file->data, ctx->file.name.data) == NGX_OK) { return NGX_OK; } err = ngx_errno; #if (NGX_WIN32) if (err == NGX_EEXIST) { if (ngx_win32_rename_file(temp_file, &ctx->file.name, r->pool) == NGX_ERROR) { return NGX_ERROR; } } #endif if (retry || (err != NGX_ENOENT && err != NGX_ENOTDIR)) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_rename_file_n "(\"%s\", \"%s\") failed", temp_file->data, ctx->file.name.data); return NGX_ERROR; } if (ngx_create_path(&ctx->file, ctx->path) == NGX_ERROR) { return NGX_ERROR; } retry = 1; } } #endif ngx_int_t ngx_http_cache_cleaner_handler(ngx_gc_t *gc, ngx_str_t *name, ngx_dir_t *dir) { int rc; ngx_buf_t buf; ngx_http_cache_t c; u_char data[sizeof(ngx_http_cache_header_t)]; ngx_memzero(&c, sizeof(ngx_http_cache_t)); c.file.fd = NGX_INVALID_FILE; c.file.name = *name; c.file.log = gc->log; c.header_size = sizeof(ngx_http_cache_header_t); c.buf = &buf; c.log = gc->log; c.key_len = 0; buf.memory = 1; buf.temporary = 1; buf.pos = data; buf.last = data; buf.start = data; buf.end = data + sizeof(ngx_http_cache_header_t); rc = ngx_http_file_cache_open(&c); /* TODO: NGX_AGAIN */ if (rc != NGX_ERROR&& rc != NGX_DECLINED && rc != NGX_HTTP_CACHE_STALE) { return NGX_OK; } if (ngx_delete_file(name->data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, c.log, ngx_errno, ngx_delete_file_n " \"%s\" failed", name->data); return NGX_ERROR; } gc->deleted++; gc->freed += ngx_de_size(dir); return NGX_OK; }