-
static void
-
ngx_http_file_cache_loader(void *data)
-
{
-
ngx_http_file_cache_t *cache = data;
-
-
ngx_tree_ctx_t tree;
-
-
if (!cache->sh->cold || cache->sh->loading) {
-
return;
-
}
-
-
if (!ngx_atomic_cmp_set(&cache->sh->loading, 0, ngx_pid)) {
-
return;
-
}
-
-
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
-
"http file cache loader");
-
-
tree.init_handler = NULL;
-
tree.file_handler = ngx_http_file_cache_manage_file;
-
tree.pre_tree_handler = ngx_http_file_cache_noop;
-
tree.post_tree_handler = ngx_http_file_cache_noop;
-
tree.spec_handler = ngx_http_file_cache_delete_file;
-
tree.data = cache;
-
tree.alloc = 0;
-
tree.log = ngx_cycle->log;
-
-
cache->last = ngx_current_msec;
-
cache->files = 0;
-
-
if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) {
-
cache->sh->loading = 0;
-
return;
-
}
-
-
cache->sh->cold = 0;
-
cache->sh->loading = 0;
-
-
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
-
"http file cache: %V %.3fM, bsize: %uz",
-
&cache->path->name,
-
((double) cache->sh->size * cache->bsize) / (1024 * 1024),
-
cache->bsize);
-
}
==== 最后分析ngx_walk_tree方法:
/* ngx_walk_tree是递归函数,打开每层路径(dir)直到每个文件(file),根据其路径和文件名得到key,在缓存的rbtree(红黑树)里面找这个key(部分), 如果没有找到的话,就在内存中分配一个映射这个文件的node(但是不会把文件的内容进行缓存),然后插入到红黑树中和加入队列。
ngx_http_file_cache_loader
ctx->file_handler=>
ngx_http_file_cache_manage_file=>
ngx_http_file_cache_add_file=>
ngx_http_file_cache_add
从n = ngx_read_file(...)函数可以看出,每个磁盘缓存文件的开头的sizeof(ngx_http_file_cache_header_t)个byte存放了跟缓存相关的信息 */
-
ngx_int_t
-
ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t*tree)
-
{
-
void *data, *prev;
-
u_char *p, *name;
-
size_t len;
-
ngx_int_t rc;
-
ngx_err_t err;
-
ngx_str_t file, buf;
-
ngx_dir_t dir;
-
ngx_str_null(&buf);
-
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
-
"walk tree\"%V\"", tree);
-
//打开name指定的目录,并将返回值以DIR*的形式赋值给dir->dir后面对该目录下所有文件的访问都可以通过dir->dir进行
-
if(ngx_open_dir(tree, &dir) == NGX_ERROR)
-
{
-
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
-
ngx_open_dir_n "\"%s\" failed", tree->data);
-
return NGX_ERROR;
-
}
-
prev = ctx->data;
-
if(ctx->alloc)
-
{
-
data = ngx_alloc(ctx->alloc, ctx->log);
-
if (data == NULL)
-
{
-
goto failed;
-
-
}
-
if (ctx->init_handler(data, prev) == NGX_ABORT)
-
{
-
goto failed;
-
}
-
ctx->data = data;
-
}
-
else
-
{
-
data = NULL;
-
}
-
for ( ;; )
-
{
-
ngx_set_errno(0);
-
//返回下一个目录进入点,并赋值给dir->de
-
if (ngx_read_dir(&dir) == NGX_ERROR)
-
{
-
err = ngx_errno;
-
if (err == NGX_ENOMOREFILES)
-
{
-
rc = NGX_OK;
-
}
-
else
-
{
-
ngx_log_error(NGX_LOG_CRIT,ctx->log, err,
-
ngx_read_dir_n" \"%s\" failed", tree->data);
-
rc = NGX_ERROR;
-
}
-
goto done;
-
}
-
len = ngx_de_namelen(&dir);
-
name = ngx_de_name(&dir);
-
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0,
-
"tree name%uz:\"%s\"", len, name);
-
if (len == 1 && name[0] == '.')
-
{
-
continue;
-
}
-
if (len == 2 && name[0] == '.' && name[1] == '.')
-
{
-
continue;
-
}
-
file.len = tree->len + 1 + len;
-
if (file.len + NGX_DIR_MASK_LEN > buf.len)
-
{
-
if (buf.len)
-
{
-
ngx_free(buf.data);
-
}
-
buf.len = tree->len + 1 + len + NGX_DIR_MASK_LEN;
-
buf.data = ngx_alloc(buf.len + 1, ctx->log);
-
if (buf.data == NULL)
-
{
-
goto failed;
-
}
-
}
-
p = ngx_cpymem(buf.data, tree->data, tree->len);
-
*p++ = '/';
-
ngx_memcpy(p, name, len + 1);
-
file.data = buf.data;
-
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
-
"tree path \"%s\"",file.data);
-
if (!dir.valid_info)
-
{
-
if (ngx_de_info(file.data, &dir) == NGX_FILE_ERROR)
-
{
-
ngx_log_error(NGX_LOG_CRIT,ctx->log, ngx_errno,
-
ngx_de_info_n" \"%s\" failed", file.data);
-
continue;
-
}
-
}
-
//dir->de指向的是文件
-
if (ngx_de_is_file(&dir))
-
{
-
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
-
"tree file\"%s\"", file.data);
-
ctx->size = ngx_de_size(&dir);
-
ctx->fs_size = ngx_de_fs_size(&dir);
-
ctx->access = ngx_de_access(&dir);
-
ctx->mtime = ngx_de_mtime(&dir);
-
////////////////////////////////////////////////////////////////进行索引重建
-
//ngx_http_file_cache_loader中将其设置为tree.file_handler = ngx_http_file_cache_manage_file;
-
if (ctx->file_handler(ctx, &file) == NGX_ABORT)
-
{
-
goto failed;
-
}
-
//dir->de指向的是目录
-
}
-
else if (ngx_de_is_dir(&dir))
-
{
-
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
-
"tree enter dir\"%s\"", file.data);
-
ctx->access = ngx_de_access(&dir);
-
ctx->mtime = ngx_de_mtime(&dir);
-
//其实在ngx_http_file_cache_loader方法中已经完成了注册,只是返回NGX_OK
-
if (ctx->pre_tree_handler(ctx, &file) == NGX_ABORT)
-
{
-
goto failed;
-
}
-
-
//针对于子目录进行递归调用
-
if (ngx_walk_tree(ctx, &file) == NGX_ABORT)
-
{
-
goto failed;
-
}
-
ctx->access = ngx_de_access(&dir);
-
ctx->mtime = ngx_de_mtime(&dir);
-
//其实在ngx_http_file_cache_loader方法中已经完成了注册,只是返回NGX_OK
-
-
if (ctx->post_tree_handler(ctx, &file) == NGX_ABORT)
-
{
-
goto failed;
-
}
-
}
-
else
-
{
-
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
-
"tree special\"%s\"", file.data);
-
if (ctx->spec_handler(ctx, &file) == NGX_ABORT)
-
{
-
goto failed;
-
}
-
}
-
}
-
failed:
-
rc= NGX_ABORT;
-
done:
-
if(buf.len)
-
{
-
ngx_free(buf.data);
-
}
-
-
if(data)
-
{
-
ngx_free(data);
-
ctx->data = prev;
-
}
-
-
if(ngx_close_dir(&dir) == NGX_ERROR)
-
{
-
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
-
ngx_close_dir_n "\"%s\" failed", tree->data);
-
}
-
return rc;
-
}
阅读(1609) | 评论(0) | 转发(0) |