]> git.ipfire.org Git - thirdparty/squid.git/blame - src/CacheDigest.cc
- temporary fix to prevent digests from overflows
[thirdparty/squid.git] / src / CacheDigest.cc
CommitLineData
bdbb6d04 1
2/*
e998b523 3 * $Id: CacheDigest.cc,v 1.14 1998/04/18 06:54:08 rousskov Exp $
bdbb6d04 4 *
8638fc66 5 * DEBUG: section 70 Cache Digest
bdbb6d04 6 * AUTHOR: Alex Rousskov
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
31
32#include "squid.h"
33
12784378 34/* local types */
35typedef struct {
b644367b 36 int bit_count; /* total number of bits */
37 int bit_on_count; /* #bits turned on */
38 int bseq_len_sum; /* sum of all bit seq length */
39 int bseq_count; /* number of bit seqs */
12784378 40} CacheDigestStats;
41
42/* local functions */
56a1c446 43static void cacheDigestHashKey(const CacheDigest *cd, const cache_key *key);
304b267e 44static size_t cacheDigestCalcMaskSize(int cap);
12784378 45
46/* configuration params */
bdbb6d04 47static const int BitsPerEntry = 4;
48
49/* static array used by cacheDigestHashKey for optimization purposes */
50static u_num32 hashed_keys[4];
51
bdbb6d04 52
53CacheDigest *
54cacheDigestCreate(int capacity)
55{
304b267e 56 const size_t mask_size = cacheDigestCalcMaskSize(capacity);
56a1c446 57 CacheDigest *cd = cacheDigestSizedCreate(mask_size, capacity);
58 return cd;
59}
60
61/* use this method only if mask size is known a priory */
62CacheDigest *
63cacheDigestSizedCreate(size_t size, int capacity)
64{
65 CacheDigest *cd = memAllocate(MEM_CACHE_DIGEST);
1afe05c5 66 assert(MD5_DIGEST_CHARS == 16); /* our hash functions rely on 16 byte keys */
bdbb6d04 67 assert(capacity > 0);
68 cd->capacity = capacity;
56a1c446 69 cd->mask_size = size;
bdbb6d04 70 cd->mask = xcalloc(cd->mask_size, 1);
71 return cd;
72}
73
74void
1afe05c5 75cacheDigestDestroy(CacheDigest * cd)
bdbb6d04 76{
77 assert(cd);
78 xfree(cd->mask);
79 xfree(cd);
80}
81
6d80b36f 82CacheDigest *
83cacheDigestClone(const CacheDigest * cd)
84{
85 CacheDigest *clone;
86 assert(cd);
87 clone = cacheDigestCreate(cd->capacity);
c2186446 88 clone->count = cd->count;
6d80b36f 89 xmemcpy(clone->mask, cd->mask, cd->mask_size);
90 return clone;
91}
92
12784378 93void
94cacheDigestClear(CacheDigest * cd)
95{
96 assert(cd);
97 cd->count = cd->del_count = 0;
98 memset(cd->mask, 0, cd->mask_size);
99}
100
304b267e 101void
102cacheDigestChangeCap(CacheDigest * cd, int new_cap)
103{
104 assert(cd);
105 /* have to clear because capacity changes hash functions */
106 cacheDigestClear(cd);
107 cd->capacity = new_cap;
108 cd->mask_size = cacheDigestCalcMaskSize(new_cap);
109 cd->mask = xrealloc(cd->mask, cd->mask_size);
110}
111
bdbb6d04 112/* returns true if the key belongs to the digest */
113int
1afe05c5 114cacheDigestTest(const CacheDigest * cd, const cache_key * key)
bdbb6d04 115{
116 assert(cd && key);
117 /* hash */
56a1c446 118 cacheDigestHashKey(cd, key);
bdbb6d04 119 /* test corresponding bits */
1afe05c5 120 return
bdbb6d04 121 CBIT_TEST(cd->mask, hashed_keys[0]) &&
122 CBIT_TEST(cd->mask, hashed_keys[1]) &&
123 CBIT_TEST(cd->mask, hashed_keys[2]) &&
124 CBIT_TEST(cd->mask, hashed_keys[3]);
125}
126
c2186446 127void
128cacheDigestAdd(CacheDigest * cd, const cache_key * key)
129{
130 assert(cd && key);
131 /* hash */
56a1c446 132 cacheDigestHashKey(cd, key);
c2186446 133 /* turn on corresponding bits */
c135694e 134#if CD_FAST_ADD
c2186446 135 CBIT_SET(cd->mask, hashed_keys[0]);
136 CBIT_SET(cd->mask, hashed_keys[1]);
137 CBIT_SET(cd->mask, hashed_keys[2]);
138 CBIT_SET(cd->mask, hashed_keys[3]);
c135694e 139#else
140 {
141 int on_xition_cnt = 0;
142 if (!CBIT_TEST(cd->mask, hashed_keys[0])) {
143 CBIT_SET(cd->mask, hashed_keys[0]);
144 on_xition_cnt++;
145 }
146 if (!CBIT_TEST(cd->mask, hashed_keys[1])) {
147 CBIT_SET(cd->mask, hashed_keys[1]);
148 on_xition_cnt++;
149 }
150 if (!CBIT_TEST(cd->mask, hashed_keys[2])) {
151 CBIT_SET(cd->mask, hashed_keys[2]);
152 on_xition_cnt++;
153 }
154 if (!CBIT_TEST(cd->mask, hashed_keys[3])) {
155 CBIT_SET(cd->mask, hashed_keys[3]);
156 on_xition_cnt++;
157 }
e998b523 158#if SQUID_PEER_DIGEST
c135694e 159 statHistCount(&Counter.cd.on_xition_count, on_xition_cnt);
e998b523 160#endif
c135694e 161 }
162#endif
c2186446 163 cd->count++;
164}
165
bdbb6d04 166void
1afe05c5 167cacheDigestDel(CacheDigest * cd, const cache_key * key)
bdbb6d04 168{
169 assert(cd && key);
170 cd->del_count++;
171 /* we do not support deletions from the digest */
172}
173
c2186446 174/* returns mask utilization parameters */
12784378 175static void
b644367b 176cacheDigestStats(const CacheDigest * cd, CacheDigestStats * stats)
c2186446 177{
c2186446 178 int on_count = 0;
56a1c446 179 int pos = cd->mask_size * 8;
12784378 180 int seq_len_sum = 0;
181 int seq_count = 0;
182 int cur_seq_len = 0;
183 int cur_seq_type = 1;
184 assert(stats);
185 memset(stats, 0, sizeof(*stats));
c2186446 186 while (pos-- > 0) {
e998b523 187 const int is_on = 0 != CBIT_TEST(cd->mask, pos);
12784378 188 if (is_on)
c2186446 189 on_count++;
12784378 190 if (is_on != cur_seq_type || !pos) {
191 seq_len_sum += cur_seq_len;
192 seq_count++;
e998b523 193 cur_seq_type = is_on;
12784378 194 cur_seq_len = 0;
195 }
196 cur_seq_len++;
c2186446 197 }
56a1c446 198 stats->bit_count = cd->mask_size * 8;
12784378 199 stats->bit_on_count = on_count;
200 stats->bseq_len_sum = seq_len_sum;
201 stats->bseq_count = seq_count;
c2186446 202}
bdbb6d04 203
8638fc66 204void
56a1c446 205cacheDigestGuessStatsUpdate(cd_guess_stats *stats, int real_hit, int guess_hit)
206{
207 assert(stats);
208 if (real_hit) {
209 if (guess_hit)
210 stats->true_hits++;
211 else
212 stats->false_misses++;
213 } else {
214 if (guess_hit)
215 stats->false_hits++;
216 else
217 stats->true_misses++;
218 }
219}
220
221void
222cacheDigestGuessStatsReport(const cd_guess_stats *stats, StoreEntry * sentry, const char *label)
223{
224 const int true_count = stats->true_hits + stats->true_misses;
225 const int false_count = stats->false_hits + stats->false_misses;
226 const int hit_count = stats->true_hits + stats->false_hits;
227 const int miss_count = stats->true_misses + stats->false_misses;
228 const int tot_count = true_count + false_count;
229
230 assert(label);
231 assert(tot_count == hit_count + miss_count); /* paranoid */
232
233 storeAppendPrintf(sentry, "Digest guesses stats for %s:\n", label);
234 storeAppendPrintf(sentry, "guess\t hit\t\t miss\t\t total\t\t\n");
235 storeAppendPrintf(sentry, " \t #\t %%\t #\t %%\t #\t %%\t\n");
236
237 storeAppendPrintf(sentry, "true\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n",
238 stats->true_hits, xpercent(stats->true_hits, tot_count),
239 stats->true_misses, xpercent(stats->true_misses, tot_count),
240 true_count, xpercent(true_count, tot_count));
241 storeAppendPrintf(sentry, "false\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n",
242 stats->false_hits, xpercent(stats->false_hits, tot_count),
243 stats->false_misses, xpercent(stats->false_misses, tot_count),
244 false_count, xpercent(false_count, tot_count));
245 storeAppendPrintf(sentry, "all\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n",
246 hit_count, xpercent(hit_count, tot_count),
247 miss_count, xpercent(miss_count, tot_count),
248 tot_count, xpercent(tot_count, tot_count));
249}
250
251void
252cacheDigestReport(CacheDigest *cd, const char *label, StoreEntry * e)
8638fc66 253{
12784378 254 CacheDigestStats stats;
8638fc66 255 assert(cd && e);
12784378 256 cacheDigestStats(cd, &stats);
257 storeAppendPrintf(e, "%s digest: size: %d bytes\n",
b644367b 258 label ? label : "", stats.bit_count / 8
259 );
8638fc66 260 storeAppendPrintf(e, "\t entries: count: %d capacity: %d util: %d%%\n",
261 cd->count,
262 cd->capacity,
263 xpercentInt(cd->count, cd->capacity)
b644367b 264 );
265 storeAppendPrintf(e, "\t deletion attempts: %d\n",
8638fc66 266 cd->del_count
b644367b 267 );
268 storeAppendPrintf(e, "\t bits: on: %d capacity: %d util: %d%%\n",
12784378 269 stats.bit_on_count, stats.bit_count,
270 xpercentInt(stats.bit_on_count, stats.bit_count)
b644367b 271 );
272 storeAppendPrintf(e, "\t bit-seq: count: %d avg.len: %.2f\n",
12784378 273 stats.bseq_count,
274 xdiv(stats.bseq_len_sum, stats.bseq_count)
b644367b 275 );
8638fc66 276}
277
304b267e 278static size_t
279cacheDigestCalcMaskSize(int cap)
280{
281 return (size_t) (cap * BitsPerEntry + 7) / 8;
282}
283
bdbb6d04 284static void
56a1c446 285cacheDigestHashKey(const CacheDigest *cd, const cache_key *key)
bdbb6d04 286{
56a1c446 287 const int bit_count = cd->mask_size * 8;
bdbb6d04 288 /* get four hashed values */
289 memcpy(hashed_keys, key, sizeof(hashed_keys));
290 /* wrap */
291 hashed_keys[0] %= bit_count;
292 hashed_keys[1] %= bit_count;
293 hashed_keys[2] %= bit_count;
294 hashed_keys[3] %= bit_count;
56a1c446 295
296 debug(70,9) ("cacheDigestHashKey: %s -(%d)-> %d %d %d %d\n",
297 storeKeyText(key), bit_count, hashed_keys[0], hashed_keys[1], hashed_keys[2], hashed_keys[3]);
bdbb6d04 298}