store_dir.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:24k
- /*
- * $Id: store_dir.c,v 1.84.2.1 1999/02/14 00:23:11 wessels Exp $
- *
- * DEBUG: section 47 Store Directory Routines
- * AUTHOR: Duane Wessels
- *
- * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from the
- * Internet community. Development is led by Duane Wessels of the
- * National Laboratory for Applied Network Research and funded by the
- * National Science Foundation. Squid is Copyrighted (C) 1998 by
- * Duane Wessels and the University of California San Diego. Please
- * see the COPYRIGHT file for full details. Squid incorporates
- * software developed and/or copyrighted by other sources. Please see
- * the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- */
- #include "squid.h"
- #if HAVE_STATVFS
- #if HAVE_SYS_STATVFS_H
- #include <sys/statvfs.h>
- #endif
- #endif
- #define SWAP_DIR_SHIFT 24
- #define SWAP_FILE_MASK 0x00FFFFFF
- #define DefaultLevelOneDirs 16
- #define DefaultLevelTwoDirs 256
- static char *storeSwapSubDir(int dirn, int subdirn);
- static int storeDirSelectSwapDir(void);
- static int storeVerifyDirectory(const char *path);
- static int storeCreateDirectory(const char *path, int);
- static void storeCreateSwapSubDirs(int j);
- /* return full name to swapfile */
- char *
- storeSwapFullPath(int fn, char *fullpath)
- {
- LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
- int dirn = (fn >> SWAP_DIR_SHIFT) % Config.cacheSwap.n_configured;
- int filn = fn & SWAP_FILE_MASK;
- int L1 = Config.cacheSwap.swapDirs[dirn].l1;
- int L2 = Config.cacheSwap.swapDirs[dirn].l2;
- if (!fullpath)
- fullpath = fullfilename;
- fullpath[0] = ' ';
- snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X/%08X",
- Config.cacheSwap.swapDirs[dirn].path,
- ((filn / L2) / L2) % L1,
- (filn / L2) % L2,
- filn);
- return fullpath;
- }
- static char *
- storeSwapSubDir(int dirn, int subdirn)
- {
- LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
- SwapDir *SD;
- assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
- SD = &Config.cacheSwap.swapDirs[dirn];
- assert(0 <= subdirn && subdirn < SD->l1);
- snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%02X",
- Config.cacheSwap.swapDirs[dirn].path,
- subdirn);
- return fullfilename;
- }
- char *
- storeSwapSubSubDir(int fn, char *fullpath)
- {
- LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
- int dirn = (fn >> SWAP_DIR_SHIFT) % Config.cacheSwap.n_configured;
- int filn = fn & SWAP_FILE_MASK;
- int L1 = Config.cacheSwap.swapDirs[dirn].l1;
- int L2 = Config.cacheSwap.swapDirs[dirn].l2;
- if (!fullpath)
- fullpath = fullfilename;
- fullpath[0] = ' ';
- snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
- Config.cacheSwap.swapDirs[dirn].path,
- ((filn / L2) / L2) % L1,
- (filn / L2) % L2);
- return fullpath;
- }
- /*
- * Does swapfile number 'fn' belong in cachedir #F0,
- * level1 dir #F1, level2 dir #F2?
- *
- * This is called by storeDirClean(), but placed here because
- * the algorithm needs to match storeSwapSubSubDir().
- *
- * Don't check that (fn >> SWAP_DIR_SHIFT) == F0 because
- * 'fn' may not have the directory bits set.
- */
- int
- storeFilenoBelongsHere(int fn, int F0, int F1, int F2)
- {
- int D1, D2;
- int L1, L2;
- int filn = fn & SWAP_FILE_MASK;
- assert(F0 < Config.cacheSwap.n_configured);
- L1 = Config.cacheSwap.swapDirs[F0].l1;
- L2 = Config.cacheSwap.swapDirs[F0].l2;
- D1 = ((filn / L2) / L2) % L1;
- if (F1 != D1)
- return 0;
- D2 = (filn / L2) % L2;
- if (F2 != D2)
- return 0;
- return 1;
- }
- static int
- storeCreateDirectory(const char *path, int should_exist)
- {
- int created = 0;
- struct stat st;
- getCurrentTime();
- if (0 == stat(path, &st)) {
- if (S_ISDIR(st.st_mode)) {
- debug(20, should_exist ? 3 : 1) ("%s existsn", path);
- } else {
- fatalf("Swap directory %s is not a directory.", path);
- }
- } else if (0 == mkdir(path, 0755)) {
- debug(20, should_exist ? 1 : 3) ("%s createdn", path);
- created = 1;
- } else {
- fatalf("Failed to make swap directory %s: %s",
- path, xstrerror());
- }
- return created;
- }
- static int
- storeVerifyDirectory(const char *path)
- {
- struct stat sb;
- if (stat(path, &sb) < 0) {
- debug(20, 0) ("%s: %sn", path, xstrerror());
- return -1;
- }
- if (S_ISDIR(sb.st_mode) == 0) {
- debug(20, 0) ("%s is not a directoryn", path);
- return -1;
- }
- return 0;
- }
- /*
- * This function is called by storeInit(). If this returns < 0,
- * then Squid exits, complains about swap directories not
- * existing, and instructs the admin to run 'squid -z'
- */
- int
- storeVerifyCacheDirs(void)
- {
- int i;
- int j;
- const char *path;
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- path = Config.cacheSwap.swapDirs[i].path;
- if (storeVerifyDirectory(path) < 0)
- return -1;
- for (j = 0; j < Config.cacheSwap.swapDirs[i].l1; j++) {
- path = storeSwapSubDir(i, j);
- if (storeVerifyDirectory(path) < 0)
- return -1;
- }
- }
- return 0;
- }
- void
- storeCreateSwapDirectories(void)
- {
- int i;
- const char *path = NULL;
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- path = Config.cacheSwap.swapDirs[i].path;
- debug(47, 3) ("Creating swap space in %sn", path);
- storeCreateDirectory(path, 0);
- storeCreateSwapSubDirs(i);
- }
- }
- static void
- storeCreateSwapSubDirs(int j)
- {
- int i, k;
- int should_exist;
- SwapDir *SD = &Config.cacheSwap.swapDirs[j];
- LOCAL_ARRAY(char, name, MAXPATHLEN);
- for (i = 0; i < SD->l1; i++) {
- snprintf(name, MAXPATHLEN, "%s/%02X", SD->path, i);
- if (storeCreateDirectory(name, 0))
- should_exist = 0;
- else
- should_exist = 1;
- debug(47, 1) ("Making directories in %sn", name);
- for (k = 0; k < SD->l2; k++) {
- snprintf(name, MAXPATHLEN, "%s/%02X/%02X", SD->path, i, k);
- storeCreateDirectory(name, should_exist);
- }
- }
- }
- /*
- *Spread load across least 3/4 of the store directories
- */
- static int
- storeDirSelectSwapDir(void)
- {
- double least_used = 1.0;
- double high = (double) Config.Swap.highWaterMark / 100.0;
- double u;
- int dirn;
- int i, j;
- SwapDir *SD;
- static int nleast = 0;
- static int nconf = 0;
- static int *dirq = NULL;
- static double *diru = NULL;
- /*
- * Handle simplest case of a single swap directory immediately
- */
- if (Config.cacheSwap.n_configured == 1)
- return 0;
- /*
- * Initialise dirq on the first call or on change of number of dirs
- */
- if (nconf != Config.cacheSwap.n_configured) {
- nconf = Config.cacheSwap.n_configured;
- nleast = (nconf * 3) / 4;
- safe_free(dirq);
- dirq = (int *) xmalloc(sizeof(int) * nleast);
- safe_free(diru);
- diru = (double *) xmalloc(sizeof(double) * nconf);
- for (j = 0; j < nleast; j++)
- dirq[j] = -1;
- }
- /*
- * Scan for a non-negative dirn in the dirq array and return that one
- */
- dirn = -1;
- for (j = 0; j < nleast; j++) {
- dirn = dirq[j];
- if (dirn < 0)
- continue;
- dirq[j] = -1;
- break;
- }
- /*
- * If we found a valid dirn return it
- */
- if (dirn >= 0)
- return dirn;
- /*
- * Now for the real guts of the algorithm - building the dirq array
- */
- for (i = 0; i < nconf; i++) {
- diru[i] = 1.1;
- SD = &Config.cacheSwap.swapDirs[i];
- SD->flags.selected = 0;
- if (SD->flags.read_only)
- continue;
- u = (double) SD->cur_size / SD->max_size;
- if (u > high)
- continue;
- diru[i] = u;
- }
- for (j = 0; j < nleast; j++) {
- dirq[j] = -1;
- least_used = 1.0;
- dirn = -1;
- for (i = 0; i < nconf; i++) {
- if (diru[i] < least_used) {
- least_used = diru[i];
- dirn = i;
- }
- }
- if (dirn < 0)
- break;
- dirq[j] = dirn;
- diru[dirn] = 1.1;
- /* set selected flag for debugging/cachemgr only */
- Config.cacheSwap.swapDirs[dirn].flags.selected = 1;
- }
- /*
- * Setup default return of 0 if no least found
- */
- if (dirq[0] < 0)
- dirq[0] = 0;
- dirn = dirq[0];
- dirq[0] = -1;
- return dirn;
- }
- int
- storeDirValidFileno(int fn)
- {
- int dirn = fn >> SWAP_DIR_SHIFT;
- int filn = fn & SWAP_FILE_MASK;
- if (dirn > Config.cacheSwap.n_configured)
- return 0;
- if (dirn < 0)
- return 0;
- if (filn < 0)
- return 0;
- if (filn > Config.cacheSwap.swapDirs[dirn].map->max_n_files)
- return 0;
- return 1;
- }
- int
- storeDirMapBitTest(int fn)
- {
- int dirn = fn >> SWAP_DIR_SHIFT;
- int filn = fn & SWAP_FILE_MASK;
- return file_map_bit_test(Config.cacheSwap.swapDirs[dirn].map, filn);
- }
- void
- storeDirMapBitSet(int fn)
- {
- int dirn = fn >> SWAP_DIR_SHIFT;
- int filn = fn & SWAP_FILE_MASK;
- file_map_bit_set(Config.cacheSwap.swapDirs[dirn].map, filn);
- }
- void
- storeDirMapBitReset(int fn)
- {
- int dirn = fn >> SWAP_DIR_SHIFT;
- int filn = fn & SWAP_FILE_MASK;
- file_map_bit_reset(Config.cacheSwap.swapDirs[dirn].map, filn);
- }
- int
- storeDirMapAllocate(void)
- {
- int dirn = storeDirSelectSwapDir();
- SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
- int filn = file_map_allocate(SD->map, SD->suggest);
- SD->suggest = filn + 1;
- return (dirn << SWAP_DIR_SHIFT) | (filn & SWAP_FILE_MASK);
- }
- char *
- storeSwapDir(int dirn)
- {
- assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
- return Config.cacheSwap.swapDirs[dirn].path;
- }
- int
- storeDirNumber(int swap_file_number)
- {
- return swap_file_number >> SWAP_DIR_SHIFT;
- }
- int
- storeDirProperFileno(int dirn, int fn)
- {
- return (dirn << SWAP_DIR_SHIFT) | (fn & SWAP_FILE_MASK);
- }
- /*
- * An entry written to the swap log MUST have the following
- * properties.
- * 1. It MUST be a public key. It does no good to log
- * a public ADD, change the key, then log a private
- * DEL. So we need to log a DEL before we change a
- * key from public to private.
- * 2. It MUST have a valid (> -1) swap_file_number.
- */
- void
- storeDirSwapLog(const StoreEntry * e, int op)
- {
- storeSwapLogData *s;
- int dirn;
- dirn = e->swap_file_number >> SWAP_DIR_SHIFT;
- assert(dirn < Config.cacheSwap.n_configured);
- assert(!EBIT_TEST(e->flags, KEY_PRIVATE));
- assert(e->swap_file_number >= 0);
- /*
- * icons and such; don't write them to the swap log
- */
- if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
- return;
- assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
- debug(20, 3) ("storeDirSwapLog: %s %s %08Xn",
- swap_log_op_str[op],
- storeKeyText(e->key),
- e->swap_file_number);
- s = xcalloc(1, sizeof(storeSwapLogData));
- s->op = (char) op;
- s->swap_file_number = e->swap_file_number;
- 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->key, MD5_DIGEST_CHARS);
- file_write(Config.cacheSwap.swapDirs[dirn].swaplog_fd,
- -1,
- s,
- sizeof(storeSwapLogData),
- NULL,
- NULL,
- xfree);
- }
- char *
- storeDirSwapLogFile(int dirn, const char *ext)
- {
- LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN);
- LOCAL_ARRAY(char, digit, 32);
- if (Config.Log.swap) {
- xstrncpy(path, Config.Log.swap, SQUID_MAXPATHLEN - 64);
- strcat(path, ".");
- snprintf(digit, 32, "%02d", dirn);
- strncat(path, digit, 3);
- } else {
- xstrncpy(path, storeSwapDir(dirn), SQUID_MAXPATHLEN - 64);
- strcat(path, "/swap.state");
- }
- if (ext)
- strncat(path, ext, 16);
- return path;
- }
- void
- storeDirOpenSwapLogs(void)
- {
- int i;
- char *path;
- int fd;
- SwapDir *SD;
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];
- path = storeDirSwapLogFile(i, NULL);
- fd = file_open(path, O_WRONLY | O_CREAT, NULL, NULL, NULL);
- if (fd < 0) {
- debug(50, 1) ("%s: %sn", path, xstrerror());
- fatal("storeDirOpenSwapLogs: Failed to open swap log.");
- }
- debug(47, 3) ("Cache Dir #%d log opened on FD %dn", i, fd);
- SD->swaplog_fd = fd;
- }
- }
- void
- storeDirCloseSwapLogs(void)
- {
- int i;
- SwapDir *SD;
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];
- if (SD->swaplog_fd < 0) /* not open */
- continue;
- file_close(SD->swaplog_fd);
- debug(47, 3) ("Cache Dir #%d log closed on FD %dn", i, SD->swaplog_fd);
- SD->swaplog_fd = -1;
- }
- }
- FILE *
- storeDirOpenTmpSwapLog(int dirn, int *clean_flag, int *zero_flag)
- {
- char *swaplog_path = xstrdup(storeDirSwapLogFile(dirn, NULL));
- char *clean_path = xstrdup(storeDirSwapLogFile(dirn, ".last-clean"));
- char *new_path = xstrdup(storeDirSwapLogFile(dirn, ".new"));
- struct stat log_sb;
- struct stat clean_sb;
- SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
- FILE *fp;
- int fd;
- if (stat(swaplog_path, &log_sb) < 0) {
- debug(47, 1) ("Cache Dir #%d: No log filen", dirn);
- 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 (SD->swaplog_fd >= 0)
- file_close(SD->swaplog_fd);
- /* open a write-only FD for the new log */
- fd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL, NULL);
- if (fd < 0) {
- debug(50, 1) ("%s: %sn", new_path, xstrerror());
- fatal("storeDirOpenTmpSwapLog: Failed to open swap log.");
- }
- SD->swaplog_fd = fd;
- /* open a read-only stream of the old log */
- fp = fopen(swaplog_path, "r");
- if (fp == NULL) {
- debug(50, 0) ("%s: %sn", swaplog_path, xstrerror());
- fatal("Failed to open swap log for reading");
- }
- memset(&clean_sb, ' ', 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;
- }
- void
- storeDirCloseTmpSwapLog(int dirn)
- {
- char *swaplog_path = xstrdup(storeDirSwapLogFile(dirn, NULL));
- char *new_path = xstrdup(storeDirSwapLogFile(dirn, ".new"));
- SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
- int fd;
- file_close(SD->swaplog_fd);
- #ifdef _SQUID_OS2_
- if (unlink(swaplog_path) < 0) {
- debug(50, 0) ("%s: %sn", swaplog_path, xstrerror());
- fatal("storeDirCloseTmpSwapLog: unlink failed");
- }
- #endif
- if (rename(new_path, swaplog_path) < 0) {
- debug(50, 0) ("%s,%s: %sn", new_path, swaplog_path, xstrerror());
- fatal("storeDirCloseTmpSwapLog: rename failed");
- }
- fd = file_open(swaplog_path, O_WRONLY | O_CREAT, NULL, NULL, NULL);
- if (fd < 0) {
- debug(50, 1) ("%s: %sn", swaplog_path, xstrerror());
- fatal("storeDirCloseTmpSwapLog: Failed to open swap log.");
- }
- safe_free(swaplog_path);
- safe_free(new_path);
- SD->swaplog_fd = fd;
- debug(47, 3) ("Cache Dir #%d log opened on FD %dn", dirn, fd);
- }
- void
- storeDirUpdateSwapSize(int fn, size_t size, int sign)
- {
- int dirn = (fn >> SWAP_DIR_SHIFT) % Config.cacheSwap.n_configured;
- int k = ((size + 1023) >> 10) * sign;
- Config.cacheSwap.swapDirs[dirn].cur_size += k;
- store_swap_size += k;
- if (sign > 0)
- n_disk_objects++;
- else if (sign < 0)
- n_disk_objects--;
- }
- void
- storeDirStats(StoreEntry * sentry)
- {
- int i;
- SwapDir *SD;
- #if HAVE_STATVFS
- struct statvfs sfs;
- #endif
- storeAppendPrintf(sentry, "Store Directory Statistics:n");
- storeAppendPrintf(sentry, "Store Entries : %dn",
- memInUse(MEM_STOREENTRY));
- storeAppendPrintf(sentry, "Maximum Swap Size : %8d KBn",
- Config.Swap.maxSize);
- storeAppendPrintf(sentry, "Current Store Swap Size: %8d KBn",
- store_swap_size);
- storeAppendPrintf(sentry, "Current Capacity : %d%% used, %d%% freen",
- percent((int) store_swap_size, (int) Config.Swap.maxSize),
- percent((int) (Config.Swap.maxSize - store_swap_size), (int) Config.Swap.maxSize));
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];
- storeAppendPrintf(sentry, "n");
- storeAppendPrintf(sentry, "Store Directory #%d: %sn", i, SD->path);
- storeAppendPrintf(sentry, "First level subdirectories: %dn", SD->l1);
- storeAppendPrintf(sentry, "Second level subdirectories: %dn", SD->l2);
- storeAppendPrintf(sentry, "Maximum Size: %d KBn", SD->max_size);
- storeAppendPrintf(sentry, "Current Size: %d KBn", SD->cur_size);
- storeAppendPrintf(sentry, "Percent Used: %0.2f%%n",
- 100.0 * SD->cur_size / SD->max_size);
- storeAppendPrintf(sentry, "Filemap bits in use: %d of %d (%d%%)n",
- SD->map->n_files_in_map, SD->map->max_n_files,
- percent(SD->map->n_files_in_map, SD->map->max_n_files));
- #if HAVE_STATVFS
- #define fsbtoblk(num, fsbs, bs)
- (((fsbs) != 0 && (fsbs) < (bs)) ?
- (num) / ((bs) / (fsbs)) : (num) * ((fsbs) / (bs)))
- if (!statvfs(SD->path, &sfs)) {
- storeAppendPrintf(sentry, "Filesystem Space in use: %d/%d KB (%d%%)n",
- fsbtoblk((sfs.f_blocks - sfs.f_bfree), sfs.f_frsize, 1024),
- fsbtoblk(sfs.f_blocks, sfs.f_frsize, 1024),
- percent(sfs.f_blocks - sfs.f_bfree, sfs.f_blocks));
- storeAppendPrintf(sentry, "Filesystem Inodes in use: %d/%d (%d%%)n",
- sfs.f_files - sfs.f_ffree, sfs.f_files,
- percent(sfs.f_files - sfs.f_ffree, sfs.f_files));
- }
- #endif
- storeAppendPrintf(sentry, "Flags:");
- if (SD->flags.selected)
- storeAppendPrintf(sentry, " SELECTED");
- if (SD->flags.read_only)
- storeAppendPrintf(sentry, " READ-ONLY");
- storeAppendPrintf(sentry, "n");
- }
- }
- int
- storeDirMapBitsInUse(void)
- {
- int i;
- int n = 0;
- for (i = 0; i < Config.cacheSwap.n_configured; i++)
- n += Config.cacheSwap.swapDirs[i].map->n_files_in_map;
- return n;
- }
- /*
- * storeDirWriteCleanLogs
- *
- * Writes a "clean" swap log file from in-memory metadata.
- */
- #define CLEAN_BUF_SZ 16384
- int
- storeDirWriteCleanLogs(int reopen)
- {
- StoreEntry *e = NULL;
- int *fd;
- int n = 0;
- time_t start, stop, r;
- struct stat sb;
- char **cur;
- char **new;
- char **cln;
- int dirn;
- int N = Config.cacheSwap.n_configured;
- dlink_node *m;
- char **outbuf;
- off_t *outbufoffset;
- storeSwapLogData s;
- size_t ss = sizeof(storeSwapLogData);
- if (store_rebuilding) {
- debug(20, 1) ("Not currently OK to rewrite swap log.n");
- debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.n");
- return 0;
- }
- debug(20, 1) ("storeDirWriteCleanLogs: Starting...n");
- start = squid_curtime;
- fd = xcalloc(N, sizeof(int));
- cur = xcalloc(N, sizeof(char *));
- new = xcalloc(N, sizeof(char *));
- cln = xcalloc(N, sizeof(char *));
- for (dirn = 0; dirn < N; dirn++) {
- fd[dirn] = -1;
- cur[dirn] = xstrdup(storeDirSwapLogFile(dirn, NULL));
- new[dirn] = xstrdup(storeDirSwapLogFile(dirn, ".clean"));
- cln[dirn] = xstrdup(storeDirSwapLogFile(dirn, ".last-clean"));
- unlink(new[dirn]);
- unlink(cln[dirn]);
- fd[dirn] = file_open(new[dirn],
- O_WRONLY | O_CREAT | O_TRUNC,
- NULL,
- NULL,
- NULL);
- if (fd[dirn] < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: %sn", new[dirn], xstrerror());
- continue;
- }
- debug(20, 3) ("storeDirWriteCleanLogs: opened %s, FD %dn",
- new[dirn], fd[dirn]);
- #if HAVE_FCHMOD
- if (stat(cur[dirn], &sb) == 0)
- fchmod(fd[dirn], sb.st_mode);
- #endif
- }
- outbuf = xcalloc(N, sizeof(char *));
- outbufoffset = xcalloc(N, sizeof(*outbufoffset));
- for (dirn = 0; dirn < N; dirn++) {
- outbuf[dirn] = xcalloc(CLEAN_BUF_SZ, 1);
- outbufoffset[dirn] = 0;
- }
- for (m = store_list.tail; m; m = m->prev) {
- e = m->data;
- if (e->swap_file_number < 0)
- continue;
- if (e->swap_status != SWAPOUT_DONE)
- continue;
- if (e->swap_file_sz <= 0)
- continue;
- if (EBIT_TEST(e->flags, RELEASE_REQUEST))
- continue;
- if (EBIT_TEST(e->flags, KEY_PRIVATE))
- continue;
- if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
- continue;
- dirn = storeDirNumber(e->swap_file_number);
- assert(dirn < N);
- if (fd[dirn] < 0)
- continue;
- memset(&s, ' ', ss);
- s.op = (char) SWAP_LOG_ADD;
- s.swap_file_number = e->swap_file_number;
- 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->key, MD5_DIGEST_CHARS);
- xmemcpy(outbuf[dirn] + outbufoffset[dirn], &s, ss);
- outbufoffset[dirn] += ss;
- /* buffered write */
- if (outbufoffset[dirn] + ss > CLEAN_BUF_SZ) {
- if (write(fd[dirn], outbuf[dirn], outbufoffset[dirn]) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %sn",
- new[dirn], xstrerror());
- debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.n");
- file_close(fd[dirn]);
- fd[dirn] = -1;
- unlink(new[dirn]);
- continue;
- }
- outbufoffset[dirn] = 0;
- }
- if ((++n & 0xFFFF) == 0) {
- getCurrentTime();
- debug(20, 1) (" %7d entries written so far.n", n);
- }
- }
- /* flush */
- for (dirn = 0; dirn < N; dirn++) {
- if (outbufoffset[dirn] == 0)
- continue;
- if (fd[dirn] < 0)
- continue;
- if (write(fd[dirn], outbuf[dirn], outbufoffset[dirn]) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %sn",
- new[dirn], xstrerror());
- debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.n");
- file_close(fd[dirn]);
- fd[dirn] = -1;
- unlink(new[dirn]);
- continue;
- }
- safe_free(outbuf[dirn]);
- }
- safe_free(outbuf);
- safe_free(outbufoffset);
- /*
- * You can't rename open files on Microsoft "operating systems"
- * so we have to close before renaming.
- */
- storeDirCloseSwapLogs();
- /* rename */
- for (dirn = 0; dirn < N; dirn++) {
- if (fd[dirn] < 0)
- continue;
- #ifdef _SQUID_OS2_
- file_close(fd[dirn]);
- fd[dirn] = -1;
- if (unlink(cur[dirn]) < 0)
- debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %sn",
- xstrerror(), cur[dirn]);
- #endif
- if (rename(new[dirn], cur[dirn]) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: rename failed: %s, %s -> %sn",
- xstrerror(), new[dirn], cur[dirn]);
- }
- }
- if (reopen)
- storeDirOpenSwapLogs();
- stop = squid_curtime;
- r = stop - start;
- debug(20, 1) (" Finished. Wrote %d entries.n", n);
- debug(20, 1) (" Took %d seconds (%6.1f entries/sec).n",
- r > 0 ? (int) r : 0,
- (double) n / (r > 0 ? r : 1));
- /* touch a timestamp file if we're not still validating */
- if (!store_rebuilding) {
- for (dirn = 0; dirn < N; dirn++) {
- if (fd[dirn] < 0)
- continue;
- file_close(file_open(cln[dirn],
- O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL, NULL));
- }
- }
- /* close */
- for (dirn = 0; dirn < N; dirn++) {
- safe_free(cur[dirn]);
- safe_free(new[dirn]);
- safe_free(cln[dirn]);
- if (fd[dirn] < 0)
- continue;
- file_close(fd[dirn]);
- fd[dirn] = -1;
- }
- safe_free(cur);
- safe_free(new);
- safe_free(cln);
- safe_free(fd);
- return n;
- }
- #undef CLEAN_BUF_SZ
- void
- storeDirConfigure(void)
- {
- SwapDir *SD;
- int n;
- int i;
- fileMap *fm;
- Config.Swap.maxSize = 0;
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];;
- Config.Swap.maxSize += SD->max_size;
- n = 2 * SD->max_size / Config.Store.avgObjectSize;
- if (NULL == SD->map) {
- /* first time */
- SD->map = file_map_create(n);
- } else if (n > SD->map->max_n_files) {
- /* it grew, need to expand */
- fm = file_map_create(n);
- filemapCopy(SD->map, fm);
- filemapFreeMemory(SD->map);
- SD->map = fm;
- }
- /* else it shrunk, and we leave the old one in place */
- }
- }
- void
- storeDirDiskFull(int fn)
- {
- int dirn = fn >> SWAP_DIR_SHIFT;
- SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
- assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
- SD->max_size = SD->cur_size;
- debug(20, 1) ("WARNING: Shrinking cache_dir #%d to %d KBn",
- dirn, SD->cur_size);
- }