From: rousskov <> Date: Mon, 30 Mar 1998 03:02:43 +0000 (+0000) Subject: - Added cache_diff.c, a stand alone program that X-Git-Tag: SQUID_3_0_PRE1~3710 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8667b85653445cbc52add5c21e84860f68863150;p=thirdparty%2Fsquid.git - Added cache_diff.c, a stand alone program that - Computes the difference between the contents of two caches using swap logs - Reports the percentage of common files and other stats --- diff --git a/src/Makefile.in b/src/Makefile.in index 7f17d8aca4..1b439ed0b7 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.137 1998/03/28 04:41:15 wessels Exp $ +# $Id: Makefile.in,v 1.138 1998/03/29 20:02:44 rousskov Exp $ # # Uncomment and customize the following to suit your needs: # @@ -60,6 +60,7 @@ SQUID_LIBS = -L../lib $(CRYPTLIB) $(REGEXLIB) @SQUID_PTHREAD_LIB@ \ CLIENT_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) DNSSERVER_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) PINGER_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) +CACHE_DIFF_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) PROGS = squid client UTILS = dnsserver unlinkd @@ -198,6 +199,9 @@ unlinkd: unlinkd-daemon.o unlinkd-daemon.o: unlinkd.c $(CC) -c $(CFLAGS) -DUNLINK_DAEMON $(srcdir)/unlinkd.c -o $@ +cache_diff: cache_diff.o + $(CC) -o $@ $(LDFLAGS) $@.o debug.o globals.o hash.o store_key_md5.o $(CACHE_DIFF_LIBS) + cache_cf.o: cf_parser.c squid.conf cf_parser.c: cf.data cf_gen diff --git a/src/cache_diff.cc b/src/cache_diff.cc new file mode 100644 index 0000000000..c191b74ea6 --- /dev/null +++ b/src/cache_diff.cc @@ -0,0 +1,274 @@ +/* + * $Id: cache_diff.cc,v 1.1 1998/03/29 20:02:43 rousskov Exp $ + * + * AUTHOR: Alex Rousskov + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * Computes the difference between the contents of two caches + * using swap logs + * Reports the percentage of common files and other stats + */ + +#include "squid.h" + +typedef struct { + const char *name; + hash_table *hash; + int count; /* #currently cached entries */ + int scanned_count; /* #scanned entries */ + int bad_add_count; /* #duplicate adds */ + int bad_del_count; /* #dels with no prior add */ +} CacheIndex; + + +typedef struct _CacheEntry { + const cache_key *key; + struct _CacheEntry *next; + storeSwapLogData s; +} CacheEntry; + + +/* copied from url.c */ +const char *RequestMethodStr[] = +{ + "NONE", + "GET", + "POST", + "PUT", + "HEAD", + "CONNECT", + "TRACE", + "PURGE" +}; + + +static int cacheIndexScan(CacheIndex *idx, const char *fname, FILE *file); + + +static CacheEntry * +cacheEntryCreate(const storeSwapLogData *s) +{ + CacheEntry *e = xcalloc(1, sizeof(CacheEntry)); + assert(s); + e->s = *s; + e->key = &e->s.key[0]; + return e; +} + +static void +cacheEntryDestroy(CacheEntry *e) +{ + assert(e); + xfree(e); +} + +static CacheIndex * +cacheIndexCreate(const char *name) +{ + CacheIndex *idx; + if (!name || !strlen(name)) + return NULL; + + idx = xcalloc(1, sizeof(CacheIndex)); + idx->name = name; + idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash); + + return idx; +} + +static void +cacheIndexDestroy(CacheIndex *idx) +{ + hash_link *hashr = NULL; + if (idx) { + /* destroy hash list contents */ + for (hashr = hash_first(idx->hash); hashr; hashr = hash_next(idx->hash)) { + hash_remove_link(idx->hash, hashr); + cacheEntryDestroy((CacheEntry*)hashr); + } + /* destroy the hash table itself */ + hashFreeMemory(idx->hash); + xfree(idx); + } +} + +static int +cacheIndexAddLog(CacheIndex *idx, const char *fname) +{ + FILE *file; + int scanned_count = 0; + assert(idx); + assert(fname && strlen(fname)); + + file = fopen(fname, "r"); + if (!file) { + fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno)); + return 0; + } + + scanned_count = cacheIndexScan(idx, fname, file); + + fclose(file); + return scanned_count; +} + +static void +cacheIndexInitReport(CacheIndex *idx) +{ + assert(idx); + fprintf(stderr, "%s: bad swap_add: %d\n", + idx->name, idx->bad_add_count); + fprintf(stderr, "%s: bad swap_del: %d\n", + idx->name, idx->bad_del_count); + fprintf(stderr, "%s: scanned lines: %d\n", + idx->name, idx->scanned_count); +} + +static int +cacheIndexScan(CacheIndex *idx, const char *fname, FILE *file) +{ + int count = 0; + storeSwapLogData s; + fprintf(stderr, "%s scanning\n", fname); + while (fread(&s, sizeof(s), 1, file) == 1) { + count++; + idx->scanned_count++; + /* if (s.op <= SWAP_LOG_NOP || s.op >= SWAP_LOG_MAX) + continue; */ + if (s.op == SWAP_LOG_ADD) { + CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); + if (olde) { + idx->bad_add_count++; + } else { + CacheEntry *e = cacheEntryCreate(&s); + hash_join(idx->hash, (hash_link*) e); + idx->count++; + } + } else + if (s.op == SWAP_LOG_DEL) { + CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); + if (!olde) + idx->bad_del_count++; + else { + hash_delete_link(idx->hash, (hash_link*) olde); + } + } else { + fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count); + exit(-3); + } + } + fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n", + fname, count, count*sizeof(CacheEntry)); + return count; +} + +static void +cacheIndexCmpReport(CacheIndex *idx, int shared_count) +{ + assert(idx && shared_count <= idx->count); + + printf("%s:\t %7d %7.2f%% + %7.2f%%\n", + idx->name, + idx->count, + xpercent(idx->count-shared_count, idx->count), + xpercent(shared_count, idx->count)); +} + +static void +cacheIndexCmp(CacheIndex *idx1, CacheIndex *idx2) +{ + int shared_count = 0; + hash_link *hashr = NULL; + CacheIndex *small_idx = idx1; + CacheIndex *large_idx = idx2; + assert(idx1 && idx2); + + /* check our guess */ + if (idx1->count > idx2->count) { + small_idx = idx2; + large_idx = idx1; + } + /* find shared_count */ + for (hashr = hash_first(small_idx->hash); hashr; hashr = hash_next(small_idx->hash)) { + if (hash_lookup(large_idx->hash, hashr->key)) + shared_count++; + } + + cacheIndexCmpReport(idx1, shared_count); + cacheIndexCmpReport(idx2, shared_count); +} + + +static int +usage(const char *prg_name) +{ + fprintf(stderr, "usage: %s : ... : ...\n", + prg_name); + return -1; +} + +int +main(int argc, char *argv[]) +{ + CacheIndex *CacheIdx[2]; + CacheIndex *idx = NULL; + int idxCount = 0; + int i; + + if (argc < 5) + return usage(argv[0]); + + for (i = 1; i < argc; ++i) { + const int len = strlen(argv[i]); + if (!len) + return usage(argv[0]); + if (argv[i][len-1] == ':') { + idxCount++; + if (len < 2 || idxCount > 2) + return usage(argv[0]); + idx = cacheIndexCreate(argv[i]); + CacheIdx[idxCount-1] = idx; + } else { + if (!idx) + return usage(argv[0]); + cacheIndexAddLog(idx, argv[i]); + } + } + + if (idxCount != 2) + return usage(argv[0]); + + cacheIndexInitReport(CacheIdx[0]); + cacheIndexInitReport(CacheIdx[1]); + + cacheIndexCmp(CacheIdx[0], CacheIdx[1]); + + cacheIndexDestroy(CacheIdx[0]); + cacheIndexDestroy(CacheIdx[1]); + + return 1; +}