📄 store_rebuild.c
字号:
/* * $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 + -