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

📄 store.c

📁 -
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * $Id: store.c,v 1.488.2.2 1999/05/10 16:02:04 wessels Exp $ * * DEBUG: section 20    Storage Manager * AUTHOR: Harvest Derived * * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * *  Squid is the result of efforts by numerous individuals from the *  Internet community.  Development is led by Duane Wessels of the *  National Laboratory for Applied Network Research and funded by the *  National Science Foundation.  Squid is Copyrighted (C) 1998 by *  Duane Wessels and the University of California San Diego.  Please *  see the COPYRIGHT file for full details.  Squid incorporates *  software developed and/or copyrighted by other sources.  Please see *  the CREDITS file for full details. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"#define REBUILD_TIMESTAMP_DELTA_MAX 2#define STORE_IN_MEM_BUCKETS		(229)const char *memStatusStr[] ={    "NOT_IN_MEMORY",    "IN_MEMORY"};const char *pingStatusStr[] ={    "PING_NONE",    "PING_WAITING",    "PING_DONE"};const char *storeStatusStr[] ={    "STORE_OK",    "STORE_PENDING"};const char *swapStatusStr[] ={    "SWAPOUT_NONE",    "SWAPOUT_OPENING",    "SWAPOUT_WRITING",    "SWAPOUT_DONE"};typedef struct lock_ctrl_t {    SIH *callback;    void *callback_data;    StoreEntry *e;} lock_ctrl_t;/* * local function prototypes */static int storeCheckExpired(const StoreEntry *);static int storeEntryLocked(const StoreEntry *);static int storeEntryValidLength(const StoreEntry *);static void storeGetMemSpace(int);static void storeHashDelete(StoreEntry *);static MemObject *new_MemObject(const char *, const char *);static void destroy_MemObject(StoreEntry *);static FREE destroy_StoreEntry;static void storePurgeMem(StoreEntry *);static int getKeyCounter(void);static int storeKeepInMemory(const StoreEntry *);static OBJH storeCheckCachableStats;static EVH storeLateRelease;/* * local variables */static dlink_list inmem_list;static int store_pages_max = 0;static int store_swap_high = 0;static int store_swap_low = 0;static int store_swap_mid = 0;static int store_maintain_rate;static Stack LateReleaseStack;static MemObject *new_MemObject(const char *url, const char *log_url){    MemObject *mem = memAllocate(MEM_MEMOBJECT);    mem->reply = httpReplyCreate();    mem->url = xstrdup(url);    mem->log_url = xstrdup(log_url);    mem->swapout.fd = -1;    mem->object_sz = -1;    mem->fd = -1;    /* XXX account log_url */    debug(20, 3) ("new_MemObject: returning %p\n", mem);    return mem;}StoreEntry *new_StoreEntry(int mem_obj_flag, const char *url, const char *log_url){    StoreEntry *e = NULL;    e = memAllocate(MEM_STOREENTRY);    if (mem_obj_flag)	e->mem_obj = new_MemObject(url, log_url);    debug(20, 3) ("new_StoreEntry: returning %p\n", e);    e->expires = e->lastmod = e->lastref = e->timestamp = -1;    return e;}static voiddestroy_MemObject(StoreEntry * e){    MemObject *mem = e->mem_obj;    const Ctx ctx = ctx_enter(mem->url);    debug(20, 3) ("destroy_MemObject: destroying %p\n", mem);    e->mem_obj = NULL;    if (!shutting_down)	assert(mem->swapout.fd == -1);    stmemFree(&mem->data_hdr);    mem->inmem_hi = 0;    /* XXX account log_url */#if USE_ASYNC_IO    while (mem->clients != NULL)	storeUnregister(e, mem->clients->callback_data);#endif    /*     * There is no way to abort FD-less clients, so they might     * still have mem->clients set if mem->fd == -1     */    assert(mem->fd == -1 || mem->clients == NULL);    httpReplyDestroy(mem->reply);    requestUnlink(mem->request);    mem->request = NULL;    ctx_exit(ctx);		/* must exit before we free mem->url */    safe_free(mem->url);    safe_free(mem->log_url);    memFree(mem, MEM_MEMOBJECT);}static voiddestroy_StoreEntry(void *data){    StoreEntry *e = data;    debug(20, 3) ("destroy_StoreEntry: destroying %p\n", e);    assert(e != NULL);    if (e->mem_obj)	destroy_MemObject(e);    storeHashDelete(e);    assert(e->key == NULL);    memFree(e, MEM_STOREENTRY);}/* ----- INTERFACE BETWEEN STORAGE MANAGER AND HASH TABLE FUNCTIONS --------- */voidstoreHashInsert(StoreEntry * e, const cache_key * key){    debug(20, 3) ("storeHashInsert: Inserting Entry %p key '%s'\n",	e, storeKeyText(key));    e->key = storeKeyDup(key);    hash_join(store_table, (hash_link *) e);    dlinkAdd(e, &e->lru, &store_list);}static voidstoreHashDelete(StoreEntry * e){    hash_remove_link(store_table, (hash_link *) e);    dlinkDelete(&e->lru, &store_list);    storeKeyFree(e->key);    e->key = NULL;}/* -------------------------------------------------------------------------- *//* get rid of memory copy of the object *//* Only call this if storeCheckPurgeMem(e) returns 1 */static voidstorePurgeMem(StoreEntry * e){    if (e->mem_obj == NULL)	return;    debug(20, 3) ("storePurgeMem: Freeing memory-copy of %s\n",	storeKeyText(e->key));    storeSetMemStatus(e, NOT_IN_MEMORY);    destroy_MemObject(e);    if (e->swap_status != SWAPOUT_DONE)	storeRelease(e);}voidstoreLockObject(StoreEntry * e){    if (e->lock_count++ == 0) {	dlinkDelete(&e->lru, &store_list);	dlinkAdd(e, &e->lru, &store_list);    }    debug(20, 3) ("storeLockObject: key '%s' count=%d\n",	storeKeyText(e->key), (int) e->lock_count);    e->lastref = squid_curtime;}voidstoreReleaseRequest(StoreEntry * e){    if (EBIT_TEST(e->flags, RELEASE_REQUEST))	return;    debug(20, 3) ("storeReleaseRequest: '%s'\n", storeKeyText(e->key));    EBIT_SET(e->flags, RELEASE_REQUEST);    /*     * Clear cachable flag here because we might get called before     * anyone else even looks at the cachability flag.  Also, this     * prevents httpMakePublic from really setting a public key.     */    EBIT_CLR(e->flags, ENTRY_CACHABLE);    storeSetPrivateKey(e);}/* unlock object, return -1 if object get released after unlock * otherwise lock_count */intstoreUnlockObject(StoreEntry * e){    e->lock_count--;    debug(20, 3) ("storeUnlockObject: key '%s' count=%d\n",	storeKeyText(e->key), e->lock_count);    if (e->lock_count)	return (int) e->lock_count;    if (e->store_status == STORE_PENDING)	EBIT_SET(e->flags, RELEASE_REQUEST);    assert(storePendingNClients(e) == 0);    if (EBIT_TEST(e->flags, RELEASE_REQUEST))	storeRelease(e);    else if (storeKeepInMemory(e)) {	storeSetMemStatus(e, IN_MEMORY);	requestUnlink(e->mem_obj->request);	e->mem_obj->request = NULL;    } else {	storePurgeMem(e);	if (EBIT_TEST(e->flags, KEY_PRIVATE)) {	    dlinkDelete(&e->lru, &store_list);	    dlinkAddTail(e, &e->lru, &store_list);	}    }    return 0;}/* Lookup an object in the cache.  * return just a reference to object, don't start swapping in yet. */StoreEntry *storeGet(const cache_key * key){    debug(20, 3) ("storeGet: looking up %s\n", storeKeyText(key));    return (StoreEntry *) hash_lookup(store_table, key);}StoreEntry *storeGetPublic(const char *uri, const method_t method){    return storeGet(storeKeyPublic(uri, method));}static intgetKeyCounter(void){    static int key_counter = 0;    if (++key_counter < 0)	key_counter = 1;    return key_counter;}voidstoreSetPrivateKey(StoreEntry * e){    const cache_key *newkey;    MemObject *mem = e->mem_obj;    if (e->key && EBIT_TEST(e->flags, KEY_PRIVATE))	return;			/* is already private */    if (e->key) {	if (e->swap_file_number > -1)	    storeDirSwapLog(e, SWAP_LOG_DEL);	storeHashDelete(e);    }    if (mem != NULL) {	mem->id = getKeyCounter();	newkey = storeKeyPrivate(mem->url, mem->method, mem->id);    } else {	newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());    }    assert(hash_lookup(store_table, newkey) == NULL);    EBIT_SET(e->flags, KEY_PRIVATE);    storeHashInsert(e, newkey);}voidstoreSetPublicKey(StoreEntry * e){    StoreEntry *e2 = NULL;    const cache_key *newkey;    MemObject *mem = e->mem_obj;    if (e->key && !EBIT_TEST(e->flags, KEY_PRIVATE))	return;			/* is already public */    assert(mem);    /*     * We can't make RELEASE_REQUEST objects public.  Depending on     * when RELEASE_REQUEST gets set, we might not be swapping out     * the object.  If we're not swapping out, then subsequent     * store clients won't be able to access object data which has     * been freed from memory.     *     * If RELEASE_REQUEST is set, then ENTRY_CACHABLE should not     * be set, and storeSetPublicKey() should not be called.     */    assert(!EBIT_TEST(e->flags, RELEASE_REQUEST));    newkey = storeKeyPublic(mem->url, mem->method);    if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) {	debug(20, 3) ("storeSetPublicKey: Making old '%s' private.\n", mem->url);	storeSetPrivateKey(e2);	storeRelease(e2);	newkey = storeKeyPublic(mem->url, mem->method);    }    if (e->key)	storeHashDelete(e);    EBIT_CLR(e->flags, KEY_PRIVATE);    storeHashInsert(e, newkey);    if (e->swap_file_number > -1)	storeDirSwapLog(e, SWAP_LOG_ADD);}StoreEntry *storeCreateEntry(const char *url, const char *log_url, request_flags flags, method_t method){    StoreEntry *e = NULL;    MemObject *mem = NULL;    debug(20, 3) ("storeCreateEntry: '%s'\n", url);    e = new_StoreEntry(STORE_ENTRY_WITH_MEMOBJ, url, log_url);    e->lock_count = 1;		/* Note lock here w/o calling storeLock() */    mem = e->mem_obj;    mem->method = method;    if (neighbors_do_private_keys || !flags.hierarchical)	storeSetPrivateKey(e);    else	storeSetPublicKey(e);    if (flags.cachable) {	EBIT_SET(e->flags, ENTRY_CACHABLE);	EBIT_CLR(e->flags, RELEASE_REQUEST);    } else {	EBIT_CLR(e->flags, ENTRY_CACHABLE);	storeReleaseRequest(e);    }    e->store_status = STORE_PENDING;    storeSetMemStatus(e, NOT_IN_MEMORY);    e->swap_status = SWAPOUT_NONE;    e->swap_file_number = -1;    e->refcount = 0;    e->lastref = squid_curtime;    e->timestamp = 0;		/* set in storeTimestampsSet() */    e->ping_status = PING_NONE;    EBIT_SET(e->flags, ENTRY_VALIDATED);    return e;}/* Mark object as expired */voidstoreExpireNow(StoreEntry * e){    debug(20, 3) ("storeExpireNow: '%s'\n", storeKeyText(e->key));    e->expires = squid_curtime;}/* Append incoming data from a primary server to an entry. */voidstoreAppend(StoreEntry * e, const char *buf, int len){    MemObject *mem = e->mem_obj;    assert(mem != NULL);    assert(len >= 0);    assert(e->store_status == STORE_PENDING);    if (len) {	debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n",	    len,	    storeKeyText(e->key));	storeGetMemSpace(len);	stmemAppend(&mem->data_hdr, buf, len);	mem->inmem_hi += len;    }    if (EBIT_TEST(e->flags, DELAY_SENDING))	return;#ifdef OPTIMISTIC_IO    storeLockObject(e);#endif    InvokeHandlers(e);    storeCheckSwapOut(e);#ifdef OPTIMISTIC_IO

⌨️ 快捷键说明

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