]>
Commit | Line | Data |
---|---|---|
f740a279 | 1 | |
8667b856 | 2 | /* |
262a0e14 | 3 | * $Id$ |
8667b856 | 4 | * |
5 | * AUTHOR: Alex Rousskov | |
6 | * | |
2b6662ba | 7 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 8 | * ---------------------------------------------------------- |
8667b856 | 9 | * |
2b6662ba | 10 | * Squid is the result of efforts by numerous individuals from |
11 | * the Internet community; see the CONTRIBUTORS file for full | |
12 | * details. Many organizations have provided support for Squid's | |
13 | * development; see the SPONSORS file for full details. Squid is | |
14 | * Copyrighted (C) 2001 by the Regents of the University of | |
15 | * California; see the COPYRIGHT file for full details. Squid | |
16 | * incorporates software developed and/or copyrighted by other | |
17 | * sources; see the 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. | |
26ac0430 | 23 | * |
8667b856 | 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. | |
26ac0430 | 28 | * |
8667b856 | 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 | ||
f7f3304a | 41 | #include "squid-old.h" |
8667b856 | 42 | |
26ac0430 | 43 | typedef struct { |
8667b856 | 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 */ | |
2fadd50d | 50 | } CacheIndex; |
8667b856 | 51 | |
52 | ||
26ac0430 | 53 | typedef struct _CacheEntry { |
8667b856 | 54 | const cache_key *key; |
62e76326 | 55 | |
8667b856 | 56 | struct _CacheEntry *next; |
51ee7c82 | 57 | /* StoreSwapLogData s; */ |
c3031d67 | 58 | unsigned char key_arr[SQUID_MD5_DIGEST_LENGTH]; |
2fadd50d | 59 | } CacheEntry; |
8667b856 | 60 | |
61 | ||
62 | /* copied from url.c */ | |
26ac0430 AJ |
63 | const char *RequestMethodStr[] = { |
64 | "NONE", | |
65 | "GET", | |
66 | "POST", | |
67 | "PUT", | |
68 | "HEAD", | |
69 | "CONNECT", | |
70 | "TRACE", | |
71 | "PURGE" | |
72 | }; | |
8667b856 | 73 | |
74 | ||
1afe05c5 | 75 | static int cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file); |
8667b856 | 76 | |
77 | ||
78 | static CacheEntry * | |
51ee7c82 | 79 | cacheEntryCreate(const StoreSwapLogData * s) |
8667b856 | 80 | { |
81 | CacheEntry *e = xcalloc(1, sizeof(CacheEntry)); | |
82 | assert(s); | |
edc1d6da | 83 | /* e->s = *s; */ |
41d00cd3 | 84 | memcpy(e->key_arr, s->key, SQUID_MD5_DIGEST_LENGTH); |
edc1d6da | 85 | e->key = &e->key_arr[0]; |
8667b856 | 86 | return e; |
87 | } | |
88 | ||
89 | static void | |
1afe05c5 | 90 | cacheEntryDestroy(CacheEntry * e) |
8667b856 | 91 | { |
92 | assert(e); | |
93 | xfree(e); | |
94 | } | |
95 | ||
96 | static CacheIndex * | |
97 | cacheIndexCreate(const char *name) | |
98 | { | |
99 | CacheIndex *idx; | |
62e76326 | 100 | |
8667b856 | 101 | if (!name || !strlen(name)) |
62e76326 | 102 | return NULL; |
8667b856 | 103 | |
104 | idx = xcalloc(1, sizeof(CacheIndex)); | |
62e76326 | 105 | |
8667b856 | 106 | idx->name = name; |
62e76326 | 107 | |
8667b856 | 108 | idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash); |
109 | ||
110 | return idx; | |
111 | } | |
112 | ||
113 | static void | |
1afe05c5 | 114 | cacheIndexDestroy(CacheIndex * idx) |
8667b856 | 115 | { |
116 | hash_link *hashr = NULL; | |
62e76326 | 117 | |
8667b856 | 118 | if (idx) { |
62e76326 | 119 | /* destroy hash list contents */ |
120 | hash_first(idx->hash); | |
121 | ||
122 | while (hashr = hash_next(idx->hash)) { | |
123 | hash_remove_link(idx->hash, hashr); | |
124 | cacheEntryDestroy((CacheEntry *) hashr); | |
125 | } | |
126 | ||
127 | /* destroy the hash table itself */ | |
128 | hashFreeMemory(idx->hash); | |
129 | ||
130 | xfree(idx); | |
8667b856 | 131 | } |
132 | } | |
133 | ||
134 | static int | |
1afe05c5 | 135 | cacheIndexAddLog(CacheIndex * idx, const char *fname) |
8667b856 | 136 | { |
137 | FILE *file; | |
138 | int scanned_count = 0; | |
139 | assert(idx); | |
140 | assert(fname && strlen(fname)); | |
141 | ||
142 | file = fopen(fname, "r"); | |
62e76326 | 143 | |
8667b856 | 144 | if (!file) { |
62e76326 | 145 | fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno)); |
146 | return 0; | |
8667b856 | 147 | } |
62e76326 | 148 | |
be266cb2 | 149 | #if _SQUID_WINDOWS_ |
c4aefe96 | 150 | setmode(fileno(file), O_BINARY); |
151 | #endif | |
62e76326 | 152 | |
8667b856 | 153 | scanned_count = cacheIndexScan(idx, fname, file); |
154 | ||
155 | fclose(file); | |
62e76326 | 156 | |
8667b856 | 157 | return scanned_count; |
158 | } | |
159 | ||
160 | static void | |
1afe05c5 | 161 | cacheIndexInitReport(CacheIndex * idx) |
8667b856 | 162 | { |
163 | assert(idx); | |
164 | fprintf(stderr, "%s: bad swap_add: %d\n", | |
62e76326 | 165 | idx->name, idx->bad_add_count); |
1afe05c5 | 166 | fprintf(stderr, "%s: bad swap_del: %d\n", |
62e76326 | 167 | idx->name, idx->bad_del_count); |
1afe05c5 | 168 | fprintf(stderr, "%s: scanned lines: %d\n", |
62e76326 | 169 | idx->name, idx->scanned_count); |
8667b856 | 170 | } |
171 | ||
172 | static int | |
1afe05c5 | 173 | cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file) |
8667b856 | 174 | { |
175 | int count = 0; | |
51ee7c82 | 176 | StoreSwapLogData s; |
8667b856 | 177 | fprintf(stderr, "%s scanning\n", fname); |
62e76326 | 178 | |
8667b856 | 179 | while (fread(&s, sizeof(s), 1, file) == 1) { |
d7ae3534 FC |
180 | ++count; |
181 | ++ idx->scanned_count; | |
3f9d4dc2 | 182 | /* if (!s.sane()) |
62e76326 | 183 | * continue; */ |
184 | ||
185 | if (s.op == SWAP_LOG_ADD) { | |
186 | CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); | |
187 | ||
188 | if (olde) { | |
d7ae3534 | 189 | ++ idx->bad_add_count; |
62e76326 | 190 | } else { |
191 | CacheEntry *e = cacheEntryCreate(&s); | |
192 | hash_join(idx->hash, &e->hash); | |
d7ae3534 | 193 | ++ idx->count; |
62e76326 | 194 | } |
195 | } else if (s.op == SWAP_LOG_DEL) { | |
196 | CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); | |
197 | ||
198 | if (!olde) | |
d7ae3534 | 199 | ++ idx->bad_del_count; |
62e76326 | 200 | else { |
201 | assert(idx->count); | |
202 | hash_remove_link(idx->hash, (hash_link *) olde); | |
203 | cacheEntryDestroy(olde); | |
5e263176 | 204 | -- idx->count; |
62e76326 | 205 | } |
206 | } else { | |
207 | fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count); | |
208 | exit(-3); | |
209 | } | |
8667b856 | 210 | } |
62e76326 | 211 | |
1afe05c5 | 212 | fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n", |
62e76326 | 213 | fname, count, (int) (count * sizeof(CacheEntry))); |
8667b856 | 214 | return count; |
215 | } | |
216 | ||
217 | static void | |
1afe05c5 | 218 | cacheIndexCmpReport(CacheIndex * idx, int shared_count) |
8667b856 | 219 | { |
220 | assert(idx && shared_count <= idx->count); | |
221 | ||
f97c9706 | 222 | printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n", |
62e76326 | 223 | idx->name, |
224 | idx->count, | |
225 | idx->count - shared_count, | |
226 | shared_count, | |
227 | xpercent(idx->count - shared_count, idx->count), | |
228 | xpercent(shared_count, idx->count)); | |
8667b856 | 229 | } |
230 | ||
231 | static void | |
1afe05c5 | 232 | cacheIndexCmp(CacheIndex * idx1, CacheIndex * idx2) |
8667b856 | 233 | { |
234 | int shared_count = 0; | |
681e7924 | 235 | int hashed_count = 0; |
8667b856 | 236 | hash_link *hashr = NULL; |
237 | CacheIndex *small_idx = idx1; | |
238 | CacheIndex *large_idx = idx2; | |
239 | assert(idx1 && idx2); | |
240 | ||
241 | /* check our guess */ | |
62e76326 | 242 | |
8667b856 | 243 | if (idx1->count > idx2->count) { |
62e76326 | 244 | small_idx = idx2; |
245 | large_idx = idx1; | |
8667b856 | 246 | } |
62e76326 | 247 | |
8667b856 | 248 | /* find shared_count */ |
0f6bebac | 249 | hash_first(small_idx->hash); |
62e76326 | 250 | |
0f6bebac | 251 | for (hashr = hash_next(small_idx->hash)) { |
d7ae3534 | 252 | ++hashed_count; |
62e76326 | 253 | |
254 | if (hash_lookup(large_idx->hash, hashr->key)) | |
d7ae3534 | 255 | ++shared_count; |
8667b856 | 256 | } |
62e76326 | 257 | |
681e7924 | 258 | assert(hashed_count == small_idx->count); |
8667b856 | 259 | |
260 | cacheIndexCmpReport(idx1, shared_count); | |
261 | cacheIndexCmpReport(idx2, shared_count); | |
262 | } | |
263 | ||
264 | ||
265 | static int | |
266 | usage(const char *prg_name) | |
267 | { | |
268 | fprintf(stderr, "usage: %s <label1>: <swap_state>... <label2>: <swap_state>...\n", | |
62e76326 | 269 | prg_name); |
8667b856 | 270 | return -1; |
271 | } | |
272 | ||
273 | int | |
274 | main(int argc, char *argv[]) | |
275 | { | |
276 | CacheIndex *CacheIdx[2]; | |
277 | CacheIndex *idx = NULL; | |
278 | int idxCount = 0; | |
279 | int i; | |
280 | ||
281 | if (argc < 5) | |
62e76326 | 282 | return usage(argv[0]); |
8667b856 | 283 | |
284 | for (i = 1; i < argc; ++i) { | |
62e76326 | 285 | const int len = strlen(argv[i]); |
286 | ||
287 | if (!len) | |
288 | return usage(argv[0]); | |
289 | ||
290 | if (argv[i][len - 1] == ':') { | |
d7ae3534 | 291 | ++idxCount; |
62e76326 | 292 | |
293 | if (len < 2 || idxCount > 2) | |
294 | return usage(argv[0]); | |
295 | ||
296 | idx = cacheIndexCreate(argv[i]); | |
297 | ||
298 | CacheIdx[idxCount - 1] = idx; | |
299 | } else { | |
300 | if (!idx) | |
301 | return usage(argv[0]); | |
302 | ||
303 | cacheIndexAddLog(idx, argv[i]); | |
304 | } | |
8667b856 | 305 | } |
306 | ||
307 | if (idxCount != 2) | |
62e76326 | 308 | return usage(argv[0]); |
8667b856 | 309 | |
310 | cacheIndexInitReport(CacheIdx[0]); | |
62e76326 | 311 | |
8667b856 | 312 | cacheIndexInitReport(CacheIdx[1]); |
313 | ||
314 | cacheIndexCmp(CacheIdx[0], CacheIdx[1]); | |
315 | ||
316 | cacheIndexDestroy(CacheIdx[0]); | |
62e76326 | 317 | |
8667b856 | 318 | cacheIndexDestroy(CacheIdx[1]); |
319 | ||
320 | return 1; | |
321 | } |