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