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