⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 store_dir_ufs.c

📁 一个功能非常全面的代理服务器源代码程序,
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	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 + -