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

📄 store_swapout.c

📁 -
💻 C
字号:
/* * $Id: store_swapout.c,v 1.46 1999/01/29 17:36:37 wessels Exp $ * * DEBUG: section 20    Storage Manager Swapout Functions * AUTHOR: Duane Wessels * * 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"typedef struct swapout_ctrl_t {    char *swapfilename;    int oldswapstatus;    StoreEntry *e;} swapout_ctrl_t;static FOCB storeSwapOutFileOpened;static off_t storeSwapOutObjectBytesOnDisk(const MemObject *);static void storeSwapOutStart(StoreEntry * e);static DWCB storeSwapOutHandle;/* start swapping object to disk */static voidstoreSwapOutStart(StoreEntry * e){    swapout_ctrl_t *ctrlp = xmalloc(sizeof(swapout_ctrl_t));    assert(e->mem_obj);    cbdataAdd(ctrlp, cbdataXfree, 0);    storeLockObject(e);    e->swap_file_number = storeDirMapAllocate();    ctrlp->swapfilename = xstrdup(storeSwapFullPath(e->swap_file_number, NULL));    ctrlp->e = e;    ctrlp->oldswapstatus = e->swap_status;    e->swap_status = SWAPOUT_OPENING;    e->mem_obj->swapout.ctrl = ctrlp;    store_open_disk_fd++;    file_open(ctrlp->swapfilename,	O_WRONLY | O_CREAT | O_TRUNC,	storeSwapOutFileOpened,	ctrlp,	e);}static voidstoreSwapOutHandle(int fdnotused, int flag, size_t len, void *data){    swapout_ctrl_t *ctrlp = data;    StoreEntry *e = ctrlp->e;    MemObject *mem = e->mem_obj;    debug(20, 3) ("storeSwapOutHandle: '%s', len=%d\n", storeKeyText(e->key), (int) len);    if (flag < 0) {	debug(20, 1) ("storeSwapOutHandle: SwapOut failure (err code = %d).\n",	    flag);	e->swap_status = SWAPOUT_NONE;	if (e->swap_file_number > -1) {	    storeUnlinkFileno(e->swap_file_number);	    storeDirMapBitReset(e->swap_file_number);	    if (flag == DISK_NO_SPACE_LEFT) {		storeDirDiskFull(e->swap_file_number);		storeDirConfigure();		storeConfigure();	    }	    e->swap_file_number = -1;	}	storeReleaseRequest(e);	storeSwapOutFileClose(e);	return;    }#if USE_ASYNC_IO    if (mem == NULL) {	debug(20, 1) ("storeSwapOutHandle: mem == NULL : Cancelling swapout\n");	return;    }#else    assert(mem != NULL);#endif    assert(mem->swap_hdr_sz != 0);    mem->swapout.done_offset += len;    if (e->store_status == STORE_PENDING) {	storeCheckSwapOut(e);	return;    } else if (mem->swapout.done_offset < objectLen(e) + mem->swap_hdr_sz) {	storeCheckSwapOut(e);	return;    }    /* swapping complete */    debug(20, 5) ("storeSwapOutHandle: SwapOut complete: '%s' to %s.\n",	storeUrl(e), storeSwapFullPath(e->swap_file_number, NULL));    e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;    e->swap_status = SWAPOUT_DONE;    storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);    if (storeCheckCachable(e)) {	storeLog(STORE_LOG_SWAPOUT, e);	storeDirSwapLog(e, SWAP_LOG_ADD);    }    /* Note, we don't otherwise call storeReleaseRequest() here because     * storeCheckCachable() does it for is if necessary */    storeSwapOutFileClose(e);}voidstoreCheckSwapOut(StoreEntry * e){    MemObject *mem = e->mem_obj;    off_t lowest_offset;    off_t new_mem_lo;    off_t on_disk;    size_t swapout_size;    char *swap_buf;    ssize_t swap_buf_len;    int hdr_len = 0;    if (mem == NULL)	return;    /* should we swap something out to disk? */    debug(20, 7) ("storeCheckSwapOut: %s\n", storeUrl(e));    debug(20, 7) ("storeCheckSwapOut: store_status = %s\n",	storeStatusStr[e->store_status]);    if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {	assert(EBIT_TEST(e->flags, RELEASE_REQUEST));	storeSwapOutFileClose(e);	return;    }    debug(20, 7) ("storeCheckSwapOut: mem->inmem_lo = %d\n",	(int) mem->inmem_lo);    debug(20, 7) ("storeCheckSwapOut: mem->inmem_hi = %d\n",	(int) mem->inmem_hi);    debug(20, 7) ("storeCheckSwapOut: swapout.queue_offset = %d\n",	(int) mem->swapout.queue_offset);    debug(20, 7) ("storeCheckSwapOut: swapout.done_offset = %d\n",	(int) mem->swapout.done_offset);#if USE_ASYNC_IO    if (mem->inmem_hi < mem->swapout.queue_offset) {	storeAbort(e);	assert(EBIT_TEST(e->flags, RELEASE_REQUEST));	storeSwapOutFileClose(e);	return;    }#else    assert(mem->inmem_hi >= mem->swapout.queue_offset);#endif    lowest_offset = storeLowestMemReaderOffset(e);    debug(20, 7) ("storeCheckSwapOut: lowest_offset = %d\n",	(int) lowest_offset);    new_mem_lo = lowest_offset;    assert(new_mem_lo >= mem->inmem_lo);    /*     * We should only free up to what we know has been written to     * disk, not what has been queued for writing.  Otherwise there     * will be a chunk of the data which is not in memory and is     * not yet on disk.     */    if (storeSwapOutAble(e))	if ((on_disk = storeSwapOutObjectBytesOnDisk(mem)) < new_mem_lo)	    new_mem_lo = on_disk;    stmemFreeDataUpto(&mem->data_hdr, new_mem_lo);    mem->inmem_lo = new_mem_lo;    if (e->swap_status == SWAPOUT_WRITING)	assert(mem->inmem_lo <= mem->swapout.done_offset);    if (!storeSwapOutAble(e))	return;    swapout_size = (size_t) (mem->inmem_hi - mem->swapout.queue_offset);    debug(20, 7) ("storeCheckSwapOut: swapout_size = %d\n",	(int) swapout_size);    if (swapout_size == 0) {	if (e->store_status == STORE_OK && !storeSwapOutWriteQueued(mem)) {	    debug(20, 7) ("storeCheckSwapOut: nothing to write for STORE_OK\n");	    if (e->swap_file_number > -1) {		storeUnlinkFileno(e->swap_file_number);		storeDirMapBitReset(e->swap_file_number);		e->swap_file_number = -1;	    }	    e->swap_status = SWAPOUT_NONE;	    storeReleaseRequest(e);	    storeSwapOutFileClose(e);	}	return;    }    if (e->store_status == STORE_PENDING) {	/* wait for a full block to write */	if (swapout_size < VM_WINDOW_SZ)	    return;	/*	 * Wait until we are below the disk FD limit, only if the	 * next server-side read won't be deferred.	 */	if (storeTooManyDiskFilesOpen() && !fwdCheckDeferRead(-1, e))	    return;    }    /* Ok, we have stuff to swap out.  Is there a swapout.fd open? */    if (e->swap_status == SWAPOUT_NONE) {	assert(mem->swapout.fd == -1);	assert(mem->inmem_lo == 0);	if (storeCheckCachable(e))	    storeSwapOutStart(e);	/* else ENTRY_CACHABLE will be cleared and we'll never get	 * here again */	return;    }    if (e->swap_status == SWAPOUT_OPENING)	return;    assert(mem->swapout.fd > -1);    if (swapout_size > STORE_SWAP_BUF)	swapout_size = STORE_SWAP_BUF;    swap_buf = memAllocate(MEM_DISK_BUF);    swap_buf_len = stmemCopy(&mem->data_hdr,	mem->swapout.queue_offset,	swap_buf,	swapout_size);    if (swap_buf_len < 0) {	debug(20, 1) ("stmemCopy returned %d for '%s'\n", swap_buf_len, storeKeyText(e->key));	storeUnlinkFileno(e->swap_file_number);	storeDirMapBitReset(e->swap_file_number);	e->swap_file_number = -1;	e->swap_status = SWAPOUT_NONE;	memFree(swap_buf, MEM_DISK_BUF);	storeReleaseRequest(e);	storeSwapOutFileClose(e);	return;    }    debug(20, 3) ("storeCheckSwapOut: swap_buf_len = %d\n", (int) swap_buf_len);    assert(swap_buf_len > 0);    debug(20, 3) ("storeCheckSwapOut: swapping out %d bytes from %d\n",	swap_buf_len, (int) mem->swapout.queue_offset);    mem->swapout.queue_offset += swap_buf_len - hdr_len;    file_write(mem->swapout.fd,	-1,	swap_buf,	swap_buf_len,	storeSwapOutHandle,	mem->swapout.ctrl,	memFreeDISK);}voidstoreSwapOutFileClose(StoreEntry * e){    MemObject *mem = e->mem_obj;    swapout_ctrl_t *ctrlp;    assert(mem != NULL);    debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->key));    if (mem->swapout.fd < 0) {#if USE_ASYNC_IO	aioCancel(-1, e);	/* Make doubly certain pending ops are gone */#endif	return;    }    ctrlp = mem->swapout.ctrl;    file_close(mem->swapout.fd);    store_open_disk_fd--;    mem->swapout.fd = -1;    xfree(ctrlp->swapfilename);    cbdataFree(ctrlp);    mem->swapout.ctrl = NULL;    storeUnlockObject(e);}static voidstoreSwapOutFileOpened(void *data, int fd, int errcode){    swapout_ctrl_t *ctrlp = data;    StoreEntry *e = ctrlp->e;    MemObject *mem = e->mem_obj;    int swap_hdr_sz = 0;    tlv *tlv_list;    char *buf;    if (fd == -2 && errcode == -2) {	/* Cancelled - Clean up */	xfree(ctrlp->swapfilename);	cbdataFree(ctrlp);	mem->swapout.ctrl = NULL;	store_open_disk_fd--;	return;    }    assert(e->swap_status == SWAPOUT_OPENING);    if (fd < 0) {	debug(20, 0) ("storeSwapOutFileOpened: Unable to open swapfile: %s\n\t%s\n",	    ctrlp->swapfilename, xstrerror());	/*	 * yuck.  don't clear the filemap bit for some errors so that	 * we don't try re-using it over and over	 */	if (errno != EPERM)	    storeDirMapBitReset(e->swap_file_number);	e->swap_file_number = -1;	e->swap_status = ctrlp->oldswapstatus;	xfree(ctrlp->swapfilename);	cbdataFree(ctrlp);	mem->swapout.ctrl = NULL;	store_open_disk_fd--;	return;    }    mem->swapout.fd = (short) fd;    e->swap_status = SWAPOUT_WRITING;    debug(20, 5) ("storeSwapOutFileOpened: Begin SwapOut '%s' to FD %d '%s'\n",	storeUrl(e), fd, ctrlp->swapfilename);    debug(20, 5) ("swap_file_number=%08X\n", e->swap_file_number);    tlv_list = storeSwapMetaBuild(e);    buf = storeSwapMetaPack(tlv_list, &swap_hdr_sz);    storeSwapTLVFree(tlv_list);    mem->swap_hdr_sz = (size_t) swap_hdr_sz;    file_write(mem->swapout.fd,	-1,	buf,	mem->swap_hdr_sz,	storeSwapOutHandle,	ctrlp,	xfree);}/* * Return 1 if we have some data queued.  If there is no data queued, * then 'done_offset' equals 'queued_offset' + 'swap_hdr_sz' * * done_offset represents data written to disk (including the swap meta * header), but queued_offset is relative to the in-memory data, and * does not include the meta header. */intstoreSwapOutWriteQueued(MemObject * mem){    /*     * this function doesn't get called much, so I'm using     * local variables to improve readability.  pphhbbht.     */    off_t queued = mem->swapout.queue_offset;    off_t done = mem->swapout.done_offset;    size_t hdr = mem->swap_hdr_sz;    assert(queued + hdr >= done);    return (queued + hdr > done);}/* * How much of the object data is on the disk? */static off_tstoreSwapOutObjectBytesOnDisk(const MemObject * mem){    /*     * NOTE: done_offset represents the disk file size,     * not the amount of object data on disk.     *      * If we don't have at least 'swap_hdr_sz' bytes     * then none of the object data is on disk.     *     * This should still be safe if swap_hdr_sz == 0,     * meaning we haven't even opened the swapout file     * yet.     */    if (mem->swapout.done_offset <= mem->swap_hdr_sz)	return 0;    return mem->swapout.done_offset - mem->swap_hdr_sz;}/* * Is this entry a candidate for writing to disk? */intstoreSwapOutAble(const StoreEntry * e){    store_client *sc;    if (e->swap_status == SWAPOUT_OPENING)	return 1;    if (e->mem_obj->swapout.fd > -1)	return 1;    if (e->mem_obj->inmem_lo > 0)	return 0;    /* swapout.fd == -1 && inmem_lo == 0 */    /*     * If there are DISK clients, we must write to disk     * even if its not cachable     */    for (sc = e->mem_obj->clients; sc; sc = sc->next)	if (sc->type == STORE_DISK_CLIENT)	    return 1;    return EBIT_TEST(e->flags, ENTRY_CACHABLE);}

⌨️ 快捷键说明

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