]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/cache_diff.cc
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
10 * Computes the difference between the contents of two caches
12 * Reports the percentage of common files and other stats
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 */
27 typedef struct _CacheEntry
{
30 struct _CacheEntry
*next
;
31 /* StoreSwapLogData s; */
32 unsigned char key_arr
[SQUID_MD5_DIGEST_LENGTH
];
35 static int cacheIndexScan(CacheIndex
* idx
, const char *fname
, FILE * file
);
38 cacheEntryCreate(const StoreSwapLogData
* s
)
40 CacheEntry
*e
= xcalloc(1, sizeof(CacheEntry
));
43 memcpy(e
->key_arr
, s
->key
, SQUID_MD5_DIGEST_LENGTH
);
44 e
->key
= &e
->key_arr
[0];
49 cacheEntryDestroy(CacheEntry
* e
)
56 cacheIndexCreate(const char *name
)
60 if (!name
|| !strlen(name
))
63 idx
= xcalloc(1, sizeof(CacheIndex
));
67 idx
->hash
= hash_create(storeKeyHashCmp
, 2e6
, storeKeyHashHash
);
73 cacheIndexDestroy(CacheIndex
* idx
)
75 hash_link
*hashr
= NULL
;
78 /* destroy hash list contents */
79 hash_first(idx
->hash
);
81 while (hashr
= hash_next(idx
->hash
)) {
82 hash_remove_link(idx
->hash
, hashr
);
83 cacheEntryDestroy((CacheEntry
*) hashr
);
86 /* destroy the hash table itself */
87 hashFreeMemory(idx
->hash
);
94 cacheIndexAddLog(CacheIndex
* idx
, const char *fname
)
97 int scanned_count
= 0;
99 assert(fname
&& strlen(fname
));
101 file
= fopen(fname
, "r");
104 fprintf(stderr
, "cannot open %s: %s\n", fname
, strerror(errno
));
109 setmode(fileno(file
), O_BINARY
);
112 scanned_count
= cacheIndexScan(idx
, fname
, file
);
116 return scanned_count
;
120 cacheIndexInitReport(CacheIndex
* idx
)
123 fprintf(stderr
, "%s: bad swap_add: %d\n",
124 idx
->name
, idx
->bad_add_count
);
125 fprintf(stderr
, "%s: bad swap_del: %d\n",
126 idx
->name
, idx
->bad_del_count
);
127 fprintf(stderr
, "%s: scanned lines: %d\n",
128 idx
->name
, idx
->scanned_count
);
132 cacheIndexScan(CacheIndex
* idx
, const char *fname
, FILE * file
)
136 fprintf(stderr
, "%s scanning\n", fname
);
138 while (fread(&s
, sizeof(s
), 1, file
) == 1) {
140 ++ idx
->scanned_count
;
144 if (s
.op
== SWAP_LOG_ADD
) {
145 CacheEntry
*olde
= (CacheEntry
*) hash_lookup(idx
->hash
, s
.key
);
148 ++ idx
->bad_add_count
;
150 CacheEntry
*e
= cacheEntryCreate(&s
);
151 hash_join(idx
->hash
, &e
->hash
);
154 } else if (s
.op
== SWAP_LOG_DEL
) {
155 CacheEntry
*olde
= (CacheEntry
*) hash_lookup(idx
->hash
, s
.key
);
158 ++ idx
->bad_del_count
;
161 hash_remove_link(idx
->hash
, (hash_link
*) olde
);
162 cacheEntryDestroy(olde
);
166 fprintf(stderr
, "%s:%d: unknown swap log action\n", fname
, count
);
171 fprintf(stderr
, "%s:%d: scanned (size: %d bytes)\n",
172 fname
, count
, (int) (count
* sizeof(CacheEntry
)));
177 cacheIndexCmpReport(CacheIndex
* idx
, int shared_count
)
179 assert(idx
&& shared_count
<= idx
->count
);
181 printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n",
184 idx
->count
- shared_count
,
186 xpercent(idx
->count
- shared_count
, idx
->count
),
187 xpercent(shared_count
, idx
->count
));
191 cacheIndexCmp(CacheIndex
* idx1
, CacheIndex
* idx2
)
193 int shared_count
= 0;
194 int hashed_count
= 0;
195 hash_link
*hashr
= NULL
;
196 CacheIndex
*small_idx
= idx1
;
197 CacheIndex
*large_idx
= idx2
;
198 assert(idx1
&& idx2
);
200 /* check our guess */
202 if (idx1
->count
> idx2
->count
) {
207 /* find shared_count */
208 hash_first(small_idx
->hash
);
210 for (hashr
= hash_next(small_idx
->hash
)) {
213 if (hash_lookup(large_idx
->hash
, hashr
->key
))
217 assert(hashed_count
== small_idx
->count
);
219 cacheIndexCmpReport(idx1
, shared_count
);
220 cacheIndexCmpReport(idx2
, shared_count
);
224 usage(const char *prg_name
)
226 fprintf(stderr
, "usage: %s <label1>: <swap_state>... <label2>: <swap_state>...\n",
232 main(int argc
, char *argv
[])
234 CacheIndex
*CacheIdx
[2];
235 CacheIndex
*idx
= NULL
;
240 return usage(argv
[0]);
242 for (i
= 1; i
< argc
; ++i
) {
243 const int len
= strlen(argv
[i
]);
246 return usage(argv
[0]);
248 if (argv
[i
][len
- 1] == ':') {
251 if (len
< 2 || idxCount
> 2)
252 return usage(argv
[0]);
254 idx
= cacheIndexCreate(argv
[i
]);
256 CacheIdx
[idxCount
- 1] = idx
;
259 return usage(argv
[0]);
261 cacheIndexAddLog(idx
, argv
[i
]);
266 return usage(argv
[0]);
268 cacheIndexInitReport(CacheIdx
[0]);
270 cacheIndexInitReport(CacheIdx
[1]);
272 cacheIndexCmp(CacheIdx
[0], CacheIdx
[1]);
274 cacheIndexDestroy(CacheIdx
[0]);
276 cacheIndexDestroy(CacheIdx
[1]);