From: wessels <> Date: Tue, 25 May 1999 12:53:40 +0000 (+0000) Subject: massive store filesystem reorganization. Removing hard-coded hooks X-Git-Tag: SQUID_3_0_PRE1~2184 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2c141d4440ca2ba7c37fee43c9875a4049317a6;p=thirdparty%2Fsquid.git massive store filesystem reorganization. Removing hard-coded hooks for UFS storage and using function pointers instead. Yummmm... --- diff --git a/src/dns.cc b/src/dns.cc index 60853f17b4..3b074cc859 100644 --- a/src/dns.cc +++ b/src/dns.cc @@ -1,6 +1,6 @@ /* - * $Id: dns.cc,v 1.76 1999/05/19 21:55:51 wessels Exp $ + * $Id: dns.cc,v 1.77 1999/05/25 06:53:40 wessels Exp $ * * DEBUG: section 34 Dnsserver interface * AUTHOR: Harvest Derived @@ -44,6 +44,7 @@ dnsStats(StoreEntry * sentry) storeAppendPrintf(sentry, "Dnsserver Statistics:\n"); helperStats(sentry, dnsservers); } + #endif void diff --git a/src/globals.h b/src/globals.h index 570bd83b0c..021e19d73b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.81 1999/05/22 07:42:04 wessels Exp $ + * $Id: globals.h,v 1.82 1999/05/25 06:53:41 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -118,7 +118,7 @@ extern struct timeval squid_start; extern time_t squid_curtime; /* 0 */ extern int shutting_down; /* 0 */ extern int reconfiguring; /* 0 */ -extern int store_rebuilding; /* 1 */ +extern int store_dirs_rebuilding; /* 0 */ extern int store_swap_size; /* 0 */ extern unsigned long store_mem_size; /* 0 */ extern time_t hit_only_mode_until; /* 0 */ diff --git a/src/icp_v2.cc b/src/icp_v2.cc index 6b16c821ee..e887f93d6a 100644 --- a/src/icp_v2.cc +++ b/src/icp_v2.cc @@ -1,6 +1,6 @@ /* - * $Id: icp_v2.cc,v 1.58 1999/01/29 21:28:13 wessels Exp $ + * $Id: icp_v2.cc,v 1.59 1999/05/25 06:53:42 wessels Exp $ * * DEBUG: section 12 Internet Cache Protocol * AUTHOR: Duane Wessels @@ -256,7 +256,7 @@ icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) netdbPingSite(icp_request->host); } /* if store is rebuilding, return a UDP_HIT, but not a MISS */ - if (store_rebuilding && opt_reload_hit_only) { + if (store_dirs_rebuilding && opt_reload_hit_only) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (hit_only_mode_until > squid_curtime) { diff --git a/src/icp_v3.cc b/src/icp_v3.cc index 4213a9a9fa..6033e63c11 100644 --- a/src/icp_v3.cc +++ b/src/icp_v3.cc @@ -1,6 +1,6 @@ /* - * $Id: icp_v3.cc,v 1.28 1999/01/29 21:28:14 wessels Exp $ + * $Id: icp_v3.cc,v 1.29 1999/05/25 06:53:43 wessels Exp $ * * DEBUG: section 12 Internet Cache Protocol * AUTHOR: Duane Wessels @@ -100,7 +100,7 @@ icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len) break; } /* if store is rebuilding, return a UDP_HIT, but not a MISS */ - if (opt_reload_hit_only && store_rebuilding) { + if (opt_reload_hit_only && store_dirs_rebuilding) { reply = icpCreateMessage(ICP_MISS_NOFETCH, 0, url, header.reqnum, 0); icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (hit_only_mode_until > squid_curtime) { diff --git a/src/protos.h b/src/protos.h index 3840312f9b..36804f945f 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.330 1999/05/22 07:42:05 wessels Exp $ + * $Id: protos.h,v 1.331 1999/05/25 06:53:44 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -856,11 +856,11 @@ extern int storeTooManyDiskFilesOpen(void); extern void storeEntryReset(StoreEntry *); /* store_io.c */ -extern STOPEN storeOpen; -extern STCLOSE storeClose; -extern STREAD storeRead; -extern STWRITE storeWrite; -extern STUNLINK storeUnlink; +extern STOBJOPEN storeOpen; +extern STOBJCLOSE storeClose; +extern STOBJREAD storeRead; +extern STOBJWRITE storeWrite; +extern STOBJUNLINK storeUnlink; extern off_t storeOffset(storeIOState *); /* store_io_ufs.c */ @@ -940,17 +940,8 @@ extern void storeDirUpdateSwapSize(int fn, size_t size, int sign); /* * store_dir_ufs.c */ -extern FILE *storeUfsDirOpenTmpSwapLog(int dirn, int *clean, int *zero); extern OBJH storeUfsDirStats; -extern char *storeUfsDirSwapLogFile(int, const char *); -extern int storeUfsDirWriteCleanLogs(int reopen); extern int storeUfsFilenoBelongsHere(int, int, int, int); -extern void storeUfsCreateSwapDirectories(void); -extern void storeUfsDirCloseSwapLogs(void); -extern void storeUfsDirCloseTmpSwapLog(int dirn); -extern void storeUfsDirInit(void); -extern void storeUfsDirOpenSwapLogs(void); -extern void storeUfsDirSwapLog(const StoreEntry *, int op); extern void storeUfsDirParse(cacheSwap * swap); extern void storeUfsDirDump(StoreEntry * entry, const char *name, SwapDir * s); extern void storeUfsDirFree(SwapDir *); @@ -967,8 +958,8 @@ extern void storeSwapTLVFree(tlv * n); /* * store_rebuild.c */ -extern void storeDoRebuildFromSwapFiles(void *data); -extern void storeUfsRebuildStart(void); +extern void storeRebuildStart(void); +extern void storeRebuildComplete(struct _store_rebuild_data *); /* * store_swapin.c diff --git a/src/store.cc b/src/store.cc index 0f0043bc82..5962118c42 100644 --- a/src/store.cc +++ b/src/store.cc @@ -1,6 +1,6 @@ /* - * $Id: store.cc,v 1.501 1999/05/22 07:42:07 wessels Exp $ + * $Id: store.cc,v 1.502 1999/05/25 06:53:46 wessels Exp $ * * DEBUG: section 20 Storage Manager * AUTHOR: Harvest Derived @@ -637,7 +637,7 @@ storeGetMemSpace(int size) pages_needed = (size / SM_PAGE_SIZE) + 1; if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max) return; - if (store_rebuilding) + if (store_dirs_rebuilding) return; debug(20, 2) ("storeGetMemSpace: Starting, need %d pages\n", pages_needed); head = inmem_list.head; @@ -686,7 +686,7 @@ storeMaintainSwapSpace(void *datanotused) double f; static time_t last_warn_time = 0; /* We can't delete objects while rebuilding swap */ - if (store_rebuilding) { + if (store_dirs_rebuilding) { eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1); return; } else { @@ -753,7 +753,7 @@ storeRelease(StoreEntry * e) storeReleaseRequest(e); return; } - if (store_rebuilding) { + if (store_dirs_rebuilding) { storeSetPrivateKey(e); if (e->mem_obj) { storeSetMemStatus(e, NOT_IN_MEMORY); @@ -787,7 +787,7 @@ storeLateRelease(void *unused) StoreEntry *e; int i; static int n = 0; - if (store_rebuilding) { + if (store_dirs_rebuilding) { eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1); return; } @@ -898,6 +898,7 @@ storeInit(void) stackInit(&LateReleaseStack); eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1); storeDirInit(); + storeRebuildStart(); cachemgrRegister("storedir", "Store Directory Stats", storeDirStats, 0, 1); diff --git a/src/store_dir.cc b/src/store_dir.cc index a436b21ad7..d481b9e86a 100644 --- a/src/store_dir.cc +++ b/src/store_dir.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir.cc,v 1.92 1999/05/22 07:42:11 wessels Exp $ + * $Id: store_dir.cc,v 1.93 1999/05/25 06:53:48 wessels Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -44,19 +44,35 @@ const char *SwapDirType[] = void storeDirInit(void) { - storeUfsDirInit(); -} - -char * -storeSwapFullPath(sfileno f, char *buf) -{ - return storeUfsFullPath(f, buf); + int i; + SwapDir *sd; + for (i = 0; i < Config.cacheSwap.n_configured; i++) { + sd = &Config.cacheSwap.swapDirs[i]; + sd->init(sd); + } } void storeCreateSwapDirectories(void) { - storeUfsCreateSwapDirectories(); + int i; + SwapDir *sd; + pid_t pid; + int status; + for (i = 0; i < Config.cacheSwap.n_configured; i++) { + if (fork()) + continue; + sd = &Config.cacheSwap.swapDirs[i]; + sd->newfs(sd); + exit(0); + } + do { +#ifdef _SQUID_NEXT_ + pid = wait3(&status, WNOHANG, NULL); +#else + pid = waitpid(-1, &status, 0); +#endif + } while (pid > 0 || (pid < 0 && errno == EINTR)); } /* @@ -245,13 +261,7 @@ storeDirSwapLog(const StoreEntry * e, int op) swap_log_op_str[op], storeKeyText(e->key), e->swap_file_number); - storeUfsDirSwapLog(e, op); -} - -char * -storeDirSwapLogFile(int dirn, const char *ext) -{ - return storeUfsDirSwapLogFile(dirn, ext); + Config.cacheSwap.swapDirs[dirn].obj.log(e, op); } void @@ -280,7 +290,7 @@ storeDirStats(StoreEntry * sentry) storeAppendPrintf(sentry, "Current Capacity : %d%% used, %d%% free\n", percent((int) store_swap_size, (int) Config.Swap.maxSize), percent((int) (Config.Swap.maxSize - store_swap_size), (int) Config.Swap.maxSize)); - storeUfsDirStats(sentry); + storeUfsDirStats(sentry); /* XXX */ } int @@ -293,17 +303,6 @@ storeDirMapBitsInUse(void) return n; } -/* - * storeDirWriteCleanLogs - * - * Writes a "clean" swap log file from in-memory metadata. - */ -int -storeDirWriteCleanLogs(int reopen) -{ - return storeUfsDirWriteCleanLogs(reopen); -} - void storeDirConfigure(void) { @@ -344,17 +343,94 @@ storeDirDiskFull(int fn) void storeDirOpenSwapLogs(void) { - return storeUfsDirOpenSwapLogs(); + int dirn; + SwapDir *sd; + for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) { + sd = &Config.cacheSwap.swapDirs[dirn]; + sd->log.open(sd); + } } void storeDirCloseSwapLogs(void) { - return storeUfsDirCloseSwapLogs(); + int dirn; + SwapDir *sd; + for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) { + sd = &Config.cacheSwap.swapDirs[dirn]; + sd->log.close(sd); + } } -void -storeDirCloseTmpSwapLog(int dirn) +/* + * storeDirWriteCleanLogs + * + * Writes a "clean" swap log file from in-memory metadata. + */ +#define CLEAN_BUF_SZ 16384 +int +storeDirWriteCleanLogs(int reopen) { - return storeUfsDirCloseTmpSwapLog(dirn); + StoreEntry *e = NULL; + int n = 0; + time_t start, stop, r; + SwapDir *sd; + int dirn; + int N = Config.cacheSwap.n_configured; + dlink_node *m; + if (store_dirs_rebuilding) { + debug(20, 1) ("Not currently OK to rewrite swap log.\n"); + debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n"); + return 0; + } + debug(20, 1) ("storeDirWriteCleanLogs: Starting...\n"); + start = squid_curtime; + for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) { + sd = &Config.cacheSwap.swapDirs[dirn]; + if (sd->log.clean.open(sd) < 0) { + debug(20, 1) ("log.clean.open() failed for dir #%d\n", sd->index); + continue; + } + } + for (m = store_list.tail; m; m = m->prev) { + e = m->data; + if (e->swap_file_number < 0) + continue; + if (e->swap_status != SWAPOUT_DONE) + continue; + if (e->swap_file_sz <= 0) + continue; + if (EBIT_TEST(e->flags, RELEASE_REQUEST)) + continue; + if (EBIT_TEST(e->flags, KEY_PRIVATE)) + continue; + if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) + continue; + dirn = storeDirNumber(e->swap_file_number); + sd = &Config.cacheSwap.swapDirs[dirn]; + if (NULL == sd->log.clean.write) + continue; + sd->log.clean.write(e, sd->log.clean.state); + if ((++n & 0xFFFF) == 0) { + getCurrentTime(); + debug(20, 1) (" %7d entries written so far.\n", n); + } + } + /* flush */ + for (dirn = 0; dirn < N; dirn++) { + sd = &Config.cacheSwap.swapDirs[dirn]; + if (NULL == sd->log.clean.write) + continue; + sd->log.clean.write(NULL, sd); + } + if (reopen) + storeDirOpenSwapLogs(); + stop = squid_curtime; + r = stop - start; + debug(20, 1) (" Finished. Wrote %d entries.\n", n); + debug(20, 1) (" Took %d seconds (%6.1f entries/sec).\n", + r > 0 ? (int) r : 0, + (double) n / (r > 0 ? r : 1)); + return n; } +#undef CLEAN_BUF_SZ diff --git a/src/store_io.cc b/src/store_io.cc index 7a4720c5ed..359c4e38fd 100644 --- a/src/store_io.cc +++ b/src/store_io.cc @@ -7,7 +7,7 @@ storeOpen(sfileno f, mode_t mode, STIOCB * callback, void *callback_data) { SwapDir *SD = &Config.cacheSwap.swapDirs[f >> SWAP_DIR_SHIFT]; assert(mode == O_RDONLY || mode == O_WRONLY); - return SD->open(f, mode, callback, callback_data); + return SD->obj.open(f, mode, callback, callback_data); } void @@ -16,28 +16,28 @@ storeClose(storeIOState * sio) SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_file_number >> SWAP_DIR_SHIFT]; assert(!sio->flags.closing); sio->flags.closing = 1; - SD->close(sio); + SD->obj.close(sio); } void storeRead(storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) { SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_file_number >> SWAP_DIR_SHIFT]; - SD->read(sio, buf, size, offset, callback, callback_data); + SD->obj.read(sio, buf, size, offset, callback, callback_data); } void storeWrite(storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func) { SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_file_number >> SWAP_DIR_SHIFT]; - SD->write(sio, buf, size, offset, free_func); + SD->obj.write(sio, buf, size, offset, free_func); } void storeUnlink(sfileno f) { SwapDir *SD = &Config.cacheSwap.swapDirs[f >> SWAP_DIR_SHIFT]; - SD->unlink(f); + SD->obj.unlink(f); } off_t diff --git a/src/store_rebuild.cc b/src/store_rebuild.cc index d23ed5ab60..dad98fd768 100644 --- a/src/store_rebuild.cc +++ b/src/store_rebuild.cc @@ -1,6 +1,6 @@ /* - * $Id: store_rebuild.cc,v 1.61 1999/05/22 07:42:14 wessels Exp $ + * $Id: store_rebuild.cc,v 1.62 1999/05/25 06:53:51 wessels Exp $ * * DEBUG: section 20 Store Rebuild Routines * AUTHOR: Duane Wessels @@ -35,551 +35,9 @@ #include "squid.h" -#define STORE_META_BUFSZ 4096 - - -typedef 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 int -storeRebuildFromDirectory(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"); - storeUnlink(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"); - storeUnlink(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); - storeUnlink(sfileno); - continue; - } - if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) { - storeUnlink(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 int -storeRebuildFromSwapLog(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; -} - -static void -storeRebuildADirectory(void *unused) -{ - int count; - rebuild_dir *d; - rebuild_dir **D; - if ((d = RebuildState.rebuild_dir) == NULL) { - storeRebuildComplete(); - return; - } - count = d->rebuild_func(d); - RebuildState.rebuild_dir = d->next; - if (count < 0) { - xfree(d); - } else { - for (D = &RebuildState.rebuild_dir; *D; D = &(*D)->next); - *D = d; - d->next = NULL; - } - if (opt_foreground_rebuild) - storeRebuildADirectory(NULL); - else - eventAdd("storeRebuild", storeRebuildADirectory, NULL, 0.0, 1); -} - -#if TEMP_UNUSED_CODE -static void -storeConvertFile(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_short refcount, - u_short flags, - int clean) -{ - int fd_r, fd_w; - int hdr_len, x, y; - LOCAL_ARRAY(char, swapfilename, SQUID_MAXPATHLEN); - LOCAL_ARRAY(char, copybuf, DISK_PAGE_SIZE); - char *buf; - tlv *tlv_list; - StoreEntry e; - e.key = key; - e.swap_file_sz = swap_file_sz; - e.expires = expires; - e.lastref = lastref; - e.refcount = refcount; - e.flag = flags; - storeSwapFullPath(file_number, swapfilename); - fd_r = file_open(swapfilename, O_RDONLY, NULL, NULL, NULL); - if (fd_r < 0) - return; - safeunlink(swapfilename, 1); - fd_w = file_open(swapfilename, O_CREAT | O_WRONLY | O_TRUNC, NULL, NULL, NULL); - tlv_list = storeSwapMetaBuild(&e); - buf = storeSwapMetaPack(tlv_list, &hdr_len); - x = write(fd_w, buf, hdr_len); - while (x > 0) { - y = read(fd_r, copybuf, DISK_PAGE_SIZE); - x = write(fd_w, copybuf, y); - } - file_close(fd_r); - file_close(fd_w); - xfree(buf); - storeSwapTLVFree(tlv_list); -} -#endif - -static int -storeGetNextFile(rebuild_dir * d, int *sfileno, int *size) -{ - int fd = -1; - int used = 0; - debug(20, 3) ("storeGetNextFile: flag=%d, %d: /%02X/%02X\n", - d->flag, - d->dirn, - d->curlvl1, - d->curlvl2); - if (d->done) - return -2; - while (fd < 0 && d->done == 0) { - fd = -1; - if (0 == d->flag) { /* initialize, open first file */ - d->done = 0; - d->curlvl1 = 0; - d->curlvl2 = 0; - d->in_dir = 0; - d->flag = 1; - assert(Config.cacheSwap.n_configured > 0); - } - if (0 == d->in_dir) { /* we need to read in a new directory */ - snprintf(d->fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X", - Config.cacheSwap.swapDirs[d->dirn].path, - d->curlvl1, d->curlvl2); - if (d->flag && d->td != NULL) - closedir(d->td); - d->td = opendir(d->fullpath); - if (d->td == NULL) { - debug(50, 1) ("storeGetNextFile: opendir: %s: %s\n", - d->fullpath, xstrerror()); - } else { - d->entry = readdir(d->td); /* skip . and .. */ - d->entry = readdir(d->td); - if (d->entry == NULL && errno == ENOENT) - debug(20, 1) ("storeGetNextFile: directory does not exist!.\n"); - debug(20, 3) ("storeGetNextFile: Directory %s\n", d->fullpath); - } - } - if (d->td != NULL && (d->entry = readdir(d->td)) != NULL) { - d->in_dir++; - if (sscanf(d->entry->d_name, "%x", &d->fn) != 1) { - debug(20, 3) ("storeGetNextFile: invalid %s\n", - d->entry->d_name); - continue; - } - if (!storeUfsFilenoBelongsHere(d->fn, d->dirn, d->curlvl1, d->curlvl2)) { - debug(20, 3) ("storeGetNextFile: %08X does not belong in %d/%d/%d\n", - d->fn, d->dirn, d->curlvl1, d->curlvl2); - continue; - } - d->fn = storeDirProperFileno(d->dirn, d->fn); - used = storeDirMapBitTest(d->fn); - if (used) { - debug(20, 3) ("storeGetNextFile: Locked, continuing with next.\n"); - continue; - } - snprintf(d->fullfilename, SQUID_MAXPATHLEN, "%s/%s", - d->fullpath, d->entry->d_name); - debug(20, 3) ("storeGetNextFile: Opening %s\n", d->fullfilename); - fd = file_open(d->fullfilename, O_RDONLY, NULL, NULL, NULL); - if (fd < 0) - debug(50, 1) ("storeGetNextFile: %s: %s\n", d->fullfilename, xstrerror()); - continue; - store_open_disk_fd++; - } - d->in_dir = 0; - if (++d->curlvl2 < Config.cacheSwap.swapDirs[d->dirn].u.ufs.l2) - continue; - d->curlvl2 = 0; - if (++d->curlvl1 < Config.cacheSwap.swapDirs[d->dirn].u.ufs.l1) - continue; - d->curlvl1 = 0; - d->done = 1; - } - *sfileno = d->fn; - return fd; -} - -/* Add a new object to the cache with empty memory copy and pointer to disk - * use to rebuild store from disk. */ -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) -{ - StoreEntry *e = NULL; - debug(20, 5) ("StoreAddDiskRestore: %s, fileno=%08X\n", storeKeyText(key), file_number); - /* if you call this you'd better be sure file_number is not - * already in use! */ - e = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL); - e->store_status = STORE_OK; - storeSetMemStatus(e, NOT_IN_MEMORY); - e->swap_status = SWAPOUT_DONE; - e->swap_file_number = file_number; - e->swap_file_sz = swap_file_sz; - e->lock_count = 0; - e->refcount = 0; - e->lastref = lastref; - e->timestamp = timestamp; - e->expires = expires; - e->lastmod = lastmod; - e->refcount = refcount; - e->flags = flags; - EBIT_SET(e->flags, ENTRY_CACHABLE); - EBIT_CLR(e->flags, RELEASE_REQUEST); - EBIT_CLR(e->flags, KEY_PRIVATE); - e->ping_status = PING_NONE; - EBIT_CLR(e->flags, ENTRY_VALIDATED); - storeDirMapBitSet(e->swap_file_number); - storeHashInsert(e, key); /* do it after we clear KEY_PRIVATE */ - return e; -} +static struct _store_rebuild_data counts; +static struct timeval rebuild_start; +static void storeCleanup(void *); static void storeCleanup(void *datanotused) @@ -594,7 +52,6 @@ storeCleanup(void *datanotused) debug(20, 1) (" Completed Validation Procedure\n"); debug(20, 1) (" Validated %d Entries\n", validnum); debug(20, 1) (" store_swap_size = %dk\n", store_swap_size); - store_rebuilding = 0; if (opt_store_doublecheck) assert(store_errors == 0); if (store_digest) @@ -614,13 +71,21 @@ storeCleanup(void *datanotused) if (e->swap_file_number < 0) continue; if (opt_store_doublecheck) { + /* XXX too UFS specific */ struct stat sb; - if (stat(storeSwapFullPath(e->swap_file_number, NULL), &sb) < 0) { + int dirn = e->swap_file_number >> SWAP_DIR_SHIFT; + if (Config.cacheSwap.swapDirs[dirn].type == SWAPDIR_UFS) + (void) 0; + else if (Config.cacheSwap.swapDirs[dirn].type == SWAPDIR_UFS_ASYNC) + (void) 0; + else + continue; + if (stat(storeUfsFullPath(e->swap_file_number, NULL), &sb) < 0) { store_errors++; debug(20, 0) ("storeCleanup: MISSING SWAP FILE\n"); debug(20, 0) ("storeCleanup: FILENO %08X\n", e->swap_file_number); debug(20, 0) ("storeCleanup: PATH %s\n", - storeSwapFullPath(e->swap_file_number, NULL)); + storeUfsFullPath(e->swap_file_number, NULL)); storeEntryDump(e, 0); continue; } @@ -629,7 +94,7 @@ storeCleanup(void *datanotused) debug(20, 0) ("storeCleanup: SIZE MISMATCH\n"); debug(20, 0) ("storeCleanup: FILENO %08X\n", e->swap_file_number); debug(20, 0) ("storeCleanup: PATH %s\n", - storeSwapFullPath(e->swap_file_number, NULL)); + storeUfsFullPath(e->swap_file_number, NULL)); debug(20, 0) ("storeCleanup: ENTRY SIZE: %d, FILE SIZE: %d\n", e->swap_file_sz, (int) sb.st_size); storeEntryDump(e, 0); @@ -647,68 +112,58 @@ storeCleanup(void *datanotused) } /* meta data recreated from disk image in swap directory */ -static void -storeRebuildComplete(void) +void +storeRebuildComplete(struct _store_rebuild_data *dc) { - time_t r; - time_t stop; - stop = squid_curtime; - r = stop - RebuildState.start; - debug(20, 1) ("Finished rebuilding storage disk.\n"); - debug(20, 1) (" %7d Entries read from previous logfile.\n", - RebuildState.linecount); - debug(20, 1) (" %7d Entries scanned from swap files.\n", - RebuildState.statcount); - debug(20, 1) (" %7d Invalid entries.\n", RebuildState.invalid); - debug(20, 1) (" %7d With invalid flags.\n", RebuildState.badflags); - debug(20, 1) (" %7d Objects loaded.\n", RebuildState.objcount); - debug(20, 1) (" %7d Objects expired.\n", RebuildState.expcount); - debug(20, 1) (" %7d Objects cancelled.\n", RebuildState.cancelcount); - debug(20, 1) (" %7d Duplicate URLs purged.\n", RebuildState.dupcount); - debug(20, 1) (" %7d Swapfile clashes avoided.\n", RebuildState.clashcount); - debug(20, 1) (" Took %d seconds (%6.1f objects/sec).\n", - r > 0 ? (int) r : 0, - (double) RebuildState.objcount / (r > 0 ? r : 1)); + double dt; + counts.objcount += dc->objcount; + counts.expcount += dc->expcount; + counts.scancount += dc->scancount; + counts.clashcount += dc->clashcount; + counts.dupcount += dc->dupcount; + counts.cancelcount += dc->cancelcount; + counts.invalid += dc->invalid; + counts.badflags += dc->badflags; + counts.bad_log_op += dc->bad_log_op; + counts.zero_object_sz += dc->zero_object_sz; + /* + * When store_dirs_rebuilding == 1, it means we are done reading + * or scanning all cache_dirs. Now report the stats and start + * the validation thread. + */ + if (store_dirs_rebuilding > 1) + return; + dt = tvSubDsec(rebuild_start, current_time); + debug(20, 1) ("Finished rebuilding storage from disk.\n"); + debug(20, 1) (" %7d Entries scanned\n", counts.scancount); + debug(20, 1) (" %7d Invalid entries.\n", counts.invalid); + debug(20, 1) (" %7d With invalid flags.\n", counts.badflags); + debug(20, 1) (" %7d Objects loaded.\n", counts.objcount); + debug(20, 1) (" %7d Objects expired.\n", counts.expcount); + debug(20, 1) (" %7d Objects cancelled.\n", counts.cancelcount); + debug(20, 1) (" %7d Duplicate URLs purged.\n", counts.dupcount); + debug(20, 1) (" %7d Swapfile clashes avoided.\n", counts.clashcount); + debug(20, 1) (" Took %3.1f seconds (%6.1f objects/sec).\n", dt, + (double) counts.objcount / (dt > 0.0 ? dt : 1.0)); debug(20, 1) ("Beginning Validation Procedure\n"); eventAdd("storeCleanup", storeCleanup, NULL, 0.0, 1); } +/* + * this is ugly. We don't actually start any rebuild threads here, + * but only initialize counters, etc. The rebuild threads are + * actually started by the filesystem "fooDirInit" function. + */ void -storeUfsRebuildStart(void) +storeRebuildStart(void) { - rebuild_dir *d; - int clean = 0; - int zero = 0; - FILE *fp; - int i; - memset(&RebuildState, '\0', sizeof(RebuildState)); - RebuildState.start = squid_curtime; - for (i = 0; i < Config.cacheSwap.n_configured; i++) { - d = xcalloc(1, sizeof(rebuild_dir)); - d->dirn = i; - d->speed = opt_foreground_rebuild ? 1 << 30 : 50; - /* - * If the swap.state file exists in the cache_dir, then - * we'll use storeRebuildFromSwapLog(), otherwise we'll - * use storeRebuildFromDirectory() to open up each file - * and suck in the meta data. - */ - fp = storeUfsDirOpenTmpSwapLog(i, &clean, &zero); - if (fp == NULL || zero) { - if (fp != NULL) - fclose(fp); - d->rebuild_func = storeRebuildFromDirectory; - } else { - d->rebuild_func = storeRebuildFromSwapLog; - d->log = fp; - d->clean = clean; - } - d->next = RebuildState.rebuild_dir; - RebuildState.rebuild_dir = d; - if (!clean) - RebuildState.need_to_validate = 1; - debug(20, 1) ("Rebuilding storage in Cache Dir #%d (%s)\n", - i, clean ? "CLEAN" : "DIRTY"); - } - eventAdd("storeRebuild", storeRebuildADirectory, NULL, 0.0, 1); + memset(&counts, '\0', sizeof(counts)); + rebuild_start = current_time; + /* + * Normally store_dirs_rebuilding is incremented once for each + * cache_dir. We increment it here as well for the disk storage + * system as a whole. The corresponding decrement occurs in + * storeClean(), when it is finished. + */ + store_dirs_rebuilding++; } diff --git a/src/structs.h b/src/structs.h index fdb6474667..7bf0c2178b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.291 1999/05/22 07:42:16 wessels Exp $ + * $Id: structs.h,v 1.292 1999/05/25 06:53:52 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -1265,16 +1265,31 @@ struct _SwapDir { int cur_size; int max_size; char *path; + int index; /* This entry's index into the swapDirs array */ int suggest; struct { unsigned int selected:1; unsigned int read_only:1; } flags; - STOPEN *open; - STCLOSE *close; - STREAD *read; - STWRITE *write; - STUNLINK *unlink; + STINIT *init; + STNEWFS *newfs; + struct { + STOBJOPEN *open; + STOBJCLOSE *close; + STOBJREAD *read; + STOBJWRITE *write; + STOBJUNLINK *unlink; + STOBJLOG *log; + } obj; + struct { + STLOGOPEN *open; + STLOGCLOSE *close; + struct { + STLOGCLEANOPEN *open; + STLOGCLEANWRITE *write; + void *state; + } clean; + } log; union { struct { int l1; @@ -1720,3 +1735,16 @@ struct _helper_server { struct _generic_cbdata { void *data; }; + +struct _store_rebuild_data { + int objcount; /* # objects successfully reloaded */ + int expcount; /* # objects expired */ + int scancount; /* # entries scanned or read from state file */ + 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 bad_log_op; + int zero_object_sz; +}; diff --git a/src/tools.cc b/src/tools.cc index 06f1184081..2254daf9ff 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -1,6 +1,6 @@ /* - * $Id: tools.cc,v 1.179 1999/05/19 19:57:56 wessels Exp $ + * $Id: tools.cc,v 1.180 1999/05/25 06:53:53 wessels Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -317,10 +317,10 @@ void fatal(const char *message) { releaseServerSockets(); - /* check for store_rebuilding flag because fatal() is often + /* check for store_dirs_rebuilding because fatal() is often * used in early initialization phases, long before we ever * get to the store log. */ - if (!store_rebuilding) + if (0 == store_dirs_rebuilding) storeDirWriteCleanLogs(0); fatal_common(message); exit(shutting_down ? 0 : 1); diff --git a/src/typedefs.h b/src/typedefs.h index 06534f440d..06280ae606 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.91 1999/05/22 07:42:17 wessels Exp $ + * $Id: typedefs.h,v 1.92 1999/05/25 06:53:54 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -211,11 +211,18 @@ typedef void HLPCB(void *, char *buf); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int); -typedef storeIOState *STOPEN(sfileno, mode_t, STIOCB *, void *); -typedef void STCLOSE(storeIOState *); -typedef void STREAD(storeIOState *, char *, size_t, off_t, STRCB *, void *); -typedef void STWRITE(storeIOState *, char *, size_t, off_t, FREE *); -typedef void STUNLINK(sfileno); +typedef void STINIT(SwapDir *); +typedef void STNEWFS(SwapDir *); +typedef storeIOState *STOBJOPEN(sfileno, mode_t, STIOCB *, void *); +typedef void STOBJCLOSE(storeIOState *); +typedef void STOBJREAD(storeIOState *, char *, size_t, off_t, STRCB *, void *); +typedef void STOBJWRITE(storeIOState *, char *, size_t, off_t, FREE *); +typedef void STOBJUNLINK(sfileno); +typedef void STOBJLOG(const StoreEntry *, int); +typedef void STLOGOPEN(SwapDir *); +typedef void STLOGCLOSE(SwapDir *); +typedef int STLOGCLEANOPEN(SwapDir *); +typedef void STLOGCLEANWRITE(const StoreEntry *, SwapDir *); typedef double hbase_f(double); typedef void StatHistBinDumper(StoreEntry *, int idx, double val, double size, int count);