📄 store_dir_coss.c
字号:
/* * $Id: store_dir_coss.c,v 1.65 2006/10/26 20:00:21 serassio Exp $ * * DEBUG: section 47 Store COSS Directory Routines * AUTHOR: Eric Stern * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from * the Internet community; see the CONTRIBUTORS file for full * details. Many organizations have provided support for Squid's * development; see the SPONSORS file for full details. Squid is * Copyrighted (C) 2001 by the Regents of the University of * California; see the COPYRIGHT file for full details. Squid * incorporates software developed and/or copyrighted by other * sources; 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_AIO_H#include <aio.h>#endif#include "async_io.h"#include "store_coss.h"#if USE_AUFSOPS#include "../aufs/async_io.h"#endif#define STORE_META_BUFSZ 4096#define HITONLY_BUFS 2int max_coss_dir_size = 0;static int last_coss_pick_index = -1;int coss_initialised = 0;MemPool *coss_state_pool = NULL;MemPool *coss_index_pool = NULL;MemPool *coss_realloc_pool = NULL;MemPool *coss_op_pool = NULL;typedef struct _RebuildState RebuildState;struct _RebuildState { SwapDir *sd; int n_read; FILE *log; int report_interval; int report_current; struct { unsigned int clean:1; } flags; struct _store_rebuild_data counts; struct { int new; int reloc; int fresher; int unknown; } cosscounts;};static char *storeCossDirSwapLogFile(SwapDir *, const char *);static void storeCossDirRebuild(SwapDir * sd);static void storeCossDirCloseTmpSwapLog(SwapDir * sd);static FILE *storeCossDirOpenTmpSwapLog(SwapDir *, int *, int *);static STLOGOPEN storeCossDirOpenSwapLog;static STINIT storeCossDirInit;static STLOGCLEANSTART storeCossDirWriteCleanStart;static STLOGCLEANNEXTENTRY storeCossDirCleanLogNextEntry;static STLOGCLEANWRITE storeCossDirWriteCleanEntry;static STLOGCLEANDONE storeCossDirWriteCleanDone;static STLOGCLOSE storeCossDirCloseSwapLog;static STLOGWRITE storeCossDirSwapLog;static STNEWFS storeCossDirNewfs;static STCHECKOBJ storeCossDirCheckObj;static STCHECKLOADAV storeCossDirCheckLoadAv;static STFREE storeCossDirShutdown;static STFSPARSE storeCossDirParse;static STFSRECONFIGURE storeCossDirReconfigure;static STDUMP storeCossDirDump;static STCALLBACK storeCossDirCallback;static void storeCossDirParseBlkSize(SwapDir *, const char *, const char *, int);static void storeCossDirParseOverwritePct(SwapDir *, const char *, const char *, int);static void storeCossDirParseMaxWaste(SwapDir *, const char *, const char *, int);static void storeCossDirParseMemOnlyBufs(SwapDir *, const char *, const char *, int);static void storeCossDirParseMaxFullBufs(SwapDir *, const char *, const char *, int);static void storeCossDirDumpBlkSize(StoreEntry *, const char *, SwapDir *);static void storeCossDirDumpOverwritePct(StoreEntry *, const char *, SwapDir *);static void storeCossDirDumpMaxWaste(StoreEntry *, const char *, SwapDir *);static void storeCossDirDumpMemOnlyBufs(StoreEntry *, const char *, SwapDir *);static void storeCossDirDumpMaxFullBufs(StoreEntry *, const char *, SwapDir *);static OBJH storeCossStats;static void storeDirCoss_StartDiskRebuild(RebuildState * rb);/* The "only" externally visible function */STSETUP storeFsSetup_coss;static struct cache_dir_option options[] ={ {"block-size", storeCossDirParseBlkSize, storeCossDirDumpBlkSize}, {"overwrite-percent", storeCossDirParseOverwritePct, storeCossDirDumpOverwritePct}, {"max-stripe-waste", storeCossDirParseMaxWaste, storeCossDirDumpMaxWaste}, {"membufs", storeCossDirParseMemOnlyBufs, storeCossDirDumpMemOnlyBufs}, {"maxfullbufs", storeCossDirParseMaxFullBufs, storeCossDirDumpMaxFullBufs}, {NULL, NULL}};struct _coss_stats coss_stats;char const *stripePath(SwapDir * sd){ CossInfo *cs = (CossInfo *) sd->fsdata; char pathtmp[SQUID_MAXPATHLEN]; struct stat st; if (!cs->stripe_path) { strcpy(pathtmp, sd->path); if (stat(sd->path, &st) == 0) { if (S_ISDIR(st.st_mode)) strcat(pathtmp, "/stripe"); } else fatalf("stripePath: Cannot stat %s.", sd->path); cs->stripe_path = xstrdup(pathtmp); } return cs->stripe_path;}static char *storeCossDirSwapLogFile(SwapDir * sd, const char *ext){ LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN); LOCAL_ARRAY(char, pathtmp, SQUID_MAXPATHLEN); LOCAL_ARRAY(char, digit, 32); char *pathtmp2; struct stat st; if (Config.Log.swap) { xstrncpy(pathtmp, sd->path, SQUID_MAXPATHLEN - 64); pathtmp2 = pathtmp; while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL) *pathtmp2 = '.'; while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.') pathtmp[strlen(pathtmp) - 1] = '\0'; for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++); snprintf(path, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2); if (strncmp(path, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) { strcat(path, "."); snprintf(digit, 32, "%02d", sd->index); strncat(path, digit, 3); } } else { if (stat(sd->path, &st) == 0) { if (S_ISDIR(st.st_mode)) { xstrncpy(path, sd->path, SQUID_MAXPATHLEN - 64); strcat(path, "/swap.state"); } else fatal("storeCossDirSwapLogFile: 'cache_swap_log' is needed in your COSS configuration."); } else fatalf("storeCossDirSwapLogFile: Cannot stat %s.", sd->path); } if (ext) strncat(path, ext, 16); return path;}static voidstoreCossDirOpenSwapLog(SwapDir * sd){ CossInfo *cs = (CossInfo *) sd->fsdata; char *path; int fd; path = storeCossDirSwapLogFile(sd, NULL); fd = file_open(path, O_WRONLY | O_CREAT | O_BINARY); if (fd < 0) { debug(79, 1) ("%s: %s\n", path, xstrerror()); fatal("storeCossDirOpenSwapLog: Failed to open swap log."); } debug(79, 3) ("Cache COSS Dir #%d log opened on FD %d\n", sd->index, fd); cs->swaplog_fd = fd;}static voidstoreCossDirCloseSwapLog(SwapDir * sd){ CossInfo *cs = (CossInfo *) sd->fsdata; if (cs->swaplog_fd < 0) /* not open */ return; file_close(cs->swaplog_fd); debug(79, 3) ("Cache COSS Dir #%d log closed on FD %d\n", sd->index, cs->swaplog_fd); cs->swaplog_fd = -1;}static voidstoreCossDirInit(SwapDir * sd){ CossInfo *cs = (CossInfo *) sd->fsdata; /* COSS is pretty useless without 64 bit file offsets */ if (sizeof(off_t) < 8) { fatalf("COSS will not function without large file support (off_t is %d bytes long. Please reconsider recompiling squid with --with-large-files\n", (int) sizeof(off_t)); }#if USE_AUFSOPS aioInit(); squidaio_init();#else a_file_setupqueue(&cs->aq);#endif cs->fd = file_open(stripePath(sd), O_RDWR | O_CREAT | O_BINARY); if (cs->fd < 0) { debug(79, 1) ("%s: %s\n", stripePath(sd), xstrerror()); fatal("storeCossDirInit: Failed to open a COSS file."); } storeCossDirOpenSwapLog(sd); storeCossDirRebuild(sd); n_coss_dirs++; /* * fs.blksize is normally determined by calling statvfs() etc, * but we just set it here. It is used in accounting the * total store size, and is reported in cachemgr 'storedir' * page. */ sd->fs.blksize = 1 << cs->blksz_bits; comm_quick_poll_required();}voidstoreCossRemove(SwapDir * sd, StoreEntry * e){ CossInfo *cs = (CossInfo *) sd->fsdata; int stripe;#if 0 debug(1, 1) ("storeCossRemove: %x: %d/%d\n", e, (int) e->swap_dirn, (e) e->swap_filen);#endif CossIndexNode *coss_node = e->repl.data; /* Do what the LRU and HEAP repl policies do.. */ if (e->repl.data == NULL) { return; } assert(sd->index == e->swap_dirn); assert(e->swap_filen >= 0); e->repl.data = NULL; stripe = storeCossFilenoToStripe(cs, e->swap_filen); dlinkDelete(&coss_node->node, &cs->stripes[stripe].objlist); memPoolFree(coss_index_pool, coss_node); cs->count -= 1;}voidstoreCossAdd(SwapDir * sd, StoreEntry * e, int curstripe){ CossInfo *cs = (CossInfo *) sd->fsdata; CossStripe *cstripe = &cs->stripes[curstripe]; CossIndexNode *coss_node = memPoolAlloc(coss_index_pool); assert(!e->repl.data); assert(sd->index == e->swap_dirn); /* Make sure the object exists in the current stripe, it should do! */ assert(curstripe == storeCossFilenoToStripe(cs, e->swap_filen)); e->repl.data = coss_node; dlinkAddTail(e, &coss_node->node, &cstripe->objlist); cs->count += 1;}static voidstoreCossRebuildComplete(void *data){ RebuildState *rb = data; SwapDir *SD = rb->sd; CossInfo *cs = SD->fsdata; storeCossStartMembuf(SD); store_dirs_rebuilding--; storeCossDirCloseTmpSwapLog(SD); storeRebuildComplete(&rb->counts); debug(47, 1) ("COSS: %s: Rebuild Completed\n", stripePath(SD)); cs->rebuild.rebuilding = 0; debug(47, 1) (" %d objects scanned, %d objects relocated, %d objects fresher, %d objects ignored\n", rb->counts.scancount, rb->cosscounts.reloc, rb->cosscounts.fresher, rb->cosscounts.unknown); cbdataFree(rb);}CBDATA_TYPE(RebuildState);static voidstoreCossDirRebuild(SwapDir * sd){ RebuildState *rb; int clean = 0; int zero = 0; FILE *fp; CBDATA_INIT_TYPE(RebuildState); rb = cbdataAlloc(RebuildState); rb->sd = sd; rb->flags.clean = (unsigned int) clean; fp = storeCossDirOpenTmpSwapLog(sd, &clean, &zero); fclose(fp); debug(20, 1) ("Rebuilding COSS storage in %s (DIRTY)\n", stripePath(sd)); store_dirs_rebuilding++; storeDirCoss_StartDiskRebuild(rb);}static voidstoreCossDirCloseTmpSwapLog(SwapDir * sd){ CossInfo *cs = (CossInfo *) sd->fsdata; char *swaplog_path = xstrdup(storeCossDirSwapLogFile(sd, NULL)); char *new_path = xstrdup(storeCossDirSwapLogFile(sd, ".new")); int fd; file_close(cs->swaplog_fd); if (xrename(new_path, swaplog_path) < 0) { fatal("storeCossDirCloseTmpSwapLog: 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("storeCossDirCloseTmpSwapLog: Failed to open swap log."); } safe_free(swaplog_path); safe_free(new_path); cs->swaplog_fd = fd; debug(47, 3) ("Cache COSS Dir #%d log opened on FD %d\n", sd->index, fd);}static FILE *storeCossDirOpenTmpSwapLog(SwapDir * sd, int *clean_flag, int *zero_flag){ CossInfo *cs = (CossInfo *) sd->fsdata; char *swaplog_path = xstrdup(storeCossDirSwapLogFile(sd, NULL)); char *clean_path = xstrdup(storeCossDirSwapLogFile(sd, ".last-clean")); char *new_path = xstrdup(storeCossDirSwapLogFile(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 COSS 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 (cs->swaplog_fd >= 0) file_close(cs->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."); } cs->swaplog_fd = 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -