]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_diff.cc
update
[thirdparty/squid.git] / src / cache_diff.cc
CommitLineData
8667b856 1/*
cbdec147 2 * $Id: cache_diff.cc,v 1.9 1998/07/20 17:19:21 wessels Exp $
8667b856 3 *
4 * AUTHOR: Alex Rousskov
5 *
6 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
7 * --------------------------------------------------------
8 *
9 * Squid is the result of efforts by numerous individuals from the
10 * Internet community. Development is led by Duane Wessels of the
11 * National Laboratory for Applied Network Research and funded by
12 * the National Science Foundation.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
cbdec147 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
8667b856 27 *
28 */
29
30/*
31 * Computes the difference between the contents of two caches
32 * using swap logs
33 * Reports the percentage of common files and other stats
34 */
35
36#include "squid.h"
37
38typedef struct {
39 const char *name;
40 hash_table *hash;
1afe05c5 41 int count; /* #currently cached entries */
42 int scanned_count; /* #scanned entries */
43 int bad_add_count; /* #duplicate adds */
44 int bad_del_count; /* #dels with no prior add */
8667b856 45} CacheIndex;
46
47
48typedef struct _CacheEntry {
49 const cache_key *key;
50 struct _CacheEntry *next;
edc1d6da 51 /* storeSwapLogData s; */
52 unsigned char key_arr[MD5_DIGEST_CHARS];
8667b856 53} CacheEntry;
54
55
56/* copied from url.c */
57const char *RequestMethodStr[] =
58{
59 "NONE",
60 "GET",
61 "POST",
62 "PUT",
63 "HEAD",
64 "CONNECT",
65 "TRACE",
66 "PURGE"
67};
68
69
1afe05c5 70static int cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file);
8667b856 71
72
73static CacheEntry *
1afe05c5 74cacheEntryCreate(const storeSwapLogData * s)
8667b856 75{
76 CacheEntry *e = xcalloc(1, sizeof(CacheEntry));
77 assert(s);
edc1d6da 78 /* e->s = *s; */
79 xmemcpy(e->key_arr, s->key, MD5_DIGEST_CHARS);
80 e->key = &e->key_arr[0];
8667b856 81 return e;
82}
83
84static void
1afe05c5 85cacheEntryDestroy(CacheEntry * e)
8667b856 86{
87 assert(e);
88 xfree(e);
89}
90
91static CacheIndex *
92cacheIndexCreate(const char *name)
93{
94 CacheIndex *idx;
95 if (!name || !strlen(name))
96 return NULL;
97
98 idx = xcalloc(1, sizeof(CacheIndex));
99 idx->name = name;
100 idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash);
101
102 return idx;
103}
104
105static void
1afe05c5 106cacheIndexDestroy(CacheIndex * idx)
8667b856 107{
108 hash_link *hashr = NULL;
109 if (idx) {
110 /* destroy hash list contents */
0f6bebac 111 hash_first(idx->hash);
112 while (hashr = hash_next(idx->hash)) {
8667b856 113 hash_remove_link(idx->hash, hashr);
1afe05c5 114 cacheEntryDestroy((CacheEntry *) hashr);
8667b856 115 }
116 /* destroy the hash table itself */
117 hashFreeMemory(idx->hash);
118 xfree(idx);
119 }
120}
121
122static int
1afe05c5 123cacheIndexAddLog(CacheIndex * idx, const char *fname)
8667b856 124{
125 FILE *file;
126 int scanned_count = 0;
127 assert(idx);
128 assert(fname && strlen(fname));
129
130 file = fopen(fname, "r");
131 if (!file) {
132 fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
133 return 0;
134 }
8667b856 135 scanned_count = cacheIndexScan(idx, fname, file);
136
137 fclose(file);
138 return scanned_count;
139}
140
141static void
1afe05c5 142cacheIndexInitReport(CacheIndex * idx)
8667b856 143{
144 assert(idx);
145 fprintf(stderr, "%s: bad swap_add: %d\n",
146 idx->name, idx->bad_add_count);
1afe05c5 147 fprintf(stderr, "%s: bad swap_del: %d\n",
8667b856 148 idx->name, idx->bad_del_count);
1afe05c5 149 fprintf(stderr, "%s: scanned lines: %d\n",
8667b856 150 idx->name, idx->scanned_count);
151}
152
153static int
1afe05c5 154cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file)
8667b856 155{
156 int count = 0;
157 storeSwapLogData s;
158 fprintf(stderr, "%s scanning\n", fname);
159 while (fread(&s, sizeof(s), 1, file) == 1) {
160 count++;
161 idx->scanned_count++;
162 /* if (s.op <= SWAP_LOG_NOP || s.op >= SWAP_LOG_MAX)
1afe05c5 163 * continue; */
8667b856 164 if (s.op == SWAP_LOG_ADD) {
165 CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key);
166 if (olde) {
167 idx->bad_add_count++;
168 } else {
169 CacheEntry *e = cacheEntryCreate(&s);
1afe05c5 170 hash_join(idx->hash, (hash_link *) e);
8667b856 171 idx->count++;
172 }
1afe05c5 173 } else if (s.op == SWAP_LOG_DEL) {
8667b856 174 CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key);
175 if (!olde)
176 idx->bad_del_count++;
177 else {
681e7924 178 assert(idx->count);
1afe05c5 179 hash_remove_link(idx->hash, (hash_link *) olde);
681e7924 180 cacheEntryDestroy(olde);
181 idx->count--;
8667b856 182 }
183 } else {
184 fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count);
185 exit(-3);
186 }
187 }
1afe05c5 188 fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n",
189 fname, count, (int) (count * sizeof(CacheEntry)));
8667b856 190 return count;
191}
192
193static void
1afe05c5 194cacheIndexCmpReport(CacheIndex * idx, int shared_count)
8667b856 195{
196 assert(idx && shared_count <= idx->count);
197
f97c9706 198 printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n",
199 idx->name,
200 idx->count,
7028e201 201 idx->count - shared_count,
202 shared_count,
1afe05c5 203 xpercent(idx->count - shared_count, idx->count),
8667b856 204 xpercent(shared_count, idx->count));
205}
206
207static void
1afe05c5 208cacheIndexCmp(CacheIndex * idx1, CacheIndex * idx2)
8667b856 209{
210 int shared_count = 0;
681e7924 211 int hashed_count = 0;
8667b856 212 hash_link *hashr = NULL;
213 CacheIndex *small_idx = idx1;
214 CacheIndex *large_idx = idx2;
215 assert(idx1 && idx2);
216
217 /* check our guess */
218 if (idx1->count > idx2->count) {
219 small_idx = idx2;
220 large_idx = idx1;
221 }
222 /* find shared_count */
0f6bebac 223 hash_first(small_idx->hash);
224 for (hashr = hash_next(small_idx->hash)) {
681e7924 225 hashed_count++;
8667b856 226 if (hash_lookup(large_idx->hash, hashr->key))
227 shared_count++;
228 }
681e7924 229 assert(hashed_count == small_idx->count);
8667b856 230
231 cacheIndexCmpReport(idx1, shared_count);
232 cacheIndexCmpReport(idx2, shared_count);
233}
234
235
236static int
237usage(const char *prg_name)
238{
239 fprintf(stderr, "usage: %s <label1>: <swap_state>... <label2>: <swap_state>...\n",
240 prg_name);
241 return -1;
242}
243
244int
245main(int argc, char *argv[])
246{
247 CacheIndex *CacheIdx[2];
248 CacheIndex *idx = NULL;
249 int idxCount = 0;
250 int i;
251
252 if (argc < 5)
253 return usage(argv[0]);
254
255 for (i = 1; i < argc; ++i) {
256 const int len = strlen(argv[i]);
257 if (!len)
258 return usage(argv[0]);
1afe05c5 259 if (argv[i][len - 1] == ':') {
8667b856 260 idxCount++;
261 if (len < 2 || idxCount > 2)
262 return usage(argv[0]);
263 idx = cacheIndexCreate(argv[i]);
1afe05c5 264 CacheIdx[idxCount - 1] = idx;
8667b856 265 } else {
266 if (!idx)
267 return usage(argv[0]);
268 cacheIndexAddLog(idx, argv[i]);
269 }
270 }
271
272 if (idxCount != 2)
273 return usage(argv[0]);
274
275 cacheIndexInitReport(CacheIdx[0]);
276 cacheIndexInitReport(CacheIdx[1]);
277
278 cacheIndexCmp(CacheIdx[0], CacheIdx[1]);
279
280 cacheIndexDestroy(CacheIdx[0]);
281 cacheIndexDestroy(CacheIdx[1]);
282
283 return 1;
284}