/*
- * $Id: store_dir.cc,v 1.54 1998/02/12 07:03:07 wessels Exp $
+ * $Id: store_dir.cc,v 1.55 1998/02/12 23:36:02 wessels Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
*
* This is called by storeDirClean(), but placed here because
* the algorithm needs to match storeSwapSubSubDir().
+ *
+ * Don't check that (fn >> SWAP_DIR_SHIFT) == F0 because
+ * 'fn' may not have the directory bits set.
*/
int
storeFilenoBelongsHere(int fn, int F0, int F1, int F2)
{
- int D0, D1, D2;
+ int D1, D2;
int L1, L2;
int filn = fn & SWAP_FILE_MASK;
- D0 = (fn >> SWAP_DIR_SHIFT) % Config.cacheSwap.n_configured;
- if (F0 != D0)
- return 0;
- L1 = Config.cacheSwap.swapDirs[D0].l1;
- L2 = Config.cacheSwap.swapDirs[D0].l2;
+ assert(F0 < Config.cacheSwap.n_configured);
+ L1 = Config.cacheSwap.swapDirs[F0].l1;
+ L2 = Config.cacheSwap.swapDirs[F0].l2;
D1 = ((filn / L2) / L2) % L1;
if (F1 != D1)
return 0;
return (dirn << SWAP_DIR_SHIFT) | (fn & SWAP_FILE_MASK);
}
+/*
+ * An entry written to the swap log MUST have the following
+ * properties.
+ * 1. It MUST be a public key. It does no good to log
+ * a public ADD, change the key, then log a private
+ * DEL. So we need to log a DEL before we change a
+ * key from public to private.
+ * 2. It MUST have a valid (> -1) swap_file_number.
+ */
void
storeDirSwapLog(const StoreEntry * e, int op)
{
int dirn;
dirn = e->swap_file_number >> SWAP_DIR_SHIFT;
assert(dirn < Config.cacheSwap.n_configured);
- if (op == SWAP_LOG_ADD) {
- assert(!EBIT_TEST(e->flag, KEY_PRIVATE));
- assert(e->swap_file_number >= 0);
- }
- if (op == SWAP_LOG_DEL) {
- if (e->swap_file_number < 0) /* was never swapped out */
- return;
- }
+ assert(!EBIT_TEST(e->flag, KEY_PRIVATE));
+ assert(e->swap_file_number >= 0);
/*
* icons and such; don't write them to the swap log
*/
if (EBIT_TEST(e->flag, ENTRY_SPECIAL))
return;
+ assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
debug(20, 3) ("storeDirSwapLog: %s %s %08X\n",
- op == SWAP_LOG_DEL ? "SWAP_LOG_DEL" : "SWAP_LOG_ADD",
+ swap_log_op_str[op],
storeKeyText(e->key),
e->swap_file_number);
s->op = (char) op;
DIR *td;
RBHD *rebuild_func;
rebuild_dir *next;
+ char fullpath[SQUID_MAXPATHLEN];
+ char fullfilename[SQUID_MAXPATHLEN];
};
struct storeRebuildState {
int sfileno = 0;
int count;
int size;
- struct stat fst;
+ struct stat sb;
int swap_hdr_len;
int fd = -1;
tlv *tlv_list;
}
assert(fd > -1);
/* lets get file stats here */
- if (fstat(fd, &fst) < 0) {
+ if (fstat(fd, &sb) < 0) {
debug(20, 1) ("storeRebuildFromDirectory: fstat(FD %d): %s\n",
fd, xstrerror());
file_close(fd);
if ((++RebuildState.statcount & 0x3FFF) == 0)
debug(20, 1) (" %7d files opened so far.\n",
RebuildState.statcount);
- debug(20, 9) ("file_in: fd=%d %08x\n", fd, sfileno);
+ debug(20, 9) ("file_in: fd=%d %08X\n", fd, sfileno);
if (read(fd, hdr_buf, DISK_PAGE_SIZE) < 0) {
debug(20, 1) ("storeRebuildFromDirectory: read(FD %d): %s\n",
fd, xstrerror());
#endif
/* check sizes */
if (tmpe.swap_file_sz == 0) {
- tmpe.swap_file_sz = fst.st_size;
- } else if (tmpe.swap_file_sz != fst.st_size) {
+ 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, fst.st_size);
+ tmpe.swap_file_sz, sb.st_size);
storeUnlinkFileno(sfileno);
continue;
}
return -1;
}
d->n_read++;
+ if (s.op <= SWAP_LOG_NOP)
+ continue;
+ if (s.op >= SWAP_LOG_MAX)
+ continue;
+ 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) {
* because adding to store_swap_size happens in
* the cleanup procedure.
*/
-
storeExpireNow(e);
storeSetPrivateKey(e);
EBIT_SET(e->flag, RELEASE_REQUEST);
RebuildState.clashcount++;
continue;
} else if (e) {
- /* URL already exists, this swapfile not being used */
+ /* key already exists, this swapfile not being used */
/* junk old, load new */
- storeRelease(e); /* release old entry */
+ storeExpireNow(e);
+ storeSetPrivateKey(e);
+ EBIT_SET(e->flag, RELEASE_REQUEST);
+ 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 */
{
int fd = -1;
int used = 0;
- LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
- LOCAL_ARRAY(char, fullpath, SQUID_MAXPATHLEN);
debug(20, 3) ("storeGetNextFile: flag=%d, %d: /%02X/%02X\n",
d->flag,
d->dirn,
assert(Config.cacheSwap.n_configured > 0);
}
if (0 == d->in_dir) { /* we need to read in a new directory */
- snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
+ 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(fullpath);
+ d->td = opendir(d->fullpath);
if (d->td == NULL) {
debug(50, 1) ("storeGetNextFile: opendir: %s: %s\n",
- fullpath, xstrerror());
+ d->fullpath, xstrerror());
break;
}
d->entry = readdir(d->td); /* skip . and .. */
d->entry = readdir(d->td);
if (errno == ENOENT)
debug(20, 1) ("storeGetNextFile: directory does not exist!.\n");
- debug(20, 3) ("storeGetNextFile: Directory %s\n", fullpath);
+ 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", sfileno) != 1) {
+ if (sscanf(d->entry->d_name, "%x", &d->fn) != 1) {
debug(20, 3) ("storeGetNextFile: invalid %s\n",
d->entry->d_name);
continue;
}
- d->fn = *sfileno;
- if (!storeFilenoBelongsHere(d->fn, d->dirn, d->curlvl1, d->curlvl2))
+ if (!storeFilenoBelongsHere(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);
- *sfileno = d->fn;
used = storeDirMapBitTest(d->fn);
if (used) {
debug(20, 3) ("storeGetNextFile: Locked, continuing with next.\n");
continue;
}
- snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%s",
- fullpath, d->entry->d_name);
- debug(20, 3) ("storeGetNextFile: Opening %s\n", fullfilename);
- fd = file_open(fullfilename, O_RDONLY, NULL, NULL, NULL);
+ 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;
}
d->in_dir = 0;
d->curlvl1 = 0;
d->done = 1;
}
+ *sfileno = d->fn;
return fd;
}
{
static int bucketnum = -1;
static int validnum = 0;
+ static int store_errors = 0;
StoreEntry *e;
hash_link *link_ptr = NULL;
if (++bucketnum >= store_hash_buckets) {
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);
return;
}
link_ptr = hash_get_bucket(store_table, bucketnum);
continue;
if (e->swap_file_number < 0)
continue;
-#if STORE_DOUBLECHECK
- {
+ if (EBIT_TEST(e->flag, RELEASE_REQUEST)) {
+ assert(!storeDirMapBitTest(e->swap_file_number));
+ /*
+ * I don't think it safe to call storeRelease()
+ * from inside this loop using link_ptr.
+ */
+ continue;
+ }
+ if (opt_store_doublecheck) {
struct stat sb;
if (stat(storeSwapFullPath(e->swap_file_number, NULL), &sb) < 0) {
+ store_errors++;
debug(0, 0) ("storeCleanup: MISSING SWAP FILE\n");
debug(0, 0) ("storeCleanup: FILENO %08X\n", e->swap_file_number);
debug(0, 0) ("storeCleanup: PATH %s\n",
storeSwapFullPath(e->swap_file_number, NULL));
storeEntryDump(e, 0);
- assert(0);
+ continue;
+ }
+ if (e->swap_file_sz != sb.st_size) {
+ store_errors++;
+ debug(0, 0) ("storeCleanup: SIZE MISMATCH\n");
+ debug(0, 0) ("storeCleanup: FILENO %08X\n", e->swap_file_number);
+ debug(0, 0) ("storeCleanup: PATH %s\n",
+ storeSwapFullPath(e->swap_file_number, NULL));
+ debug(0, 0) ("storeCleanup: ENTRY SIZE: %d, FILE SIZE: %d\n",
+ e->swap_file_sz, sb.st_size);
+ storeEntryDump(e, 0);
+ continue;
}
}
-#endif
EBIT_SET(e->flag, ENTRY_VALIDATED);
/* Only set the file bit if we know its a valid entry */
/* otherwise, set it in the validation procedure */
storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);
if ((++validnum & 0xFFFF) == 0)
debug(20, 1) (" %7d Entries Validated so far.\n", validnum);
- assert(validnum <= memInUse(MEM_STOREENTRY));
}
eventAdd("storeCleanup", storeCleanup, NULL, 0);
}