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

📄 mod_mem_cache.c

📁 apache服务器源代码(版本号:2.2.2)
💻 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;        }    }    /* Allocate and initialize cache_object_t */    obj = calloc(1, sizeof(*obj));    if (!obj) {        return DECLINED;    }    key_len = strlen(key) + 1;    obj->key = malloc(key_len);    if (!obj->key) {        cleanup_cache_object(obj);        return DECLINED;    }    memcpy((void*)obj->key, key, key_len);    /* Allocate and init mem_cache_object_t */    mobj = calloc(1, sizeof(*mobj));    if (!mobj) {        cleanup_cache_object(obj);        return DECLINED;    }    /* 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;}static apr_status_t serialize_table(cache_header_tbl_t **obj,                                    apr_ssize_t *nelts,                                    apr_table_t *table){    const apr_array_header_t *elts_arr = apr_table_elts(table);    apr_table_entry_t *elts = (apr_table_entry_t *) elts_arr->elts;    apr_ssize_t i;    apr_size_t len = 0;    apr_size_t idx = 0;    char *buf;    *nelts = elts_arr->nelts;    if (*nelts == 0 ) {        *obj=NULL;        return APR_SUCCESS;    }    *obj = malloc(sizeof(cache_header_tbl_t) * elts_arr->nelts);    if (NULL == *obj) {        return APR_ENOMEM;    }    for (i = 0; i < elts_arr->nelts; ++i) {        len += strlen(elts[i].key);        len += strlen(elts[i].val);        len += 2;  /* Extra space for NULL string terminator for key and val */    }    /* Transfer the headers into a contiguous memory block */    buf = malloc(len);    if (!buf) {        *obj = NULL;        return APR_ENOMEM;    }    for (i = 0; i < *nelts; ++i) {        (*obj)[i].hdr = &buf[idx];        len = strlen(elts[i].key) + 1;              /* Include NULL terminator */        memcpy(&buf[idx], elts[i].key, len);        idx+=len;        (*obj)[i].val = &buf[idx];        len = strlen(elts[i].val) + 1;        memcpy(&buf[idx], elts[i].val, len);        idx+=len;    }    return APR_SUCCESS;}static int unserialize_table( cache_header_tbl_t *ctbl,                              int num_headers,                              apr_table_t *t ){    int i;    for (i = 0; i < num_headers; ++i) {        apr_table_addn(t, ctbl[i].hdr, ctbl[i].val);    }    return APR_SUCCESS;}/* 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_status_t recall_headers(cache_handle_t *h, request_rec *r){    int rc;    mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj;    h->req_hdrs = apr_table_make(r->pool, mobj->num_req_hdrs);    h->resp_hdrs = apr_table_make(r->pool, mobj->num_header_out);    rc = unserialize_table(mobj->req_hdrs, mobj->num_req_hdrs, h->req_hdrs);    rc = unserialize_table(mobj->header_out, mobj->num_header_out,                           h->resp_hdrs);    return rc;}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;    int rc;    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     */    rc = serialize_table(&mobj->req_hdrs,                         &mobj->num_req_hdrs,                         r->headers_in);    if (rc != APR_SUCCESS) {        return rc;    }    /* Precompute how much storage we need to hold the headers */    headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out,                                              r->server);    headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out);    rc = serialize_table(&mobj->header_out, &mobj->num_header_out,                         headers_out);    if (rc != APR_SUCCESS) {        return rc;    }    /* 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;

⌨️ 快捷键说明

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