📄 store_dir_diskd.c
字号:
if (fd < 0) { debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror()); fatal("storeDiskdDirCloseTmpSwapLog: Failed to open swap log."); } safe_free(swaplog_path); safe_free(new_path); diskdinfo->swaplog_fd = fd; debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", sd->index, fd);}static voidstoreSwapLogDataFree(void *s){ memFree(s, MEM_SWAP_LOG_DATA);}static voidstoreDiskdWriteSwapLogheader(int fd){ storeSwapLogHeader *hdr = memAllocate(MEM_SWAP_LOG_DATA); hdr->op = SWAP_LOG_VERSION; hdr->version = 1; hdr->record_size = sizeof(storeSwapLogData); /* The header size is a full log record to keep some level of backward * compatibility even if the actual header is smaller */ file_write(fd, -1, hdr, sizeof(storeSwapLogData), NULL, NULL, (FREE *) storeSwapLogDataFree);}static FILE *storeDiskdDirOpenTmpSwapLog(SwapDir * sd, int *clean_flag, int *zero_flag){ diskdinfo_t *diskdinfo = sd->fsdata; char *swaplog_path = xstrdup(storeDiskdDirSwapLogFile(sd, NULL)); char *clean_path = xstrdup(storeDiskdDirSwapLogFile(sd, ".last-clean")); char *new_path = xstrdup(storeDiskdDirSwapLogFile(sd, ".new")); struct stat log_sb; struct stat clean_sb; FILE *fp; int fd; if (stat(swaplog_path, &log_sb) < 0) { debug(47, 1) ("Cache Dir #%d: No log file\n", sd->index); safe_free(swaplog_path); safe_free(clean_path); safe_free(new_path); return NULL; } *zero_flag = log_sb.st_size == 0 ? 1 : 0; /* close the existing write-only FD */ if (diskdinfo->swaplog_fd >= 0) file_close(diskdinfo->swaplog_fd); /* open a write-only FD for the new log */ fd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); if (fd < 0) { debug(50, 1) ("%s: %s\n", new_path, xstrerror()); fatal("storeDirOpenTmpSwapLog: Failed to open swap log."); } diskdinfo->swaplog_fd = fd; storeDiskdWriteSwapLogheader(fd); /* open a read-only stream of the old log */ fp = fopen(swaplog_path, "rb"); if (fp == NULL) { debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); fatal("Failed to open swap log for reading"); } memset(&clean_sb, '\0', sizeof(struct stat)); if (stat(clean_path, &clean_sb) < 0) *clean_flag = 0; else if (clean_sb.st_mtime < log_sb.st_mtime) *clean_flag = 0; else *clean_flag = 1; safeunlink(clean_path, 1); safe_free(swaplog_path); safe_free(clean_path); safe_free(new_path); return fp;}struct _clean_state { char *cur; char *new; char *cln; char *outbuf; int outbuf_offset; int fd; RemovalPolicyWalker *walker;};#define CLEAN_BUF_SZ 16384/* * Begin the process to write clean cache state. For DISKD this means * opening some log files and allocating write buffers. Return 0 if * we succeed, and assign the 'func' and 'data' return pointers. */static intstoreDiskdDirWriteCleanStart(SwapDir * sd){ struct _clean_state *state = xcalloc(1, sizeof(*state));#if HAVE_FCHMOD struct stat sb;#endif sd->log.clean.write = NULL; sd->log.clean.state = NULL; state->new = xstrdup(storeDiskdDirSwapLogFile(sd, ".clean")); state->cur = xstrdup(storeDiskdDirSwapLogFile(sd, NULL)); state->cln = xstrdup(storeDiskdDirSwapLogFile(sd, ".last-clean")); state->outbuf = xcalloc(CLEAN_BUF_SZ, 1); state->outbuf_offset = 0; state->walker = sd->repl->WalkInit(sd->repl); unlink(state->cln); state->fd = file_open(state->new, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); if (state->fd < 0) { xfree(state->new); xfree(state->cur); xfree(state->cln); xfree(state); return -1; } debug(20, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n", state->new, state->fd); storeDiskdWriteSwapLogheader(state->fd);#if HAVE_FCHMOD if (stat(state->cur, &sb) == 0) fchmod(state->fd, sb.st_mode);#endif sd->log.clean.write = storeDiskdDirWriteCleanEntry; sd->log.clean.state = state; return 0;}/* * Get the next entry that is a candidate for clean log writing */const StoreEntry *storeDiskdDirCleanLogNextEntry(SwapDir * sd){ const StoreEntry *entry = NULL; struct _clean_state *state = sd->log.clean.state; if (state->walker) entry = state->walker->Next(state->walker); return entry;}/* * "write" an entry to the clean log file. */static voidstoreDiskdDirWriteCleanEntry(SwapDir * sd, const StoreEntry * e){ storeSwapLogData s; static size_t ss = sizeof(storeSwapLogData); struct _clean_state *state = sd->log.clean.state; memset(&s, '\0', ss); s.op = (char) SWAP_LOG_ADD; s.swap_filen = e->swap_filen; s.timestamp = e->timestamp; s.lastref = e->lastref; s.expires = e->expires; s.lastmod = e->lastmod; s.swap_file_sz = e->swap_file_sz; s.refcount = e->refcount; s.flags = e->flags; xmemcpy(&s.key, e->hash.key, MD5_DIGEST_CHARS); xmemcpy(state->outbuf + state->outbuf_offset, &s, ss); state->outbuf_offset += ss; /* buffered write */ if (state->outbuf_offset + ss > CLEAN_BUF_SZ) { if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n", state->new, xstrerror()); debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n"); file_close(state->fd); state->fd = -1; unlink(state->new); safe_free(state); sd->log.clean.state = NULL; sd->log.clean.write = NULL; return; } state->outbuf_offset = 0; }}static voidstoreDiskdDirWriteCleanDone(SwapDir * sd){ struct _clean_state *state = sd->log.clean.state; if (NULL == state) return; if (state->fd < 0) return; state->walker->Done(state->walker); if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n", state->new, xstrerror()); debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile " "not replaced.\n"); file_close(state->fd); state->fd = -1; unlink(state->new); } safe_free(state->outbuf); /* * You can't rename open files on Microsoft "operating systems" * so we have to close before renaming. */ storeDiskdDirCloseSwapLog(sd); /* rename */ if (state->fd >= 0) {#ifdef _SQUID_OS2_ file_close(state->fd); state->fd = -1;#endif xrename(state->new, state->cur); } /* touch a timestamp file if we're not still validating */ if (store_dirs_rebuilding) (void) 0; else if (state->fd < 0) (void) 0; else file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)); /* close */ safe_free(state->cur); safe_free(state->new); safe_free(state->cln); if (state->fd >= 0) file_close(state->fd); state->fd = -1; safe_free(state); sd->log.clean.state = NULL; sd->log.clean.write = NULL;}static voidstoreDiskdDirSwapLog(const SwapDir * sd, const StoreEntry * e, int op){ diskdinfo_t *diskdinfo = sd->fsdata; storeSwapLogData *s = memAllocate(MEM_SWAP_LOG_DATA); s->op = (char) op; s->swap_filen = e->swap_filen; s->timestamp = e->timestamp; s->lastref = e->lastref; s->expires = e->expires; s->lastmod = e->lastmod; s->swap_file_sz = e->swap_file_sz; s->refcount = e->refcount; s->flags = e->flags; xmemcpy(s->key, e->hash.key, MD5_DIGEST_CHARS); file_write(diskdinfo->swaplog_fd, -1, s, sizeof(storeSwapLogData), NULL, NULL, (FREE *) storeSwapLogDataFree);}static voidstoreDiskdDirNewfs(SwapDir * sd){ debug(47, 3) ("Creating swap space in %s\n", sd->path); storeDiskdDirCreateDirectory(sd->path, 0); storeDiskdDirCreateSwapSubDirs(sd);}static intrev_int_sort(const void *A, const void *B){ const int *i1 = A; const int *i2 = B; return *i2 - *i1;}static intstoreDiskdDirClean(int swap_index){ DIR *dp = NULL; struct dirent *de = NULL; LOCAL_ARRAY(char, p1, MAXPATHLEN + 1); LOCAL_ARRAY(char, p2, MAXPATHLEN + 1);#if USE_TRUNCATE struct stat sb;#endif int files[20]; int swapfileno; int fn; /* same as swapfileno, but with dirn bits set */ int n = 0; int k = 0; int N0, N1, N2; int D0, D1, D2; SwapDir *SD; diskdinfo_t *diskdinfo; N0 = n_diskd_dirs; D0 = diskd_dir_index[swap_index % N0]; SD = &Config.cacheSwap.swapDirs[D0]; diskdinfo = SD->fsdata; N1 = diskdinfo->l1; D1 = (swap_index / N0) % N1; N2 = diskdinfo->l2; D2 = ((swap_index / N0) / N1) % N2; snprintf(p1, SQUID_MAXPATHLEN, "%s/%02X/%02X", Config.cacheSwap.swapDirs[D0].path, D1, D2); debug(36, 3) ("storeDirClean: Cleaning directory %s\n", p1); dp = opendir(p1); if (dp == NULL) { if (errno == ENOENT) { debug(36, 0) ("storeDirClean: WARNING: Creating %s\n", p1); if (mkdir(p1, 0777) == 0) return 0; } debug(50, 0) ("storeDirClean: %s: %s\n", p1, xstrerror()); safeunlink(p1, 1); return 0; } while ((de = readdir(dp)) != NULL && k < 20) { if (sscanf(de->d_name, "%X", &swapfileno) != 1) continue; fn = swapfileno; /* XXX should remove this cruft ! */ if (storeDiskdDirValidFileno(SD, fn, 1)) if (storeDiskdDirMapBitTest(SD, fn)) if (storeDiskdFilenoBelongsHere(fn, D0, D1, D2)) continue;#if USE_TRUNCATE if (!stat(de->d_name, &sb)) if (sb.st_size == 0) continue;#endif files[k++] = swapfileno; } closedir(dp); if (k == 0) return 0; qsort(files, k, sizeof(int), rev_int_sort); if (k > 10) k = 10; for (n = 0; n < k; n++) { debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]); snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]);#if USE_TRUNCATE truncate(p2, 0);#else safeunlink(p2, 0);#endif statCounter.swap.files_cleaned++; } debug(36, 3) ("Cleaned %d unused files from %s\n", k, p1); return k;}static voidstoreDiskdDirCleanEvent(void *unused){ static int swap_index = 0; int i; int j = 0; int n = 0; /* * Assert that there are DISKD cache_dirs configured, otherwise * we should never be called. */ assert(n_diskd_dirs); if (NULL == diskd_dir_index) { SwapDir *sd; diskdinfo_t *diskdinfo; /* * Initialize the little array that translates DISKD cache_dir * number into the Config.cacheSwap.swapDirs array index. */ diskd_dir_index = xcalloc(n_diskd_dirs, sizeof(*diskd_dir_index)); for (i = 0, n = 0; i < Config.cacheSwap.n_configured; i++) { sd = &Config.cacheSwap.swapDirs[i]; if (!storeDiskdDirIs(sd)) continue; diskd_dir_index[n++] = i; diskdinfo = sd->fsdata; j += (diskdinfo->l1 * diskdinfo->l2); } assert(n == n_diskd_dirs); /* * Start the storeDiskdDirClean() swap_index with a random * value. j equals the total number of DISKD level 2 * swap directories */ swap_index = (int) (squid_random() % j); } if (0 == store_dirs_rebuilding) { n = storeDiskdDirClean(swap_index); swap_index++; } eventAdd("storeDirClean", storeDiskdDirCleanEvent, NULL, 15.0 * exp(-0.25 * n), 1);}static intstoreDiskdDirIs(SwapDir * sd){ if (strncmp(sd->type, "diskd", 3) == 0) return 1; return 0;}/* * Does swapfile number 'fn' belong in cachedir #F0, * level1 dir #F1, level2 dir #F2? */static intstoreDiskdFilenoBelongsHere(int fn, int F0, int F1, int F2){ int D1, D2; int L1, L2; int filn = fn; diskdinfo_t *diskdinfo; assert(F0 < Config.cacheSwap.n_configured); diskdinfo = Config.cacheSwap.swapDirs[F0].fsdata; L1 = diskdinfo->l1; L2 = diskdinfo->l2; D1 = ((filn / L2) / L2) % L1; if (F1 != D1) return 0; D2 = (filn / L2) % L2; if (F2 != D2) return 0; return 1;}int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -