]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_diff.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / cache_diff.cc
CommitLineData
8667b856 1/*
77b1029d 2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
e25c139f 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
8667b856 7 */
8
9/*
10 * Computes the difference between the contents of two caches
11 * using swap logs
12 * Reports the percentage of common files and other stats
13 */
14
582c2af2 15#include "squid.h"
1a30fdf5 16#include <cerrno>
21d845b1 17
26ac0430 18typedef struct {
8667b856 19 const char *name;
20 hash_table *hash;
f53969cc
SM
21 int count; /* #currently cached entries */
22 int scanned_count; /* #scanned entries */
23 int bad_add_count; /* #duplicate adds */
24 int bad_del_count; /* #dels with no prior add */
2fadd50d 25} CacheIndex;
8667b856 26
26ac0430 27typedef struct _CacheEntry {
8667b856 28 const cache_key *key;
62e76326 29
8667b856 30 struct _CacheEntry *next;
51ee7c82 31 /* StoreSwapLogData s; */
c3031d67 32 unsigned char key_arr[SQUID_MD5_DIGEST_LENGTH];
2fadd50d 33} CacheEntry;
8667b856 34
1afe05c5 35static int cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file);
8667b856 36
8667b856 37static CacheEntry *
51ee7c82 38cacheEntryCreate(const StoreSwapLogData * s)
8667b856 39{
40 CacheEntry *e = xcalloc(1, sizeof(CacheEntry));
41 assert(s);
edc1d6da 42 /* e->s = *s; */
41d00cd3 43 memcpy(e->key_arr, s->key, SQUID_MD5_DIGEST_LENGTH);
edc1d6da 44 e->key = &e->key_arr[0];
8667b856 45 return e;
46}
47
48static void
1afe05c5 49cacheEntryDestroy(CacheEntry * e)
8667b856 50{
51 assert(e);
52 xfree(e);
53}
54
55static CacheIndex *
56cacheIndexCreate(const char *name)
57{
58 CacheIndex *idx;
62e76326 59
8667b856 60 if (!name || !strlen(name))
62e76326 61 return NULL;
8667b856 62
63 idx = xcalloc(1, sizeof(CacheIndex));
62e76326 64
8667b856 65 idx->name = name;
62e76326 66
8667b856 67 idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash);
68
69 return idx;
70}
71
72static void
1afe05c5 73cacheIndexDestroy(CacheIndex * idx)
8667b856 74{
75 hash_link *hashr = NULL;
62e76326 76
8667b856 77 if (idx) {
62e76326 78 /* destroy hash list contents */
79 hash_first(idx->hash);
80
81 while (hashr = hash_next(idx->hash)) {
82 hash_remove_link(idx->hash, hashr);
83 cacheEntryDestroy((CacheEntry *) hashr);
84 }
85
86 /* destroy the hash table itself */
87 hashFreeMemory(idx->hash);
88
89 xfree(idx);
8667b856 90 }
91}
92
93static int
1afe05c5 94cacheIndexAddLog(CacheIndex * idx, const char *fname)
8667b856 95{
96 FILE *file;
97 int scanned_count = 0;
98 assert(idx);
99 assert(fname && strlen(fname));
100
101 file = fopen(fname, "r");
62e76326 102
8667b856 103 if (!file) {
62e76326 104 fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
105 return 0;
8667b856 106 }
62e76326 107
be266cb2 108#if _SQUID_WINDOWS_
c4aefe96 109 setmode(fileno(file), O_BINARY);
110#endif
62e76326 111
8667b856 112 scanned_count = cacheIndexScan(idx, fname, file);
113
114 fclose(file);
62e76326 115
8667b856 116 return scanned_count;
117}
118
119static void
1afe05c5 120cacheIndexInitReport(CacheIndex * idx)
8667b856 121{
122 assert(idx);
123 fprintf(stderr, "%s: bad swap_add: %d\n",
62e76326 124 idx->name, idx->bad_add_count);
1afe05c5 125 fprintf(stderr, "%s: bad swap_del: %d\n",
62e76326 126 idx->name, idx->bad_del_count);
1afe05c5 127 fprintf(stderr, "%s: scanned lines: %d\n",
62e76326 128 idx->name, idx->scanned_count);
8667b856 129}
130
131static int
1afe05c5 132cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file)
8667b856 133{
134 int count = 0;
51ee7c82 135 StoreSwapLogData s;
8667b856 136 fprintf(stderr, "%s scanning\n", fname);
62e76326 137
8667b856 138 while (fread(&s, sizeof(s), 1, file) == 1) {
d7ae3534
FC
139 ++count;
140 ++ idx->scanned_count;
3f9d4dc2 141 /* if (!s.sane())
62e76326 142 * continue; */
143
144 if (s.op == SWAP_LOG_ADD) {
145 CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key);
146
147 if (olde) {
d7ae3534 148 ++ idx->bad_add_count;
62e76326 149 } else {
150 CacheEntry *e = cacheEntryCreate(&s);
151 hash_join(idx->hash, &e->hash);
d7ae3534 152 ++ idx->count;
62e76326 153 }
154 } else if (s.op == SWAP_LOG_DEL) {
155 CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key);
156
157 if (!olde)
d7ae3534 158 ++ idx->bad_del_count;
62e76326 159 else {
160 assert(idx->count);
161 hash_remove_link(idx->hash, (hash_link *) olde);
162 cacheEntryDestroy(olde);
5e263176 163 -- idx->count;
62e76326 164 }
165 } else {
166 fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count);
167 exit(-3);
168 }
8667b856 169 }
62e76326 170
1afe05c5 171 fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n",
62e76326 172 fname, count, (int) (count * sizeof(CacheEntry)));
8667b856 173 return count;
174}
175
176static void
1afe05c5 177cacheIndexCmpReport(CacheIndex * idx, int shared_count)
8667b856 178{
179 assert(idx && shared_count <= idx->count);
180
f97c9706 181 printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n",
62e76326 182 idx->name,
183 idx->count,
184 idx->count - shared_count,
185 shared_count,
186 xpercent(idx->count - shared_count, idx->count),
187 xpercent(shared_count, idx->count));
8667b856 188}
189
190static void
1afe05c5 191cacheIndexCmp(CacheIndex * idx1, CacheIndex * idx2)
8667b856 192{
193 int shared_count = 0;
681e7924 194 int hashed_count = 0;
8667b856 195 hash_link *hashr = NULL;
196 CacheIndex *small_idx = idx1;
197 CacheIndex *large_idx = idx2;
198 assert(idx1 && idx2);
199
200 /* check our guess */
62e76326 201
8667b856 202 if (idx1->count > idx2->count) {
62e76326 203 small_idx = idx2;
204 large_idx = idx1;
8667b856 205 }
62e76326 206
8667b856 207 /* find shared_count */
0f6bebac 208 hash_first(small_idx->hash);
62e76326 209
0f6bebac 210 for (hashr = hash_next(small_idx->hash)) {
d7ae3534 211 ++hashed_count;
62e76326 212
213 if (hash_lookup(large_idx->hash, hashr->key))
d7ae3534 214 ++shared_count;
8667b856 215 }
62e76326 216
681e7924 217 assert(hashed_count == small_idx->count);
8667b856 218
219 cacheIndexCmpReport(idx1, shared_count);
220 cacheIndexCmpReport(idx2, shared_count);
221}
222
8667b856 223static int
224usage(const char *prg_name)
225{
226 fprintf(stderr, "usage: %s <label1>: <swap_state>... <label2>: <swap_state>...\n",
62e76326 227 prg_name);
24885773 228 return EXIT_FAILURE;
8667b856 229}
230
231int
232main(int argc, char *argv[])
233{
234 CacheIndex *CacheIdx[2];
235 CacheIndex *idx = NULL;
236 int idxCount = 0;
237 int i;
238
239 if (argc < 5)
62e76326 240 return usage(argv[0]);
8667b856 241
242 for (i = 1; i < argc; ++i) {
62e76326 243 const int len = strlen(argv[i]);
244
245 if (!len)
246 return usage(argv[0]);
247
248 if (argv[i][len - 1] == ':') {
d7ae3534 249 ++idxCount;
62e76326 250
251 if (len < 2 || idxCount > 2)
252 return usage(argv[0]);
253
254 idx = cacheIndexCreate(argv[i]);
255
256 CacheIdx[idxCount - 1] = idx;
257 } else {
258 if (!idx)
259 return usage(argv[0]);
260
261 cacheIndexAddLog(idx, argv[i]);
262 }
8667b856 263 }
264
265 if (idxCount != 2)
62e76326 266 return usage(argv[0]);
8667b856 267
268 cacheIndexInitReport(CacheIdx[0]);
62e76326 269
8667b856 270 cacheIndexInitReport(CacheIdx[1]);
271
272 cacheIndexCmp(CacheIdx[0], CacheIdx[1]);
273
274 cacheIndexDestroy(CacheIdx[0]);
62e76326 275
8667b856 276 cacheIndexDestroy(CacheIdx[1]);
277
24885773 278 return EXIT_FAILURE;
8667b856 279}
f53969cc 280