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

📄 store_rebuild.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: store_rebuild.c,v 1.56.2.1 1999/04/27 21:54:24 wessels Exp $ * * DEBUG: section 20    Store Rebuild Routines * 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"#define STORE_META_BUFSZ 4096typedef struct _rebuild_dir rebuild_dir;typedef int RBHD(rebuild_dir * d);struct _rebuild_dir {    int dirn;    int n_read;    FILE *log;    int speed;    int clean;    int curlvl1;    int curlvl2;    int flag;    int done;    int in_dir;    int fn;    struct dirent *entry;    DIR *td;    RBHD *rebuild_func;    rebuild_dir *next;    char fullpath[SQUID_MAXPATHLEN];    char fullfilename[SQUID_MAXPATHLEN];};struct storeRebuildState {    rebuild_dir *rebuild_dir;    int objcount;		/* # objects successfully reloaded */    int expcount;		/* # objects expired */    int linecount;		/* # lines parsed from cache logfile */    int statcount;		/* # entries from directory walking */    int clashcount;		/* # swapfile clashes avoided */    int dupcount;		/* # duplicates purged */    int cancelcount;		/* # SWAP_LOG_DEL objects purged */    int invalid;		/* # bad lines */    int badflags;		/* # bad e->flags */    int need_to_validate;    int bad_log_op;    int zero_object_sz;    time_t start;    time_t stop;} RebuildState;typedef struct valid_ctrl_t {    struct stat *sb;    StoreEntry *e;    STVLDCB *callback;    void *callback_data;} valid_ctrl_t;static RBHD storeRebuildFromDirectory;static RBHD storeRebuildFromSwapLog;static void storeRebuildComplete(void);static EVH storeRebuildADirectory;static int storeGetNextFile(rebuild_dir *, int *sfileno, int *size);static StoreEntry *storeAddDiskRestore(const cache_key * key,    int file_number,    size_t swap_file_sz,    time_t expires,    time_t timestamp,    time_t lastref,    time_t lastmod,    u_num32 refcount,    u_short flags,    int clean);static AIOCB storeValidateComplete;static intstoreRebuildFromDirectory(rebuild_dir * d){    LOCAL_ARRAY(char, hdr_buf, DISK_PAGE_SIZE);    StoreEntry *e = NULL;    StoreEntry tmpe;    cache_key key[MD5_DIGEST_CHARS];    int sfileno = 0;    int count;    int size;    struct stat sb;    int swap_hdr_len;    int fd = -1;    tlv *tlv_list;    tlv *t;    assert(d != NULL);    debug(20, 3) ("storeRebuildFromDirectory: DIR #%d\n", d->dirn);    for (count = 0; count < d->speed; count++) {	assert(fd == -1);	fd = storeGetNextFile(d, &sfileno, &size);	if (fd == -2) {	    debug(20, 1) ("storeRebuildFromDirectory: DIR #%d done!\n", d->dirn);	    storeDirCloseTmpSwapLog(d->dirn);	    store_rebuilding = 0;	    return -1;	} else if (fd < 0) {	    continue;	}	assert(fd > -1);	/* lets get file stats here */	if (fstat(fd, &sb) < 0) {	    debug(20, 1) ("storeRebuildFromDirectory: fstat(FD %d): %s\n",		fd, xstrerror());	    file_close(fd);	    store_open_disk_fd--;	    fd = -1;	    continue;	}	if ((++RebuildState.statcount & 0xFFFF) == 0)	    debug(20, 1) ("  %7d files opened so far.\n",		RebuildState.statcount);	debug(20, 9) ("file_in: fd=%d %08X\n", fd, sfileno);	Counter.syscalls.disk.reads++;	if (read(fd, hdr_buf, DISK_PAGE_SIZE) < 0) {	    debug(20, 1) ("storeRebuildFromDirectory: read(FD %d): %s\n",		fd, xstrerror());	    file_close(fd);	    store_open_disk_fd--;	    fd = -1;	    continue;	}	file_close(fd);	store_open_disk_fd--;	fd = -1;	swap_hdr_len = 0;#if USE_TRUNCATE_NOT_UNLINK	if (sb.st_size == 0)	    continue;#endif	tlv_list = storeSwapMetaUnpack(hdr_buf, &swap_hdr_len);	if (tlv_list == NULL) {	    debug(20, 1) ("storeRebuildFromDirectory: failed to get meta data\n");	    storeUnlinkFileno(sfileno);	    continue;	}	debug(20, 3) ("storeRebuildFromDirectory: successful swap meta unpacking\n");	memset(key, '\0', MD5_DIGEST_CHARS);	memset(&tmpe, '\0', sizeof(StoreEntry));	for (t = tlv_list; t; t = t->next) {	    switch (t->type) {	    case STORE_META_KEY:		assert(t->length == MD5_DIGEST_CHARS);		xmemcpy(key, t->value, MD5_DIGEST_CHARS);		break;	    case STORE_META_STD:		assert(t->length == STORE_HDR_METASIZE);		xmemcpy(&tmpe.timestamp, t->value, STORE_HDR_METASIZE);		break;	    default:		break;	    }	}	storeSwapTLVFree(tlv_list);	tlv_list = NULL;	if (storeKeyNull(key)) {	    debug(20, 1) ("storeRebuildFromDirectory: NULL key\n");	    storeUnlinkFileno(sfileno);	    continue;	}	tmpe.key = key;	/* check sizes */	if (tmpe.swap_file_sz == 0) {	    tmpe.swap_file_sz = sb.st_size;	} else if (tmpe.swap_file_sz == sb.st_size - swap_hdr_len) {	    tmpe.swap_file_sz = sb.st_size;	} else if (tmpe.swap_file_sz != sb.st_size) {	    debug(20, 1) ("storeRebuildFromDirectory: SIZE MISMATCH %d!=%d\n",		tmpe.swap_file_sz, (int) sb.st_size);	    storeUnlinkFileno(sfileno);	    continue;	}	if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) {	    storeUnlinkFileno(sfileno);	    RebuildState.badflags++;	    continue;	}	e = storeGet(key);	if (e && e->lastref >= tmpe.lastref) {	    /* key already exists, current entry is newer */	    /* keep old, ignore new */	    RebuildState.dupcount++;	    continue;	} else if (NULL != e) {	    /* URL already exists, this swapfile not being used */	    /* junk old, load new */	    storeRelease(e);	/* release old entry */	    RebuildState.dupcount++;	}	RebuildState.objcount++;	storeEntryDump(&tmpe, 5);	e = storeAddDiskRestore(key,	    sfileno,	    tmpe.swap_file_sz,	    tmpe.expires,	    tmpe.timestamp,	    tmpe.lastref,	    tmpe.lastmod,	    tmpe.refcount,	/* refcount */	    tmpe.flags,		/* flags */	    d->clean);    }    return count;}static intstoreRebuildFromSwapLog(rebuild_dir * d){    StoreEntry *e = NULL;    storeSwapLogData s;    size_t ss = sizeof(storeSwapLogData);    int count;    int used;			/* is swapfile already in use? */    int disk_entry_newer;	/* is the log entry newer than current entry? */    double x;    assert(d != NULL);    /* load a number of objects per invocation */    for (count = 0; count < d->speed; count++) {	if (fread(&s, ss, 1, d->log) != 1) {	    debug(20, 1) ("Done reading Cache Dir #%d swaplog (%d entries)\n",		d->dirn, d->n_read);	    fclose(d->log);	    d->log = NULL;	    storeDirCloseTmpSwapLog(d->dirn);	    return -1;	}	d->n_read++;	if (s.op <= SWAP_LOG_NOP)	    continue;	if (s.op >= SWAP_LOG_MAX)	    continue;	s.swap_file_number = storeDirProperFileno(d->dirn, s.swap_file_number);	debug(20, 3) ("storeRebuildFromSwapLog: %s %s %08X\n",	    swap_log_op_str[(int) s.op],	    storeKeyText(s.key),	    s.swap_file_number);	if (s.op == SWAP_LOG_ADD) {	    (void) 0;	} else if (s.op == SWAP_LOG_DEL) {	    if ((e = storeGet(s.key)) != NULL) {		/*		 * Make sure we don't unlink the file, it might be		 * in use by a subsequent entry.  Also note that		 * we don't have to subtract from store_swap_size		 * because adding to store_swap_size happens in		 * the cleanup procedure.		 */		storeExpireNow(e);		storeReleaseRequest(e);		if (e->swap_file_number > -1) {		    storeDirMapBitReset(e->swap_file_number);		    e->swap_file_number = -1;		}		RebuildState.objcount--;		RebuildState.cancelcount++;	    }	    continue;	} else {	    x = log(++RebuildState.bad_log_op) / log(10.0);	    if (0.0 == x - (double) (int) x)		debug(20, 1) ("WARNING: %d invalid swap log entries found\n",		    RebuildState.bad_log_op);	    RebuildState.invalid++;	    continue;	}	if ((++RebuildState.linecount & 0xFFFF) == 0)	    debug(20, 1) ("  %7d Entries read so far.\n",		RebuildState.linecount);	if (!storeDirValidFileno(s.swap_file_number)) {	    RebuildState.invalid++;	    continue;	}	if (EBIT_TEST(s.flags, KEY_PRIVATE)) {	    RebuildState.badflags++;	    continue;	}	e = storeGet(s.key);	used = storeDirMapBitTest(s.swap_file_number);	/* If this URL already exists in the cache, does the swap log	 * appear to have a newer entry?  Compare 'lastref' from the	 * swap log to e->lastref. */	disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;	if (used && !disk_entry_newer) {	    /* log entry is old, ignore it */	    RebuildState.clashcount++;	    continue;	} else if (used && e && e->swap_file_number == s.swap_file_number) {	    /* swapfile taken, same URL, newer, update meta */	    if (e->store_status == STORE_OK) {		e->lastref = s.timestamp;		e->timestamp = s.timestamp;		e->expires = s.expires;		e->lastmod = s.lastmod;		e->flags = s.flags;		e->refcount += s.refcount;	    } else {		debug_trap("storeRebuildFromSwapLog: bad condition");		debug(20, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);	    }	    continue;	} else if (used) {	    /* swapfile in use, not by this URL, log entry is newer */	    /* This is sorta bad: the log entry should NOT be newer at this	     * point.  If the log is dirty, the filesize check should have	     * caught this.  If the log is clean, there should never be a	     * newer entry. */	    debug(20, 1) ("WARNING: newer swaplog entry for fileno %08X\n",		s.swap_file_number);	    /* I'm tempted to remove the swapfile here just to be safe,	     * but there is a bad race condition in the NOVM version if	     * the swapfile has recently been opened for writing, but	     * not yet opened for reading.  Because we can't map	     * swapfiles back to StoreEntrys, we don't know the state	     * of the entry using that file.  */	    /* We'll assume the existing entry is valid, probably because	     * were in a slow rebuild and the the swap file number got taken	     * and the validation procedure hasn't run. */	    assert(RebuildState.need_to_validate);	    RebuildState.clashcount++;	    continue;	} else if (e && !disk_entry_newer) {	    /* key already exists, current entry is newer */	    /* keep old, ignore new */	    RebuildState.dupcount++;	    continue;	} else if (e) {	    /* key already exists, this swapfile not being used */	    /* junk old, load new */	    storeExpireNow(e);	    storeReleaseRequest(e);	    if (e->swap_file_number > -1) {		storeDirMapBitReset(e->swap_file_number);		e->swap_file_number = -1;	    }	    RebuildState.dupcount++;	} else {	    /* URL doesnt exist, swapfile not in use */	    /* load new */	    (void) 0;	}	/* update store_swap_size */	RebuildState.objcount++;	e = storeAddDiskRestore(s.key,	    s.swap_file_number,	    s.swap_file_sz,	    s.expires,	    s.timestamp,	    s.lastref,	    s.lastmod,	    s.refcount,	    s.flags,	    d->clean);	storeDirSwapLog(e, SWAP_LOG_ADD);    }    return count;}

⌨️ 快捷键说明

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