comparison src/http/ngx_http_cache.c @ 202:74994aeef848

nginx-0.0.1-2003-12-01-19:28:14 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 01 Dec 2003 16:28:14 +0000
parents 267ea1d98683
children c9da5900c79e
comparison
equal deleted inserted replaced
201:267ea1d98683 202:74994aeef848
1 1
2 #include <ngx_config.h> 2 #include <ngx_config.h>
3 #include <ngx_core.h> 3 #include <ngx_core.h>
4 #include <ngx_http.h> 4 #include <ngx_http.h>
5 5
6
7 #include <md5.h>
8
9 #if (HAVE_OPENSSL_MD5)
10 #define MD5Init MD5_Init
11 #define MD5Update MD5_Update
12 #define MD5Final MD5_Final
13 #endif
14 6
15 7
16 static ngx_http_module_t ngx_http_cache_module_ctx = { 8 static ngx_http_module_t ngx_http_cache_module_ctx = {
17 NULL, /* pre conf */ 9 NULL, /* pre conf */
18 10
56 && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0) 48 && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0)
57 { 49 {
58 c[i].refs++; 50 c[i].refs++;
59 ngx_mutex_unlock(&hash->mutex); 51 ngx_mutex_unlock(&hash->mutex);
60 52
61 if (c[i].notify) { 53 if ((!(c[i].notify && (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)))
62 if (!(ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)) { 54 && (ngx_cached_time - c[i].updated >= hash->update))
63 c[i].valid = 0; 55 {
64 } 56 c[i].expired = 1;
65
66 } else if (ngx_cached_time - c[i].updated >= hash->update) {
67 c[i].valid = 0;
68 } 57 }
69 58
70 if (cleanup) { 59 if (cleanup) {
71 cleanup->data.cache.hash = hash; 60 cleanup->data.cache.hash = hash;
72 cleanup->data.cache.cache = &c[i]; 61 cleanup->data.cache.cache = &c[i];
166 cache->key.len = key->len; 155 cache->key.len = key->len;
167 156
168 cache->refs = 1; 157 cache->refs = 1;
169 cache->count = 0; 158 cache->count = 0;
170 159
171 cache->valid = 1;
172 cache->deleted = 0; 160 cache->deleted = 0;
161 cache->expired = 0;
173 cache->memory = 0; 162 cache->memory = 0;
174 cache->mmap = 0; 163 cache->mmap = 0;
175 cache->notify = 0; 164 cache->notify = 0;
176 165
177 if (cleanup) { 166 if (cleanup) {
251 240
252 ev = &ngx_cycle->read_events[fd]; 241 ev = &ngx_cycle->read_events[fd];
253 ngx_memzero(ev, sizeof(ngx_event_t); 242 ngx_memzero(ev, sizeof(ngx_event_t);
254 243
255 ev->data = data; 244 ev->data = data;
256 ev->event_handler = handler; 245 ev->event_handler = ngx_http_cache_invalidate;
257 246
258 return ngx_add_event(ev, NGX_VNODE_EVENT, 0); 247 return ngx_add_event(ev, NGX_VNODE_EVENT, 0);
259 } 248 }
260 249
261 250
276 265
277 ngx_http_cache_unlock(&ctx->hash->mutex); 266 ngx_http_cache_unlock(&ctx->hash->mutex);
278 } 267 }
279 268
280 #endif 269 #endif
281
282
283 int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx)
284 {
285 MD5_CTX md5;
286
287 /* we use offsetof() because sizeof() pads struct size to int size */
288 ctx->header_size = offsetof(ngx_http_cache_header_t, key)
289 + ctx->key.len + 1;
290
291 ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32;
292 if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) {
293 return NGX_ERROR;
294 }
295
296 ngx_memcpy(ctx->file.name.data, ctx->path->name.data, ctx->path->name.len);
297
298 MD5Init(&md5);
299 MD5Update(&md5, (u_char *) ctx->key.data, ctx->key.len);
300 MD5Final(ctx->md5, &md5);
301
302 ngx_md5_text(ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len,
303 ctx->md5);
304
305 ngx_log_debug(r->connection->log, "URL: %s, md5: %s" _ ctx->key.data _
306 ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
307
308 ngx_create_hashed_filename(&ctx->file, ctx->path);
309
310 ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data);
311
312 /* TODO: look open files cache */
313
314 return ngx_http_cache_open_file(ctx, 0);
315 }
316
317
318 int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq)
319 {
320 ssize_t n;
321 ngx_err_t err;
322 ngx_http_cache_header_t *h;
323
324 ctx->file.fd = ngx_open_file(ctx->file.name.data,
325 NGX_FILE_RDONLY, NGX_FILE_OPEN);
326
327 if (ctx->file.fd == NGX_INVALID_FILE) {
328 err = ngx_errno;
329
330 if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
331 return NGX_DECLINED;
332 }
333
334 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
335 ngx_open_file_n " \"%s\" failed", ctx->file.name.data);
336 return NGX_ERROR;
337 }
338
339 if (uniq) {
340 if (ngx_fd_info(ctx->file.fd, &ctx->file.info) == NGX_FILE_ERROR) {
341 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
342 ngx_fd_info_n " \"%s\" failed", ctx->file.name.data);
343
344 return NGX_ERROR;
345 }
346
347 if (ngx_file_uniq(&ctx->file.info) == uniq) {
348 if (ngx_close_file(ctx->file.fd) == NGX_FILE_ERROR) {
349 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
350 ngx_close_file_n " \"%s\" failed",
351 ctx->file.name.data);
352 }
353
354 return NGX_HTTP_CACHE_THE_SAME;
355 }
356 }
357
358 n = ngx_read_file(&ctx->file, ctx->buf->pos,
359 ctx->buf->end - ctx->buf->last, 0);
360
361 if (n == NGX_ERROR || n == NGX_AGAIN) {
362 return n;
363 }
364
365 if (n <= ctx->header_size) {
366 ngx_log_error(NGX_LOG_CRIT, ctx->log, 0,
367 "cache file \"%s\" is too small", ctx->file.name.data);
368 return NGX_ERROR;
369 }
370
371 h = (ngx_http_cache_header_t *) ctx->buf->pos;
372 ctx->expires = h->expires;
373 ctx->last_modified= h->last_modified;
374 ctx->date = h->date;
375 ctx->length = h->length;
376
377 if (h->key_len > (size_t) (ctx->buf->end - ctx->buf->pos)) {
378 ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
379 "cache file \"%s\" is probably invalid",
380 ctx->file.name.data);
381 return NGX_DECLINED;
382 }
383
384 if (ctx->key.len
385 && (h->key_len != ctx->key.len
386 || ngx_strncmp(h->key, ctx->key.data, h->key_len) != 0))
387 {
388 h->key[h->key_len] = '\0';
389 ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
390 "md5 collision: \"%s\" and \"%s\"",
391 h->key, ctx->key.data);
392 return NGX_DECLINED;
393 }
394
395 ctx->buf->last += n;
396
397 if (ctx->expires < ngx_time()) {
398 ngx_log_debug(ctx->log, "EXPIRED");
399 return NGX_HTTP_CACHE_STALE;
400 }
401
402 /* TODO: NGX_HTTP_CACHE_AGED */
403
404 return NGX_OK;
405 }
406
407
408 int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx,
409 ngx_str_t *temp_file)
410 {
411 int retry;
412 ngx_err_t err;
413
414 retry = 0;
415
416 for ( ;; ) {
417 if (ngx_rename_file(temp_file->data, ctx->file.name.data) == NGX_OK) {
418 return NGX_OK;
419 }
420
421 err = ngx_errno;
422
423 #if (WIN32)
424 if (err == NGX_EEXIST) {
425 if (ngx_win32_rename_file(temp_file, &ctx->file.name, r->pool)
426 == NGX_ERROR)
427 {
428 return NGX_ERROR;
429 }
430 }
431 #endif
432
433 if (retry || (err != NGX_ENOENT && err != NGX_ENOTDIR)) {
434 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
435 ngx_rename_file_n "(\"%s\", \"%s\") failed",
436 temp_file->data, ctx->file.name.data);
437
438 return NGX_ERROR;
439 }
440
441 if (ngx_create_path(&ctx->file, ctx->path) == NGX_ERROR) {
442 return NGX_ERROR;
443 }
444
445 retry = 1;
446 }
447 }
448 270
449 271
450 /* TODO: currently fd only */ 272 /* TODO: currently fd only */
451 273
452 ngx_int_t ngx_http_send_cached(ngx_http_request_t *r) 274 ngx_int_t ngx_http_send_cached(ngx_http_request_t *r)
484 } 306 }
485 307
486 h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST; 308 h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
487 309
488 h->file_pos = 0; 310 h->file_pos = 0;
489 h->file_last = ngx_file_size(&r->file.info); 311 h->file_last = r->cache->data.size;
490 312
491 h->file->fd = r->cache->fd; 313 h->file->fd = r->cache->fd;
492 h->file->log = r->connection->log; 314 h->file->log = r->connection->log;
493 315
494 out.hunk = h; 316 out.hunk = h;
495 out.next = NULL; 317 out.next = NULL;
496 318
497 return ngx_http_output_filter(r, &out); 319 return ngx_http_output_filter(r, &out);
498 }
499
500
501 int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name,
502 ngx_dir_t *dir)
503 {
504 int rc;
505 char data[sizeof(ngx_http_cache_header_t)];
506 ngx_hunk_t buf;
507 ngx_http_cache_ctx_t ctx;
508
509 ctx.file.fd = NGX_INVALID_FILE;
510 ctx.file.name = *name;
511 ctx.file.log = gc->log;
512
513 ctx.header_size = sizeof(ngx_http_cache_header_t);
514 ctx.buf = &buf;
515 ctx.log = gc->log;
516 ctx.key.len = 0;
517
518 buf.type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
519 buf.pos = data;
520 buf.last = data;
521 buf.start = data;
522 buf.end = data + sizeof(ngx_http_cache_header_t);
523
524 rc = ngx_http_cache_open_file(&ctx, 0);
525
526 /* TODO: NGX_AGAIN */
527
528 if (rc != NGX_ERROR && rc != NGX_DECLINED && rc != NGX_HTTP_CACHE_STALE) {
529 return NGX_OK;
530 }
531
532 if (ngx_delete_file(name->data) == NGX_FILE_ERROR) {
533 ngx_log_error(NGX_LOG_CRIT, gc->log, ngx_errno,
534 ngx_delete_file_n " \"%s\" failed", name->data);
535 return NGX_ERROR;
536 }
537
538 gc->deleted++;
539 gc->freed += ngx_de_size(dir);
540
541 return NGX_OK;
542 } 320 }
543 321
544 322
545 char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 323 char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
546 { 324 {