55 int zeroLengthLog = 0;
56 FILE *fp =
sd->openTmpSwapLog(&clean, &zeroLengthLog);
58 if (fp && !zeroLengthLog)
78 (clean ?
"clean log" : (
LogParser ?
"dirty log" :
"no log")) <<
")");
83 sd->closeTmpSwapLog();
98 eventAdd(
"storeRebuild", RebuildStep, rb, 0.01, 1);
112 const int maxSpentMsec = 50;
115 const int totalEntries = LogParser ? LogParser->SwapLogEntries() : -1;
119 rebuildFromSwapLog();
121 rebuildFromDirectory();
124 if (totalEntries > 0 && (n_read % 4000 == 0))
132 if (elapsedMsec > maxSpentMsec || elapsedMsec < 0) {
133 debugs(47, 5,
"pausing after " << n_read <<
" entries in " <<
134 elapsedMsec <<
"ms; " << (elapsedMsec/n_read) <<
"ms per entry");
148 debugs(47, 3,
"DIR #" << sd->index);
153 fd = getNextFile(&filn, &
size);
157 n_read <<
" entries)");
169 if (fstat(fd, &sb) < 0) {
183 const uint64_t expectedSize = sb.st_size > 0 ?
184 static_cast<uint64_t
>(sb.st_size) : 0;
195 if (parsed && !accepted) {
197 "unknown size: " << tmpe);
203 sd->unlinkFile(filn);
222 uint64_t swap_file_sz,
234 const auto addedEntry = sd->addDiskRestore(key,
253 if (
auto *indexedEntry =
Store::Root().peek(candidateKey)) {
255 if (indexedEntry->lastref >= maxRef) {
256 indexedEntry->abandon(
"Fs::Ufs::RebuildState::evictStaleAndContinue");
262 indexedEntry->release(
true);
274 if (LogParser->ReadRecord(swapData) != 1) {
275 debugs(47,
DBG_IMPORTANT,
"Done reading " << sd->path <<
" swaplog (" << n_read <<
" entries)");
285 if (!swapData.
sane()) {
314 if (0.0 == x - (
double) (
int) x)
324 if (!sd->validFileno(swapData.
swap_filen, 0)) {
342 addIfFresh(swapData.
key,
358 debugs(47, 3,
"flag=" << flags.init <<
", " <<
359 sd->index <<
": /" <<
360 asHex(curlvl1).upperCase().minDigits(2) <<
"/" <<
361 asHex(curlvl2).upperCase().minDigits(2));
366 while (fd < 0 && done == 0) {
380 fullpath.Printf(
"%s/%02X/%02X",
387 td = opendir(fullpath.c_str());
398 if (entry ==
nullptr && errno == ENOENT)
400 debugs(47, 3,
"Directory " << fullpath);
404 if (td !=
nullptr && (entry = readdir(td)) !=
nullptr) {
407 if (sscanf(entry->d_name,
"%x", &fn) != 1) {
408 debugs(47, 3,
"invalid entry " << entry->d_name);
413 debugs(47, 3,
asHex(fn).upperCase().minDigits(8) <<
414 " does not belong in " << sd->index <<
"/" <<
415 asHex(curlvl1).upperCase().minDigits(2) <<
"/" <<
416 asHex(curlvl2).upperCase().minDigits(2));
420 if (sd->mapBitTest(fn)) {
421 debugs(47, 3,
"Locked, continuing with next.");
427 debugs(47, 3,
"Opening " << fullfilename);
446 if (sd->validL2(++curlvl2))
451 if (sd->validL1(++curlvl1))
void storeDirSwapLog(const StoreEntry *e, int op)
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
#define SQUIDSBUFPRINT(s)
void log(char *format,...)
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
RefCount< UFSSwapDir > sd
void rebuildFromDirectory()
process one cache file
RebuildState(const RefCount< UFSSwapDir > &sd)
void rebuildFromSwapLog()
process one swap log entry
virtual bool error() const
bool evictStaleAndContinue(const cache_key *candidateKey, const time_t maxRef, int &staleCount)
Fs::Ufs::UFSSwapLogParser * LogParser
virtual bool isDone() const
struct Fs::Ufs::RebuildState::Flags flags
int getNextFile(sfileno *, int *size)
void rebuildStep()
load entries from swap.state or files until we run out of entries or time
void addIfFresh(const cache_key *key, sfileno file_number, uint64_t swap_file_sz, time_t expires, time_t timestamp, time_t lastref, time_t lastmod, uint32_t refcount, uint16_t flags)
if the loaded entry metadata is still relevant, indexes the entry
static bool FilenoBelongsHere(int fn, int cachedir, int level1dir, int level2dir)
static UFSSwapLogParser * GetUFSSwapLogParser(FILE *fp)
void init(mb_size_t szInit, mb_size_t szMax)
Store::DiskConfig cacheSwap
void lastModified(const time_t when)
void updateStartTime(const timeval &dirStartTime)
maintain earliest initiation time across multiple indexing cache_dirs
unsigned char key[SQUID_MD5_DIGEST_LENGTH]
bool sane() const
consistency self-check: whether the data appears to make sense
#define debugs(SECTION, LEVEL, CONTENT)
#define EBIT_TEST(flag, bit)
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
int file_open(const char *path, int mode)
int opt_foreground_rebuild
#define SQUID_MD5_DIGEST_LENGTH
Controller & Root()
safely access controller singleton
unsigned char cache_key
Store key.
const char * storeKeyText(const cache_key *key)
bool storeRebuildParseEntry(MemBuf &buf, StoreEntry &tmpe, cache_key *key, StoreRebuildData &stats, uint64_t expectedSize)
bool storeRebuildLoadEntry(int fd, int diskIndex, MemBuf &buf, StoreRebuildData &)
loads entry from disk; fills supplied memory buffer on success
static StoreRebuildData counts
void storeRebuildComplete(StoreRebuildData *dc)
void storeRebuildProgress(const int sd_index_raw, const int total, const int sofar)
time_t getCurrentTime() STUB_RETVAL(0) int tvSubUsec(struct timeval
const char * swap_log_op_str[]
static StoreEntry * addedEntry(Store::Disk *aStore, String name, String, String)
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
int tvSubMsec(struct timeval t1, struct timeval t2)
const char * xstrerr(int error)