static time_t ngx_http_file_cache_manager(void *data) { ngx_http_file_cache_t *cache = data; off_t size; time_t next; next = ngx_http_file_cache_expire(cache); cache->last = ngx_current_msec; cache->files = 0; for ( ;; ) { ngx_shmtx_lock(&cache->shpool->mutex); size = cache->sh->size; ngx_shmtx_unlock(&cache->shpool->mutex); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache size: %O", size); if (size < cache->max_size) { return next; } next = ngx_http_file_cache_forced_expire(cache); if (ngx_http_file_cache_manager_sleep(cache) != NGX_OK) { return next; } } }
static time_t ngx_http_file_cache_manager(void *data) { ngx_http_file_cache_t *cache = data; off_t size; time_t next, wait; // 检查是否有缓存文件过期 next = ngx_http_file_cache_expire(cache); // 设置缓存最后被访问的时间 cache->last = ngx_current_msec; cache->files = 0; for ( ;; ) { ngx_shmtx_lock(&cache->shpool->mutex); size = cache->sh->size; // ??? ngx_shmtx_unlock(&cache->shpool->mutex); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache size: %O", size); if (size < cache->max_size) { return next; } wait = ngx_http_file_cache_forced_expire(cache); if (wait > 0) { return wait; } if (ngx_quit || ngx_terminate) { return next; } } }
static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) { ngx_int_t rc; ngx_http_file_cache_node_t *fcn; ngx_shmtx_lock(&cache->shpool->mutex); fcn = ngx_http_file_cache_lookup(cache, c->key); if (fcn) { ngx_queue_remove(&fcn->queue); if (fcn->error) { if (fcn->valid_sec < ngx_time()) { goto renew; } rc = NGX_OK; goto done; } fcn->uses++; fcn->count++; if (fcn->exists) { c->exists = fcn->exists; c->body_start = fcn->body_start; rc = NGX_OK; goto done; } if (fcn->uses >= c->min_uses) { c->exists = fcn->exists; c->body_start = fcn->body_start; rc = NGX_OK; } else { rc = NGX_AGAIN; } goto done; } fcn = ngx_slab_alloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { ngx_shmtx_unlock(&cache->shpool->mutex); (void) ngx_http_file_cache_forced_expire(cache); ngx_shmtx_lock(&cache->shpool->mutex); fcn = ngx_slab_alloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { rc = NGX_ERROR; goto failed; } } ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t)); ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node); renew: rc = NGX_DECLINED; fcn->uses = 1; fcn->count = 1; fcn->valid_msec = 0; fcn->error = 0; fcn->exists = 0; fcn->valid_sec = 0; fcn->uniq = 0; fcn->body_start = 0; fcn->length = 0; done: fcn->expire = ngx_time() + cache->inactive; ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); c->uniq = fcn->uniq; c->error = fcn->error; c->node = fcn; failed: ngx_shmtx_unlock(&cache->shpool->mutex); return rc; }
/* NGX_OK NGX_AGAIN NGX_ERROR NGX_DECLINED: cache索引表中没有查找到,创建node并插入到红黑树和队列中,并且设置node节点到 c->node */ static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) { ngx_int_t rc; ngx_http_file_cache_node_t *fcn; // 对共享内存区上锁 ngx_shmtx_lock(&cache->shpool->mutex); // 在函数 ngx_init_zone_pool()中设置并创建 fcn = c->node; if (fcn == NULL) { // 在cache中查找key fcn = ngx_http_file_cache_lookup(cache, c->key); } // 在共享内存中找到cache if (fcn) { // 在队列中删除???? ngx_queue_remove(&fcn->queue); // ???? if (c->node == NULL) { fcn->uses++; fcn->count++; } // ???? if (fcn->error) { if (fcn->valid_sec < ngx_time()) { goto renew; } rc = NGX_OK; goto done; } if (fcn->exists || fcn->uses >= c->min_uses) { c->exists = fcn->exists; if (fcn->body_start) { c->body_start = fcn->body_start; } rc = NGX_OK; goto done; } rc = NGX_AGAIN; goto done; } //################ 在共享内存cache索引表中没有查找到此cache ################ // 1. 申请一个cache节点 fcn = ngx_slab_alloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { // 共享内存空间不足申请一个cache节点时,强制过期一个cache节点 ngx_shmtx_unlock(&cache->shpool->mutex); (void) ngx_http_file_cache_forced_expire(cache); ngx_shmtx_lock(&cache->shpool->mutex); fcn = ngx_slab_alloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { rc = NGX_ERROR; goto failed; } } // 2. 拷贝节点key ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t)); ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); // 3. 插入到红黑树中 ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node); fcn->uses = 1; fcn->count = 1; fcn->updating = 0; fcn->deleting = 0; renew: rc = NGX_DECLINED; fcn->valid_msec = 0; fcn->error = 0; fcn->exists = 0; fcn->valid_sec = 0; fcn->uniq = 0; fcn->body_start = 0; fcn->fs_size = 0; done: fcn->expire = ngx_time() + cache->inactive; ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); c->uniq = fcn->uniq; c->error = fcn->error; c->node = fcn; // 设置node节点 failed: ngx_shmtx_unlock(&cache->shpool->mutex); return rc; }