⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_mem_cache.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 3 页
字号:
        /* CACHE_TYPE_FILE is only valid for local content handled by the         * default handler. Need a better way to check if the file is         * local or not.         */        if (!r->filename) {            return DECLINED;        }    }    rv = apr_pool_create(&pool, NULL);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server,                     "mem_cache: Failed to create memory pool.");        return DECLINED;    }    /* Allocate and initialize cache_object_t */    obj = apr_pcalloc(pool, sizeof(*obj));    obj->key = apr_pstrdup(pool, key);    /* Allocate and init mem_cache_object_t */    mobj = apr_pcalloc(pool, sizeof(*mobj));    mobj->pool = pool;    /* Finish initing the cache object */    apr_atomic_set32(&obj->refcount, 1);    mobj->total_refs = 1;    obj->complete = 0;    obj->vobj = mobj;    /* Safe cast: We tested < sconf->max_cache_object_size above */    mobj->m_len = (apr_size_t)len;    mobj->type = type_e;    /* Place the cache_object_t into the hash table.     * Note: Perhaps we should wait to put the object in the     * hash table when the object is complete?  I add the object here to     * avoid multiple threads attempting to cache the same content only     * to discover at the very end that only one of them will succeed.     * Furthermore, adding the cache object to the table at the end could     * open up a subtle but easy to exploit DoS hole: someone could request     * a very large file with multiple requests. Better to detect this here     * rather than after the cache object has been completely built and     * initialized...     * XXX Need a way to insert into the cache w/o such coarse grained locking     */    if (sconf->lock) {        apr_thread_mutex_lock(sconf->lock);    }    tmp_obj = (cache_object_t *) cache_find(sconf->cache_cache, key);    if (!tmp_obj) {        cache_insert(sconf->cache_cache, obj);        /* Add a refcount to account for the reference by the         * hashtable in the cache. Refcount should be 2 now, one         * for this thread, and one for the cache.         */        apr_atomic_inc32(&obj->refcount);    }    if (sconf->lock) {        apr_thread_mutex_unlock(sconf->lock);    }    if (tmp_obj) {        /* This thread collided with another thread loading the same object         * into the cache at the same time. Defer to the other thread which         * is further along.         */        cleanup_cache_object(obj);        return DECLINED;    }    apr_pool_cleanup_register(r->pool, obj, decrement_refcount,                              apr_pool_cleanup_null);    /* Populate the cache handle */    h->cache_obj = obj;    return OK;}static int create_mem_entity(cache_handle_t *h, request_rec *r,                             const char *key, apr_off_t len){    return create_entity(h, CACHE_TYPE_HEAP, r, key, len);}static int create_fd_entity(cache_handle_t *h, request_rec *r,                            const char *key, apr_off_t len){    return create_entity(h, CACHE_TYPE_FILE, r, key, len);}static int open_entity(cache_handle_t *h, request_rec *r, const char *key){    cache_object_t *obj;    /* Look up entity keyed to 'url' */    if (sconf->lock) {        apr_thread_mutex_lock(sconf->lock);    }    obj = (cache_object_t *) cache_find(sconf->cache_cache, key);    if (obj) {        if (obj->complete) {            request_rec *rmain=r, *rtmp;            apr_atomic_inc32(&obj->refcount);            /* cache is worried about overall counts, not 'open' ones */            cache_update(sconf->cache_cache, obj);            /* If this is a subrequest, register the cleanup against             * the main request. This will prevent the cache object             * from being cleaned up from under the request after the             * subrequest is destroyed.             */            rtmp = r;            while (rtmp) {                rmain = rtmp;                rtmp = rmain->main;            }            apr_pool_cleanup_register(rmain->pool, obj, decrement_refcount,                                      apr_pool_cleanup_null);        }        else {            obj = NULL;        }    }    if (sconf->lock) {        apr_thread_mutex_unlock(sconf->lock);    }    if (!obj) {        return DECLINED;    }    /* Initialize the cache_handle */    h->cache_obj = obj;    h->req_hdrs = NULL;  /* Pick these up in recall_headers() */    return OK;}/* remove_entity() * Notes: *   refcount should be at least 1 upon entry to this function to account *   for this thread's reference to the object. If the refcount is 1, then *   object has been removed from the cache by another thread and this thread *   is the last thread accessing the object. */static int remove_entity(cache_handle_t *h){    cache_object_t *obj = h->cache_obj;    cache_object_t *tobj = NULL;    if (sconf->lock) {        apr_thread_mutex_lock(sconf->lock);    }    /* If the entity is still in the cache, remove it and decrement the     * refcount. If the entity is not in the cache, do nothing. In both cases     * decrement_refcount called by the last thread referencing the object will     * trigger the cleanup.     */    tobj = cache_find(sconf->cache_cache, obj->key);    if (tobj == obj) {        cache_remove(sconf->cache_cache, obj);        apr_atomic_dec32(&obj->refcount);    }    if (sconf->lock) {        apr_thread_mutex_unlock(sconf->lock);    }    return OK;}/* Define request processing hook handlers *//* remove_url() * Notes: */static int remove_url(cache_handle_t *h, apr_pool_t *p){    cache_object_t *obj;    int cleanup = 0;    if (sconf->lock) {        apr_thread_mutex_lock(sconf->lock);    }    obj = h->cache_obj;    if (obj) {        cache_remove(sconf->cache_cache, obj);        /* For performance, cleanup cache object after releasing the lock */        cleanup = !apr_atomic_dec32(&obj->refcount);    }    if (sconf->lock) {        apr_thread_mutex_unlock(sconf->lock);    }    if (cleanup) {        cleanup_cache_object(obj);    }    return OK;}static apr_table_t *deep_table_copy(apr_pool_t *p, const apr_table_t *table){    const apr_array_header_t *array = apr_table_elts(table);    apr_table_entry_t *elts = (apr_table_entry_t *) array->elts;    apr_table_t *copy = apr_table_make(p, array->nelts);    int i;    for (i = 0; i < array->nelts; i++) {        if (elts[i].key) {              apr_table_add(copy, elts[i].key, elts[i].val);        }    }    return copy;}static apr_status_t recall_headers(cache_handle_t *h, request_rec *r){    mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj;    h->req_hdrs = deep_table_copy(r->pool, mobj->req_hdrs);    h->resp_hdrs = deep_table_copy(r->pool, mobj->header_out);    return OK;}static apr_status_t recall_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb){    apr_bucket *b;    mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj;    if (mobj->type == CACHE_TYPE_FILE) {        /* CACHE_TYPE_FILE */        apr_file_t *file;        apr_os_file_put(&file, &mobj->fd, mobj->flags, p);        b = apr_bucket_file_create(file, 0, mobj->m_len, p, bb->bucket_alloc);    }    else {        /* CACHE_TYPE_HEAP */        b = apr_bucket_immortal_create(mobj->m, mobj->m_len, bb->bucket_alloc);    }    APR_BRIGADE_INSERT_TAIL(bb, b);    b = apr_bucket_eos_create(bb->bucket_alloc);    APR_BRIGADE_INSERT_TAIL(bb, b);    return APR_SUCCESS;}static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info){    cache_object_t *obj = h->cache_obj;    mem_cache_object_t *mobj = (mem_cache_object_t*) obj->vobj;    apr_table_t *headers_out;    /*     * The cache needs to keep track of the following information:     * - Date, LastMod, Version, ReqTime, RespTime, ContentLength     * - The original request headers (for Vary)     * - The original response headers (for returning with a cached response)     * - The body of the message     */    mobj->req_hdrs = deep_table_copy(mobj->pool, r->headers_in);    /* Precompute how much storage we need to hold the headers */    headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out,                                              r->server);    /* If not set in headers_out, set Content-Type */    if (!apr_table_get(headers_out, "Content-Type")        && r->content_type) {        apr_table_setn(headers_out, "Content-Type",                       ap_make_content_type(r, r->content_type));    }    headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out);    mobj->header_out = deep_table_copy(mobj->pool, headers_out);    /* Init the info struct */    obj->info.status = info->status;    if (info->date) {        obj->info.date = info->date;    }    if (info->response_time) {        obj->info.response_time = info->response_time;    }    if (info->request_time) {        obj->info.request_time = info->request_time;    }    if (info->expire) {        obj->info.expire = info->expire;    }    return APR_SUCCESS;}static apr_status_t store_body(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b){    apr_status_t rv;    cache_object_t *obj = h->cache_obj;    cache_object_t *tobj = NULL;    mem_cache_object_t *mobj = (mem_cache_object_t*) obj->vobj;    apr_read_type_e eblock = APR_BLOCK_READ;    apr_bucket *e;    char *cur;    int eos = 0;    if (mobj->type == CACHE_TYPE_FILE) {        apr_file_t *file = NULL;        int fd = 0;        int other = 0;        /* We can cache an open file descriptor if:         * - the brigade contains one and only one file_bucket &&         * - the brigade is complete &&         * - the file_bucket is the last data bucket in the brigade         */        for (e = APR_BRIGADE_FIRST(b);             e != APR_BRIGADE_SENTINEL(b);             e = APR_BUCKET_NEXT(e))        {            if (APR_BUCKET_IS_EOS(e)) {                eos = 1;            }            else if (APR_BUCKET_IS_FILE(e)) {                apr_bucket_file *a = e->data;                fd++;                file = a->fd;            }            else {                other++;

⌨️ 快捷键说明

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