📄 store_dir_ufs.c
字号:
} if (rb->td != NULL) closedir(rb->td); rb->td = NULL; rb->in_dir = 0; if (++rb->curlvl2 < ufsinfo->l2) continue; rb->curlvl2 = 0; if (++rb->curlvl1 < ufsinfo->l1) continue; rb->curlvl1 = 0; rb->done = 1; } *filn_p = rb->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 *storeUfsDirAddDiskRestore(SwapDir * SD, const cache_key * key, int file_number, squid_file_sz 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(47, 5) ("storeUfsAddDiskRestore: %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_filen = file_number; e->swap_dirn = SD->index; e->swap_file_sz = swap_file_sz; e->lock_count = 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); storeUfsDirMapBitSet(SD, e->swap_filen); storeHashInsert(e, key); /* do it after we clear KEY_PRIVATE */ storeUfsDirReplAdd(SD, e); return e;}CBDATA_TYPE(RebuildState);static voidstoreUfsDirRebuild(SwapDir * sd){ RebuildState *rb; int clean = 0; int zero = 0; FILE *fp; EVH *func = NULL; CBDATA_INIT_TYPE(RebuildState); rb = cbdataAlloc(RebuildState); rb->sd = sd; rb->speed = opt_foreground_rebuild ? 1 << 30 : 50; /* * If the swap.state file exists in the cache_dir, then * we'll use storeUfsDirRebuildFromSwapLog(), otherwise we'll * use storeUfsDirRebuildFromDirectory() to open up each file * and suck in the meta data. */ fp = storeUfsDirOpenTmpSwapLog(sd, &clean, &zero); if (fp == NULL || zero) { if (fp != NULL) fclose(fp); func = storeUfsDirRebuildFromDirectory; } else { func = storeUfsDirRebuildFromSwapLogCheckVersion; rb->log = fp; rb->flags.clean = (unsigned int) clean; } if (!clean) rb->flags.need_to_validate = 1; debug(47, 1) ("Rebuilding storage in %s (%s)\n", sd->path, clean ? "CLEAN" : "DIRTY"); store_dirs_rebuilding++; eventAdd("storeRebuild", func, rb, 0.0, 1);}static voidstoreUfsDirCloseTmpSwapLog(SwapDir * sd){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; char *swaplog_path = xstrdup(storeUfsDirSwapLogFile(sd, NULL)); char *new_path = xstrdup(storeUfsDirSwapLogFile(sd, ".new")); int fd; file_close(ufsinfo->swaplog_fd); if (xrename(new_path, swaplog_path) < 0) { fatal("storeUfsDirCloseTmpSwapLog: rename failed"); } fd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY); if (fd < 0) { debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror()); fatal("storeUfsDirCloseTmpSwapLog: Failed to open swap log."); } safe_free(swaplog_path); safe_free(new_path); ufsinfo->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 voidstoreUfsWriteSwapLogheader(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 *storeUfsDirOpenTmpSwapLog(SwapDir * sd, int *clean_flag, int *zero_flag){ ufsinfo_t *ufsinfo = (ufsinfo_t *) sd->fsdata; char *swaplog_path = xstrdup(storeUfsDirSwapLogFile(sd, NULL)); char *clean_path = xstrdup(storeUfsDirSwapLogFile(sd, ".last-clean")); char *new_path = xstrdup(storeUfsDirSwapLogFile(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 (ufsinfo->swaplog_fd >= 0) file_close(ufsinfo->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."); } ufsinfo->swaplog_fd = fd; storeUfsWriteSwapLogheader(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 UFS this means * opening some log files and allocating write buffers. Return 0 if * we succeed, and assign the 'func' and 'data' return pointers. */static intstoreUfsDirWriteCleanStart(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(storeUfsDirSwapLogFile(sd, ".clean")); state->fd = file_open(state->new, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); if (state->fd < 0) { debug(50, 0) ("storeDirWriteCleanStart: %s: open: %s\n", state->new, xstrerror()); debug(50, 0) ("storeDirWriteCleanStart: Current swap logfile " "not replaced.\n"); xfree(state->new); xfree(state); return -1; } storeUfsWriteSwapLogheader(state->fd); state->cur = xstrdup(storeUfsDirSwapLogFile(sd, NULL)); state->cln = xstrdup(storeUfsDirSwapLogFile(sd, ".last-clean")); state->outbuf = xcalloc(CLEAN_BUF_SZ, 1); state->outbuf_offset = 0; state->walker = sd->repl->WalkInit(sd->repl); unlink(state->cln); debug(47, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n", state->new, state->fd);#if HAVE_FCHMOD if (stat(state->cur, &sb) == 0) fchmod(state->fd, sb.st_mode);#endif sd->log.clean.write = storeUfsDirWriteCleanEntry; sd->log.clean.state = state; return 0;}/* * Get the next entry that is a candidate for clean log writing */const StoreEntry *storeUfsDirCleanLogNextEntry(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 voidstoreUfsDirWriteCleanEntry(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(50, 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 voidstoreUfsDirWriteCleanDone(SwapDir * sd){ int fd; 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(50, 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. */ storeUfsDirCloseSwapLog(sd); /* save the fd value for a later test */ fd = state->fd; /* rename */ if (state->fd >= 0) {#if defined(_SQUID_OS2_) || defined(_SQUID_WIN32_) 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 (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 voidstoreUfsDirSwapLog(const SwapDir * sd, const StoreEntry * e, int op){ ufsinfo_t *ufsinfo = (ufsinfo_t *) 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(ufsinfo->swaplog_fd, -1, s, sizeof(storeSwapLogData), NULL, NULL, (FREE *) storeSwapLogDataFree);}static voidstoreUfsDirNewfs(SwapDir * sd){ debug(47, 3) ("Creating swap space in %s\n", sd->path); storeUfsDirCreateDirectory(sd->path, 0); storeUfsDirCreateSwapSubDirs(sd);}static intrev_int_sort(const void *A, const void *B){ const int *i1 = A; const int *i2 = B; return *i2 - *i1;}static intstoreUfsDirClean(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; ufsinfo_t *ufsinfo; N0 = n_ufs_dirs; D0 = ufs_dir_index[swap_index % N0]; SD = &Config.cacheSwap.swapDirs[D0]; ufsinfo = (ufsinfo_t *) SD->fsdata; N1 = ufsinfo->l1; D1 = (swap_index / N0) % N1; N2 = ufsinfo->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);#ifdef _SQUID_MSWIN_ if (mkdir(p1) == 0)#else if (mkdir(p1, 0777) == 0)#endif 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 (storeUfsDirValidFileno(SD, fn, 1)) if (storeUfsDirMapBitTest(SD, fn)) if (storeUfsFilenoBelongsHere(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 voidstoreUfsDirCleanEvent(void *unused){ static int swap_index = 0; int i; int j = 0; int n = 0; /* * Assert that there are UFS cache_dirs configured, otherwise * we should never be called. */ assert(n_ufs_dirs); if (NULL == ufs_dir_index) { SwapDir *sd; ufsinfo_t *ufsinfo; /* * Initialize the little array that translates UFS cache_dir * number into the Config.cacheSwap.swapDirs array index.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -