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

📄 mod_mem_cache.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
         */        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(obj->key, key, key_len);    /* Safe cast: We tested < sconf->max_cache_object_size above */    obj->info.len = (apr_size_t)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_set(&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_inc(&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_inc(&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_dec(&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(const char *key) {    cache_object_t *obj;    int cleanup = 0;    if (sconf->lock) {        apr_thread_mutex_lock(sconf->lock);    }      obj = cache_find(sconf->cache_cache, key);           if (obj) {        cache_remove(sconf->cache_cache, obj);        /* For performance, cleanup cache object after releasing the lock */        cleanup = !apr_atomic_dec(&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);    h->resp_err_hdrs = apr_table_make(r->pool, mobj->num_err_header_out);    /* ### FIXME: These two items should not be saved. */    r->subprocess_env = apr_table_make(r->pool, mobj->num_subprocess_env);    r->notes = apr_table_make(r->pool, mobj->num_notes);    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);    rc = unserialize_table( mobj->err_header_out,                            mobj->num_err_header_out,                             h->resp_err_hdrs);    rc = unserialize_table( mobj->subprocess_env,                             mobj->num_subprocess_env,                             r->subprocess_env);    rc = unserialize_table( mobj->notes,                            mobj->num_notes,                            r->notes);    /* Content-Type: header may not be set if content is local since     * CACHE_IN runs before header filters....     */    h->content_type = h->cache_obj->info.content_type;    h->status = h->cache_obj->info.status;    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;     /*     * 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 */    rc = serialize_table(&mobj->header_out,                          &mobj->num_header_out,                          ap_cache_cacheable_hdrs_out(r->pool, r->headers_out));       if (rc != APR_SUCCESS) {        return rc;    }    rc = serialize_table(&mobj->err_header_out,                          &mobj->num_err_header_out,                          ap_cache_cacheable_hdrs_out(r->pool, r->err_headers_out));       if (rc != APR_SUCCESS) {        return rc;    }    rc = serialize_table(&mobj->subprocess_env,                         &mobj->num_subprocess_env,                          r->subprocess_env );    if (rc != APR_SUCCESS) {        return rc;    }    rc = serialize_table(&mobj->notes, &mobj->num_notes, r->notes);    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->lastmod) {        obj->info.lastmod = info->lastmod;    }    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;    }    if (info->content_type) {        apr_size_t len = strlen(info->content_type) + 1;        obj->info.content_type = (char*) malloc(len);        if (!obj->info.content_type) {            return APR_ENOMEM;        }        memcpy(obj->info.content_type, info->content_type, len);    }    if (info->etag) {        apr_size_t len = strlen(info->etag) + 1;        obj->info.etag = (char*) malloc(len);        if (!obj->info.etag) {

⌨️ 快捷键说明

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