キャッシュ・キューを確認して、中のインデックス情報が期限切れになっているかどうかを確認している。
static ngx_msec_t ngx_http_file_cache_manager(void *data) { ngx_http_file_cache_t *cache = data; off_t size, free; time_t wait; ngx_msec_t elapsed, next; ngx_uint_t count, watermark; cache->last = ngx_current_msec; cache->files = 0; next = (ngx_msec_t) ngx_http_file_cache_expire(cache) * 1000; if (next == 0) { next = cache->manager_sleep; goto done; } for ( ;; ) { ngx_shmtx_lock(&cache->shpool->mutex); size = cache->sh->size; count = cache->sh->count; watermark = cache->sh->watermark; ngx_shmtx_unlock(&cache->shpool->mutex); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache size: %O c:%ui w:%i", size, count, (ngx_int_t) watermark); if (size < cache->max_size && count < watermark) { if (!cache->min_free) { break; } free = ngx_fs_available(cache->path->name.data); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache free: %O", free); if (free > cache->min_free) { break; } } wait = ngx_http_file_cache_forced_expire(cache); if (wait > 0) { next = (ngx_msec_t) wait * 1000; break; } if (ngx_quit || ngx_terminate) { break; } if (++cache->files >= cache->manager_files) { next = cache->manager_sleep; break; } ngx_time_update(); elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); if (elapsed >= cache->manager_threshold) { next = cache->manager_sleep; break; } } done: elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache manager: %ui e:%M n:%M", cache->files, elapsed, next); return next; }
次はこれ
static time_t ngx_http_file_cache_expire(ngx_http_file_cache_t *cache) { u_char *name, *p; size_t len; time_t now, wait; ngx_path_t *path; ngx_msec_t elapsed; ngx_queue_t *q; ngx_http_file_cache_node_t *fcn; u_char key[2 * NGX_HTTP_CACHE_KEY_LEN]; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache expire"); path = cache->path; len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; name = ngx_alloc(len + 1, ngx_cycle->log); if (name == NULL) { return 10; } ngx_memcpy(name, path->name.data, path->name.len); now = ngx_time(); ngx_shmtx_lock(&cache->shpool->mutex); for ( ;; ) { // シャットダウン処理中などの場合は終了する if (ngx_quit || ngx_terminate) { wait = 1; break; } // キャッシュキューが空の場合は終了する if (ngx_queue_empty(&cache->sh->queue)) { wait = 10; break; } q = ngx_queue_last(&cache->sh->queue); fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); wait = fcn->expire - now; if (wait > 0) { wait = wait > 10 ? 10 : wait; break; } ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache expire: #%d %d %02xd%02xd%02xd%02xd", fcn->count, fcn->exists, fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); // 参照カウントが0の場合にキャッシュノードを削除する if (fcn->count == 0) { ngx_http_file_cache_delete(cache, q, name); goto next; } if (fcn->deleting) { wait = 1; break; } p = ngx_hex_dump(key, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t)); len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); (void) ngx_hex_dump(p, fcn->key, len); /* * abnormally exited workers may leave locked cache entries, * and although it may be safe to remove them completely, * we prefer to just move them to the top of the inactive queue */ ngx_queue_remove(q); fcn->expire = ngx_time() + cache->inactive; ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ignore long locked inactive cache entry %*s, count:%d", (size_t) 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); next: if (++cache->files >= cache->manager_files) { wait = 0; break; } ngx_time_update(); elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); if (elapsed >= cache->manager_threshold) { wait = 0; break; } } ngx_shmtx_unlock(&cache->shpool->mutex); ngx_free(name); return wait; }
実際に削除処理を呼び出しているのはngx_http_file_cache_delete
static void ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q, u_char *name) { u_char *p; size_t len; ngx_path_t *path; ngx_http_file_cache_node_t *fcn; fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); if (fcn->exists) { cache->sh->size -= fcn->fs_size; path = cache->path; p = name + path->name.len + 1 + path->len; p = ngx_hex_dump(p, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t)); len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); p = ngx_hex_dump(p, fcn->key, len); *p = '\0'; fcn->count++; fcn->deleting = 1; ngx_shmtx_unlock(&cache->shpool->mutex); len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; ngx_create_hashed_filename(path, name, len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache expire: \"%s\"", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", name); } ngx_shmtx_lock(&cache->shpool->mutex); fcn->count--; fcn->deleting = 0; } if (fcn->count == 0) { ngx_queue_remove(q); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); ngx_slab_free_locked(cache->shpool, fcn); cache->sh->count--; } }
削除自体はunlinkがマクロになってるだけ。
#define ngx_delete_file(name) unlink((const char *) name)