ngx_open_file_cache.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 820 行 · 第 1/2 页

C
820
字号
        cache->current--;        if (file->count == 0) {	    if (file->fd != NGX_INVALID_FILE) {		if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {		    ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,				  ngx_close_file_n " \"%s\" failed",                                  file->name);		}	    }            ngx_free(file->name);            ngx_free(file);        } else {            file->close = 1;        }    }    if (of->fd != NGX_INVALID_FILE) {        if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {            ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,                          ngx_close_file_n " \"%s\" failed", name->data);        }    }    return NGX_ERROR;}static ngx_int_tngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log){    ngx_fd_t         fd;    ngx_file_info_t  fi;    of->fd = NGX_INVALID_FILE;    if (of->test_dir) {        if (ngx_file_info(name, &fi) == -1) {            of->err = ngx_errno;            return NGX_ERROR;        }        of->uniq = ngx_file_uniq(&fi);        of->mtime = ngx_file_mtime(&fi);        of->size = ngx_file_size(&fi);        of->is_dir = ngx_is_dir(&fi);        of->is_file = ngx_is_file(&fi);        of->is_link = ngx_is_link(&fi);        of->is_exec = ngx_is_exec(&fi);        if (of->is_dir) {            return NGX_OK;        }    }    fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);    if (fd == NGX_INVALID_FILE) {        of->err = ngx_errno;        return NGX_ERROR;    }    if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,                      ngx_fd_info_n " \"%s\" failed", name);        if (ngx_close_file(fd) == NGX_FILE_ERROR) {            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,                          ngx_close_file_n " \"%s\" failed", name);        }        return NGX_ERROR;    }    if (ngx_is_dir(&fi)) {        if (ngx_close_file(fd) == NGX_FILE_ERROR) {            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,                          ngx_close_file_n " \"%s\" failed", name);        }        fd = NGX_INVALID_FILE;    }    of->fd = fd;    of->uniq = ngx_file_uniq(&fi);    of->mtime = ngx_file_mtime(&fi);    of->size = ngx_file_size(&fi);    of->is_dir = ngx_is_dir(&fi);    of->is_file = ngx_is_file(&fi);    of->is_link = ngx_is_link(&fi);    of->is_exec = ngx_is_exec(&fi);    return NGX_OK;}/* * we ignore any possible event setting error and * fallback to usual periodic file retests */static voidngx_open_file_add_event(ngx_open_file_cache_t *cache,    ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log){    ngx_open_file_cache_event_t  *fev;    if (!(ngx_event_flags & NGX_USE_VNODE_EVENT)        || !of->events        || file->event        || of->fd == NGX_INVALID_FILE        || file->uses < of->min_uses)    {        return;    }    file->event = ngx_calloc(sizeof(ngx_event_t), log);    if (file->event== NULL) {        return;    }    fev = ngx_alloc(sizeof(ngx_open_file_cache_event_t), log);    if (fev == NULL) {        ngx_free(file->event);        file->event = NULL;        return;    }    fev->fd = of->fd;    fev->file = file;    fev->cache = cache;    file->event->handler = ngx_open_file_cache_remove;    file->event->data = fev;    /*     * although vnode event may be called while ngx_cycle->poll     * destruction, however, cleanup procedures are run before any     * memory freeing and events will be canceled.     */    file->event->log = ngx_cycle->log;    if (ngx_add_event(file->event, NGX_VNODE_EVENT, NGX_ONESHOT_EVENT)        != NGX_OK)    {        ngx_free(file->event->data);        ngx_free(file->event);        file->event = NULL;        return;    }    /*     * we do not file->use_event here because there may be a race     * condition between opening file and adding event, so we rely     * upon event notification only after first file revalidation     */    return;}static voidngx_open_file_cleanup(void *data){    ngx_open_file_cache_cleanup_t  *c = data;    c->file->count--;    ngx_close_cached_file(c->cache, c->file, c->min_uses, c->log);    /* drop one or two expired open files */    ngx_expire_old_cached_files(c->cache, 1, c->log);}static voidngx_close_cached_file(ngx_open_file_cache_t *cache,    ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log){    ngx_log_debug5(NGX_LOG_DEBUG_CORE, log, 0,                   "close cached open file: %s, fd:%d, c:%d, u:%d, %d",                   file->name, file->fd, file->count, file->uses, file->close);    if (!file->close) {        file->accessed = ngx_time();        ngx_queue_remove(&file->queue);        ngx_queue_insert_head(&cache->expire_queue, &file->queue);        if (file->uses >= min_uses || file->count) {            return;        }    }    ngx_open_file_del_event(file);    if (file->count) {        return;    }    if (file->fd != NGX_INVALID_FILE) {        if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,                          ngx_close_file_n " \"%s\" failed", file->name);        }        file->fd = NGX_INVALID_FILE;    }    if (!file->close) {        return;    }    ngx_free(file->name);    ngx_free(file);}static voidngx_open_file_del_event(ngx_cached_open_file_t *file){    if (file->event == NULL) {        return;    }    (void) ngx_del_event(file->event, NGX_VNODE_EVENT,                         file->count ? NGX_FLUSH_EVENT : NGX_CLOSE_EVENT);    ngx_free(file->event->data);    ngx_free(file->event);    file->event = NULL;    file->use_event = 0;}static voidngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,    ngx_log_t *log){    time_t                   now;    ngx_queue_t             *q;    ngx_cached_open_file_t  *file;    now = ngx_time();    /*     * n == 1 deletes one or two inactive files     * n == 0 deletes least recently used file by force     *        and one or two inactive files     */    while (n < 3) {        if (ngx_queue_empty(&cache->expire_queue)) {            return;        }        q = ngx_queue_last(&cache->expire_queue);        file = ngx_queue_data(q, ngx_cached_open_file_t, queue);        if (n++ != 0 && now - file->accessed <= cache->inactive) {            return;        }        ngx_queue_remove(q);        ngx_rbtree_delete(&cache->rbtree, &file->node);        cache->current--;        ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,                       "expire cached open file: %s", file->name);        if (!file->err && !file->is_dir) {            file->close = 1;            ngx_close_cached_file(cache, file, 0, log);        } else {            ngx_free(file->name);            ngx_free(file);        }    }}static voidngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel){    ngx_rbtree_node_t       **p;    ngx_cached_open_file_t    *file, *file_temp;    for ( ;; ) {        if (node->key < temp->key) {            p = &temp->left;        } else if (node->key > temp->key) {            p = &temp->right;        } else { /* node->key == temp->key */            file = (ngx_cached_open_file_t *) node;            file_temp = (ngx_cached_open_file_t *) temp;            p = (ngx_strcmp(file->name, file_temp->name) < 0)                    ? &temp->left : &temp->right;        }        if (*p == sentinel) {            break;        }        temp = *p;    }    *p = node;    node->parent = temp;    node->left = sentinel;    node->right = sentinel;    ngx_rbt_red(node);}static ngx_cached_open_file_t *ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name,    uint32_t hash){    ngx_int_t                rc;    ngx_rbtree_node_t       *node, *sentinel;    ngx_cached_open_file_t  *file;    node = cache->rbtree.root;    sentinel = cache->rbtree.sentinel;    while (node != sentinel) {        if (hash < node->key) {            node = node->left;            continue;        }        if (hash > node->key) {            node = node->right;            continue;        }        /* hash == node->key */        do {            file = (ngx_cached_open_file_t *) node;            rc = ngx_strcmp(name->data, file->name);            if (rc == 0) {                return file;            }            node = (rc < 0) ? node->left : node->right;        } while (node != sentinel && hash == node->key);        break;    }    return NULL;}static voidngx_open_file_cache_remove(ngx_event_t *ev){    ngx_cached_open_file_t       *file;    ngx_open_file_cache_event_t  *fev;    fev = ev->data;    file = fev->file;    ngx_queue_remove(&file->queue);    ngx_rbtree_delete(&fev->cache->rbtree, &file->node);    fev->cache->current--;    /* NGX_ONESHOT_EVENT was already deleted */    file->event = NULL;    file->close = 1;    ngx_close_cached_file(fev->cache, file, 0, ev->log);    /* free memory only when fev->cache and fev->file are already not needed */    ngx_free(ev->data);    ngx_free(ev);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?