📄 store_dir_ufs.c
字号:
time_t timestamp; time_t lastref; time_t expires; time_t lastmod; size_t swap_file_sz; u_short refcount; u_short flags; } *tmp = t->value; assert(sizeof(*tmp) == STORE_HDR_METASIZE_OLD); tmpe.timestamp = tmp->timestamp; tmpe.lastref = tmp->lastref; tmpe.expires = tmp->expires; tmpe.lastmod = tmp->lastmod; tmpe.swap_file_sz = tmp->swap_file_sz; tmpe.refcount = tmp->refcount; tmpe.flags = tmp->flags; } break;#endif default: break; } } storeSwapTLVFree(tlv_list); tlv_list = NULL; if (storeKeyNull(key)) { debug(47, 1) ("storeUfsDirRebuildFromDirectory: NULL key\n"); storeUfsDirUnlinkFile(SD, filn); continue; } tmpe.hash.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(47, 1) ("storeUfsDirRebuildFromDirectory: SIZE MISMATCH %ld!=%ld\n", (long int) tmpe.swap_file_sz, (long int) sb.st_size); storeUfsDirUnlinkFile(SD, filn); continue; } if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) { storeUfsDirUnlinkFile(SD, filn); rb->counts.badflags++; continue; } e = storeGet(key); if (e && e->lastref >= tmpe.lastref) { /* key already exists, current entry is newer */ /* keep old, ignore new */ rb->counts.dupcount++; continue; } else if (NULL != e) { /* URL already exists, this swapfile not being used */ /* junk old, load new */ storeRelease(e); /* release old entry */ rb->counts.dupcount++; } rb->counts.objcount++; storeEntryDump(&tmpe, 5); e = storeUfsDirAddDiskRestore(SD, key, filn, tmpe.swap_file_sz, tmpe.expires, tmpe.timestamp, tmpe.lastref, tmpe.lastmod, tmpe.refcount, /* refcount */ tmpe.flags, /* flags */ (int) rb->flags.clean); storeDirSwapLog(e, SWAP_LOG_ADD); } eventAdd("storeRebuild", storeUfsDirRebuildFromDirectory, rb, 0.0, 1);}static voidstoreUfsDirRebuildFromSwapLog(void *data){ RebuildState *rb = data; SwapDir *SD = rb->sd; 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(rb != NULL); /* load a number of objects per invocation */ for (count = 0; count < rb->speed; count++) { if (fread(&s, ss, 1, rb->log) != 1) { storeUfsDirRebuildComplete(rb); return; } rb->n_read++; /* * BC: during 2.4 development, we changed the way swap file * numbers are assigned and stored. The high 16 bits used * to encode the SD index number. There used to be a call * to storeDirProperFileno here that re-assigned the index * bits. Now, for backwards compatibility, we just need * to mask it off. */ s.swap_filen &= 0x00FFFFFF; debug(47, 3) ("storeUfsDirRebuildFromSwapLog: %s %s %08X\n", swap_log_op_str[(int) s.op], storeKeyText(s.key), s.swap_filen); if (s.op == SWAP_LOG_ADD) { (void) 0; } else if (s.op == SWAP_LOG_DEL) { /* Delete unless we already have a newer copy */ if ((e = storeGet(s.key)) != NULL && s.lastref > e->lastref) { /* * 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. */ storeRecycle(e); /* * XXX considering we might've canceled an object from another store; * XXX what should happen with these stats? */ rb->counts.objcount--; rb->counts.cancelcount++; } continue; } else { x = log(++rb->counts.bad_log_op) / log(10.0); if (0.0 == x - (double) (int) x) debug(47, 1) ("WARNING: %d invalid swap log entries found\n", rb->counts.bad_log_op); rb->counts.invalid++; continue; } if ((++rb->counts.scancount & 0xFFF) == 0) { struct stat sb; if (0 == fstat(fileno(rb->log), &sb)) storeRebuildProgress(SD->index, (int) sb.st_size / ss, rb->n_read); } if (!storeUfsDirValidFileno(SD, s.swap_filen, 0)) { rb->counts.invalid++; continue; } if (EBIT_TEST(s.flags, KEY_PRIVATE)) { rb->counts.badflags++; continue; } e = storeGet(s.key); used = storeUfsDirMapBitTest(SD, s.swap_filen); /* 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 */ rb->counts.clashcount++; continue; } else if (used && e && e->swap_filen == s.swap_filen && e->swap_dirn == SD->index) { /* 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; storeUfsDirUnrefObj(SD, e); } else { debug_trap("storeUfsDirRebuildFromSwapLog: bad condition"); debug(47, 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(47, 1) ("WARNING: newer swaplog entry for dirno %d, fileno %08X\n", SD->index, s.swap_filen); /* 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(rb->flags.need_to_validate); rb->counts.clashcount++; continue; } else if (e && !disk_entry_newer) { /* key already exists, current entry is newer */ /* keep old, ignore new */ rb->counts.dupcount++; continue; } else if (e) { /* key already exists, this swapfile not being used */ /* junk old, load new */ storeRecycle(e); rb->counts.dupcount++; } else { /* URL doesnt exist, swapfile not in use */ /* load new */ (void) 0; } /* update store_swap_size */ rb->counts.objcount++; e = storeUfsDirAddDiskRestore(SD, s.key, s.swap_filen, s.swap_file_sz, s.expires, s.timestamp, s.lastref, s.lastmod, s.refcount, s.flags, (int) rb->flags.clean); storeDirSwapLog(e, SWAP_LOG_ADD); } eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLog, rb, 0.0, 1);}#if SIZEOF_SQUID_FILE_SZ != SIZEOF_SIZE_T/* This is an exact copy of the above, but using storeSwapLogDataOld entry type */static voidstoreUfsDirRebuildFromSwapLogOld(void *data){ RebuildState *rb = data; SwapDir *SD = rb->sd; StoreEntry *e = NULL; storeSwapLogDataOld s; size_t ss = sizeof(storeSwapLogDataOld); int count; int used; /* is swapfile already in use? */ int disk_entry_newer; /* is the log entry newer than current entry? */ double x; assert(rb != NULL); /* load a number of objects per invocation */ for (count = 0; count < rb->speed; count++) { if (fread(&s, ss, 1, rb->log) != 1) { storeUfsDirRebuildComplete(rb); return; } rb->n_read++; /* * BC: during 2.4 development, we changed the way swap file * numbers are assigned and stored. The high 16 bits used * to encode the SD index number. There used to be a call * to storeDirProperFileno here that re-assigned the index * bits. Now, for backwards compatibility, we just need * to mask it off. */ s.swap_filen &= 0x00FFFFFF; debug(47, 3) ("storeUfsDirRebuildFromSwapLog: %s %s %08X\n", swap_log_op_str[(int) s.op], storeKeyText(s.key), s.swap_filen); if (s.op == SWAP_LOG_ADD) { (void) 0; } else if (s.op == SWAP_LOG_DEL) { /* Delete unless we already have a newer copy */ if ((e = storeGet(s.key)) != NULL && s.lastref > e->lastref) { /* * 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. */ storeRecycle(e); /* XXX are these counters valid since e could be from another swapfs? */ rb->counts.objcount--; rb->counts.cancelcount++; } continue; } else { x = log(++rb->counts.bad_log_op) / log(10.0); if (0.0 == x - (double) (int) x) debug(47, 1) ("WARNING: %d invalid swap log entries found\n", rb->counts.bad_log_op); rb->counts.invalid++; continue; } if ((++rb->counts.scancount & 0xFFF) == 0) { struct stat sb; if (0 == fstat(fileno(rb->log), &sb)) storeRebuildProgress(SD->index, (int) sb.st_size / ss, rb->n_read); } if (!storeUfsDirValidFileno(SD, s.swap_filen, 0)) { rb->counts.invalid++; continue; } if (EBIT_TEST(s.flags, KEY_PRIVATE)) { rb->counts.badflags++; continue; } e = storeGet(s.key); used = storeUfsDirMapBitTest(SD, s.swap_filen); /* 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 */ rb->counts.clashcount++; continue; } else if (used && e && e->swap_filen == s.swap_filen && e->swap_dirn == SD->index) { /* 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; storeUfsDirUnrefObj(SD, e); } else { debug_trap("storeUfsDirRebuildFromSwapLog: bad condition"); debug(47, 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(47, 1) ("WARNING: newer swaplog entry for dirno %d, fileno %08X\n", SD->index, s.swap_filen); /* 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(rb->flags.need_to_validate); rb->counts.clashcount++; continue; } else if (e && !disk_entry_newer) { /* key already exists, current entry is newer */ /* keep old, ignore new */ rb->counts.dupcount++; continue; } else if (e) { /* key already exists, this swapfile not being used */ /* junk old, load new */ storeRecycle(e); rb->counts.dupcount++; } else { /* URL doesnt exist, swapfile not in use */ /* load new */ (void) 0; } /* update store_swap_size */ rb->counts.objcount++; e = storeUfsDirAddDiskRestore(SD, s.key, s.swap_filen, s.swap_file_sz, s.expires, s.timestamp, s.lastref, s.lastmod, s.refcount, s.flags, (int) rb->flags.clean); storeDirSwapLog(e, SWAP_LOG_ADD); } eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLogOld, rb, 0.0, 1);}#endifstatic voidstoreUfsDirRebuildFromSwapLogCheckVersion(void *data){ RebuildState *rb = data; storeSwapLogHeader hdr; if (fread(&hdr, sizeof(hdr), 1, rb->log) != 1) { storeUfsDirRebuildComplete(rb); return; } if (hdr.op == SWAP_LOG_VERSION) { if (fseek(rb->log, hdr.record_size, SEEK_SET) != 0) { storeUfsDirRebuildComplete(rb); return; } if (hdr.version == 1 && hdr.record_size == sizeof(storeSwapLogData)) { eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLog, rb, 0.0, 1); return; }#if SIZEOF_SQUID_FILE_SZ != SIZEOF_SIZE_T if (hdr.version == 1 && hdr.record_size == sizeof(storeSwapLogDataOld)) { debug(47, 1) ("storeUfsDirRebuildFromSwapLog: Found current version but without large file support. Upgrading\n"); eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLogOld, rb, 0.0, 1); return; }#endif debug(47, 1) ("storeUfsDirRebuildFromSwapLog: Unsupported swap.state version %d size %d\n", hdr.version, hdr.record_size); storeUfsDirRebuildComplete(rb); return; } rewind(rb->log); debug(47, 1) ("storeUfsDirRebuildFromSwapLog: Old version detected. Upgrading\n");#if SIZEOF_SQUID_FILE_SZ == SIZEOF_SIZE_T eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLog, rb, 0.0, 1);#else eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLogOld, rb, 0.0, 1);#endif}static intstoreUfsDirGetNextFile(RebuildState * rb, sfileno * filn_p, int *size){ SwapDir *SD = rb->sd; ufsinfo_t *ufsinfo = (ufsinfo_t *) SD->fsdata; int fd = -1; int used = 0; int dirs_opened = 0; debug(47, 3) ("storeUfsDirGetNextFile: flag=%d, %d: /%02X/%02X\n", rb->flags.init, rb->sd->index, rb->curlvl1, rb->curlvl2); if (rb->done) return -2; while (fd < 0 && rb->done == 0) { fd = -1; if (0 == rb->flags.init) { /* initialize, open first file */ rb->done = 0; rb->curlvl1 = 0; rb->curlvl2 = 0; rb->in_dir = 0; rb->flags.init = 1; assert(Config.cacheSwap.n_configured > 0); } if (0 == rb->in_dir) { /* we need to read in a new directory */ snprintf(rb->fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X", rb->sd->path, rb->curlvl1, rb->curlvl2); if (dirs_opened) return -1; rb->td = opendir(rb->fullpath); dirs_opened++; if (rb->td == NULL) { debug(47, 1) ("storeUfsDirGetNextFile: opendir: %s: %s\n", rb->fullpath, xstrerror()); } else { rb->entry = readdir(rb->td); /* skip . and .. */ rb->entry = readdir(rb->td); if (rb->entry == NULL && errno == ENOENT) debug(47, 1) ("storeUfsDirGetNextFile: directory does not exist!.\n"); debug(47, 3) ("storeUfsDirGetNextFile: Directory %s\n", rb->fullpath); } } if (rb->td != NULL && (rb->entry = readdir(rb->td)) != NULL) { rb->in_dir++; if (sscanf(rb->entry->d_name, "%x", &rb->fn) != 1) { debug(47, 3) ("storeUfsDirGetNextFile: invalid %s\n", rb->entry->d_name); continue; } if (!storeUfsFilenoBelongsHere(rb->fn, rb->sd->index, rb->curlvl1, rb->curlvl2)) { debug(47, 3) ("storeUfsDirGetNextFile: %08X does not belong in %d/%d/%d\n", rb->fn, rb->sd->index, rb->curlvl1, rb->curlvl2); continue; } used = storeUfsDirMapBitTest(SD, rb->fn); if (used) { debug(47, 3) ("storeUfsDirGetNextFile: Locked, continuing with next.\n"); continue; } snprintf(rb->fullfilename, SQUID_MAXPATHLEN, "%s/%s", rb->fullpath, rb->entry->d_name); debug(47, 3) ("storeUfsDirGetNextFile: Opening %s\n", rb->fullfilename); fd = file_open(rb->fullfilename, O_RDONLY | O_BINARY); if (fd < 0) debug(47, 1) ("storeUfsDirGetNextFile: %s: %s\n", rb->fullfilename, xstrerror()); else store_open_disk_fd++; continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -