CacheDigest.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:9k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: CacheDigest.c,v 1.29 1998/12/05 00:54:08 wessels Exp $
  3.  *
  4.  * DEBUG: section 70    Cache Digest
  5.  * AUTHOR: Alex Rousskov
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  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.
  23.  *  
  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.
  28.  *  
  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
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. #if USE_CACHE_DIGESTS
  36. /* local types */
  37. typedef struct {
  38.     int bit_count; /* total number of bits */
  39.     int bit_on_count; /* #bits turned on */
  40.     int bseq_len_sum; /* sum of all bit seq length */
  41.     int bseq_count; /* number of bit seqs */
  42. } CacheDigestStats;
  43. /* local functions */
  44. static void cacheDigestHashKey(const CacheDigest * cd, const cache_key * key);
  45. /* static array used by cacheDigestHashKey for optimization purposes */
  46. static u_num32 hashed_keys[4];
  47. static void
  48. cacheDigestInit(CacheDigest * cd, int capacity, int bpe)
  49. {
  50.     const size_t mask_size = cacheDigestCalcMaskSize(capacity, bpe);
  51.     assert(cd);
  52.     assert(capacity > 0 && bpe > 0);
  53.     assert(mask_size > 0);
  54.     cd->capacity = capacity;
  55.     cd->bits_per_entry = bpe;
  56.     cd->mask_size = mask_size;
  57.     cd->mask = xcalloc(cd->mask_size, 1);
  58.     debug(70, 2) ("cacheDigestInit: capacity: %d entries, bpe: %d; size: %d bytesn",
  59. cd->capacity, cd->bits_per_entry, cd->mask_size);
  60. }
  61. CacheDigest *
  62. cacheDigestCreate(int capacity, int bpe)
  63. {
  64.     CacheDigest *cd = memAllocate(MEM_CACHE_DIGEST);
  65.     assert(MD5_DIGEST_CHARS == 16); /* our hash functions rely on 16 byte keys */
  66.     cacheDigestInit(cd, capacity, bpe);
  67.     return cd;
  68. }
  69. static void
  70. cacheDigestClean(CacheDigest * cd)
  71. {
  72.     assert(cd);
  73.     xfree(cd->mask);
  74.     cd->mask = NULL;
  75. }
  76. void
  77. cacheDigestDestroy(CacheDigest * cd)
  78. {
  79.     assert(cd);
  80.     cacheDigestClean(cd);
  81.     memFree(cd, MEM_CACHE_DIGEST);
  82. }
  83. CacheDigest *
  84. cacheDigestClone(const CacheDigest * cd)
  85. {
  86.     CacheDigest *clone;
  87.     assert(cd);
  88.     clone = cacheDigestCreate(cd->capacity, cd->bits_per_entry);
  89.     clone->count = cd->count;
  90.     clone->del_count = cd->del_count;
  91.     assert(cd->mask_size == clone->mask_size);
  92.     xmemcpy(clone->mask, cd->mask, cd->mask_size);
  93.     return clone;
  94. }
  95. void
  96. cacheDigestClear(CacheDigest * cd)
  97. {
  98.     assert(cd);
  99.     cd->count = cd->del_count = 0;
  100.     memset(cd->mask, 0, cd->mask_size);
  101. }
  102. /* changes mask size, resets bits to 0, preserves "cd" pointer */
  103. void
  104. cacheDigestChangeCap(CacheDigest * cd, int new_cap)
  105. {
  106.     assert(cd);
  107.     cacheDigestClean(cd);
  108.     cacheDigestInit(cd, new_cap, cd->bits_per_entry);
  109. }
  110. /* returns true if the key belongs to the digest */
  111. int
  112. cacheDigestTest(const CacheDigest * cd, const cache_key * key)
  113. {
  114.     assert(cd && key);
  115.     /* hash */
  116.     cacheDigestHashKey(cd, key);
  117.     /* test corresponding bits */
  118.     return
  119. CBIT_TEST(cd->mask, hashed_keys[0]) &&
  120. CBIT_TEST(cd->mask, hashed_keys[1]) &&
  121. CBIT_TEST(cd->mask, hashed_keys[2]) &&
  122. CBIT_TEST(cd->mask, hashed_keys[3]);
  123. }
  124. void
  125. cacheDigestAdd(CacheDigest * cd, const cache_key * key)
  126. {
  127.     assert(cd && key);
  128.     /* hash */
  129.     cacheDigestHashKey(cd, key);
  130.     /* turn on corresponding bits */
  131. #if CD_FAST_ADD
  132.     CBIT_SET(cd->mask, hashed_keys[0]);
  133.     CBIT_SET(cd->mask, hashed_keys[1]);
  134.     CBIT_SET(cd->mask, hashed_keys[2]);
  135.     CBIT_SET(cd->mask, hashed_keys[3]);
  136. #else
  137.     {
  138. int on_xition_cnt = 0;
  139. if (!CBIT_TEST(cd->mask, hashed_keys[0])) {
  140.     CBIT_SET(cd->mask, hashed_keys[0]);
  141.     on_xition_cnt++;
  142. }
  143. if (!CBIT_TEST(cd->mask, hashed_keys[1])) {
  144.     CBIT_SET(cd->mask, hashed_keys[1]);
  145.     on_xition_cnt++;
  146. }
  147. if (!CBIT_TEST(cd->mask, hashed_keys[2])) {
  148.     CBIT_SET(cd->mask, hashed_keys[2]);
  149.     on_xition_cnt++;
  150. }
  151. if (!CBIT_TEST(cd->mask, hashed_keys[3])) {
  152.     CBIT_SET(cd->mask, hashed_keys[3]);
  153.     on_xition_cnt++;
  154. }
  155. statHistCount(&Counter.cd.on_xition_count, on_xition_cnt);
  156.     }
  157. #endif
  158.     cd->count++;
  159. }
  160. void
  161. cacheDigestDel(CacheDigest * cd, const cache_key * key)
  162. {
  163.     assert(cd && key);
  164.     cd->del_count++;
  165.     /* we do not support deletions from the digest */
  166. }
  167. /* returns mask utilization parameters */
  168. static void
  169. cacheDigestStats(const CacheDigest * cd, CacheDigestStats * stats)
  170. {
  171.     int on_count = 0;
  172.     int pos = cd->mask_size * 8;
  173.     int seq_len_sum = 0;
  174.     int seq_count = 0;
  175.     int cur_seq_len = 0;
  176.     int cur_seq_type = 1;
  177.     assert(stats);
  178.     memset(stats, 0, sizeof(*stats));
  179.     while (pos-- > 0) {
  180. const int is_on = 0 != CBIT_TEST(cd->mask, pos);
  181. if (is_on)
  182.     on_count++;
  183. if (is_on != cur_seq_type || !pos) {
  184.     seq_len_sum += cur_seq_len;
  185.     seq_count++;
  186.     cur_seq_type = is_on;
  187.     cur_seq_len = 0;
  188. }
  189. cur_seq_len++;
  190.     }
  191.     stats->bit_count = cd->mask_size * 8;
  192.     stats->bit_on_count = on_count;
  193.     stats->bseq_len_sum = seq_len_sum;
  194.     stats->bseq_count = seq_count;
  195. }
  196. int
  197. cacheDigestBitUtil(const CacheDigest * cd)
  198. {
  199.     CacheDigestStats stats;
  200.     assert(cd);
  201.     cacheDigestStats(cd, &stats);
  202.     return xpercentInt(stats.bit_on_count, stats.bit_count);
  203. }
  204. void
  205. cacheDigestGuessStatsUpdate(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. void
  221. cacheDigestGuessStatsReport(const cd_guess_stats * stats, StoreEntry * sentry, const char *label)
  222. {
  223.     const int true_count = stats->true_hits + stats->true_misses;
  224.     const int false_count = stats->false_hits + stats->false_misses;
  225.     const int hit_count = stats->true_hits + stats->false_hits;
  226.     const int miss_count = stats->true_misses + stats->false_misses;
  227.     const int tot_count = true_count + false_count;
  228.     assert(label);
  229.     assert(tot_count == hit_count + miss_count); /* paranoid */
  230.     if (!tot_count) {
  231. storeAppendPrintf(sentry, "no guess stats for %s availablen", label);
  232. return;
  233.     }
  234.     storeAppendPrintf(sentry, "Digest guesses stats for %s:n", label);
  235.     storeAppendPrintf(sentry, "guesst hittt misstt totalttn");
  236.     storeAppendPrintf(sentry, " t #t %%t #t %%t #t %%tn");
  237.     storeAppendPrintf(sentry, "truet %dt %.2ft %dt %.2ft %dt %.2fn",
  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, "falset %dt %.2ft %dt %.2ft %dt %.2fn",
  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, "allt %dt %.2ft %dt %.2ft %dt %.2fn",
  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.     storeAppendPrintf(sentry, "tclose_hits: %d ( %d%%) /* cd said hit, doc was in the peer cache, but we got a miss */n",
  250. stats->close_hits, xpercentInt(stats->close_hits, stats->false_hits));
  251. }
  252. void
  253. cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e)
  254. {
  255.     CacheDigestStats stats;
  256.     assert(cd && e);
  257.     cacheDigestStats(cd, &stats);
  258.     storeAppendPrintf(e, "%s digest: size: %d bytesn",
  259. label ? label : "", stats.bit_count / 8
  260. );
  261.     storeAppendPrintf(e, "t entries: count: %d capacity: %d util: %d%%n",
  262. cd->count,
  263. cd->capacity,
  264. xpercentInt(cd->count, cd->capacity)
  265. );
  266.     storeAppendPrintf(e, "t deletion attempts: %dn",
  267. cd->del_count
  268. );
  269.     storeAppendPrintf(e, "t bits: per entry: %d on: %d capacity: %d util: %d%%n",
  270. cd->bits_per_entry,
  271. stats.bit_on_count, stats.bit_count,
  272. xpercentInt(stats.bit_on_count, stats.bit_count)
  273. );
  274.     storeAppendPrintf(e, "t bit-seq: count: %d avg.len: %.2fn",
  275. stats.bseq_count,
  276. xdiv(stats.bseq_len_sum, stats.bseq_count)
  277. );
  278. }
  279. size_t
  280. cacheDigestCalcMaskSize(int cap, int bpe)
  281. {
  282.     return (size_t) (cap * bpe + 7) / 8;
  283. }
  284. static void
  285. cacheDigestHashKey(const CacheDigest * cd, const cache_key * key)
  286. {
  287.     const unsigned int bit_count = cd->mask_size * 8;
  288.     unsigned int tmp_keys[4];
  289.     /* we must memcpy to ensure alignment */
  290.     xmemcpy(tmp_keys, key, sizeof(tmp_keys));
  291.     hashed_keys[0] = htonl(tmp_keys[0]) % bit_count;
  292.     hashed_keys[1] = htonl(tmp_keys[1]) % bit_count;
  293.     hashed_keys[2] = htonl(tmp_keys[2]) % bit_count;
  294.     hashed_keys[3] = htonl(tmp_keys[3]) % bit_count;
  295.     debug(70, 9) ("cacheDigestHashKey: %s -(%d)-> %d %d %d %dn",
  296. storeKeyText(key), bit_count,
  297. hashed_keys[0], hashed_keys[1], hashed_keys[2], hashed_keys[3]);
  298. }
  299. #endif