📄 store_rebuild.c
字号:
static voidstoreRebuildADirectory(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_CODEstatic voidstoreConvertFile(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);}#endifstatic intstoreGetNextFile(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 (!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); 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].l2) continue; d->curlvl2 = 0; if (++d->curlvl1 < Config.cacheSwap.swapDirs[d->dirn].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 voidstoreCleanup(void *datanotused){ static int bucketnum = -1; static int validnum = 0; static int store_errors = 0; StoreEntry *e; hash_link *link_ptr = NULL; hash_link *link_next = NULL; if (++bucketnum >= store_hash_buckets) { 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) storeDigestNoteStoreReady(); return; } link_next = hash_get_bucket(store_table, bucketnum); while (NULL != (link_ptr = link_next)) { link_next = link_ptr->next; e = (StoreEntry *) link_ptr; if (EBIT_TEST(e->flags, ENTRY_VALIDATED)) continue; /* * Calling storeRelease() has no effect because we're * still in 'store_rebuilding' state */ if (e->swap_file_number < 0) continue; if (opt_store_doublecheck) { struct stat sb; if (stat(storeSwapFullPath(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)); storeEntryDump(e, 0); continue; } if (e->swap_file_sz != sb.st_size) { store_errors++; 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)); debug(20, 0) ("storeCleanup: ENTRY SIZE: %d, FILE SIZE: %d\n", e->swap_file_sz, (int) sb.st_size); storeEntryDump(e, 0); continue; } } EBIT_SET(e->flags, 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); } eventAdd("storeCleanup", storeCleanup, NULL, 0.0, 1);}voidstoreValidate(StoreEntry * e, STVLDCB * callback, void *callback_data, void *tag){ valid_ctrl_t *ctrlp; char *path; struct stat *sb;#if !USE_ASYNC_IO int x;#endif assert(!EBIT_TEST(e->flags, ENTRY_VALIDATED)); if (e->swap_file_number < 0) { EBIT_CLR(e->flags, ENTRY_VALIDATED); callback(callback_data, 0, 0); return; } path = storeSwapFullPath(e->swap_file_number, NULL); sb = xmalloc(sizeof(struct stat)); ctrlp = xmalloc(sizeof(valid_ctrl_t)); ctrlp->sb = sb; ctrlp->e = e; ctrlp->callback = callback; ctrlp->callback_data = callback_data;#if USE_ASYNC_IO aioStat(path, sb, storeValidateComplete, ctrlp, tag);#else /* * When evaluating the actual arguments in a function call, the order * in which the arguments and the function expression are evaluated is * not specified; */ x = stat(path, sb); storeValidateComplete(-1, ctrlp, x, errno);#endif return;}static voidstoreValidateComplete(int fd, void *data, int retcode, int errcode){ valid_ctrl_t *ctrlp = data; struct stat *sb = ctrlp->sb; StoreEntry *e = ctrlp->e; char *path; if (retcode == -2 && errcode == -2) { xfree(sb); xfree(ctrlp); ctrlp->callback(ctrlp->callback_data, retcode, errcode); return; } if (retcode < 0 && errcode == EWOULDBLOCK) { path = storeSwapFullPath(e->swap_file_number, NULL); retcode = stat(path, sb); } if (retcode < 0 || sb->st_size == 0 || sb->st_size != e->swap_file_sz) { EBIT_CLR(e->flags, ENTRY_VALIDATED); } else { EBIT_SET(e->flags, ENTRY_VALIDATED); storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1); } errno = errcode; ctrlp->callback(ctrlp->callback_data, retcode, errcode); xfree(sb); xfree(ctrlp);}/* meta data recreated from disk image in swap directory */static voidstoreRebuildComplete(void){ 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)); debug(20, 1) ("Beginning Validation Procedure\n"); eventAdd("storeCleanup", storeCleanup, NULL, 0.0, 1);}voidstoreRebuildStart(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 = storeDirOpenTmpSwapLog(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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -