1 /* $Id: cache.c 6169 2003-01-21 06:31:40Z alexk $
3 ** MessageID to storage token cache
5 ** Written by Alex Kiernan (alex.kiernan@thus.net)
7 ** Implementation of a message ID to storage token cache which can be
8 ** built during XOVER/XHDR/NEWNEWS. If we hit in the cache when
9 ** retrieving articles the (relatively) expensive cost of a trip
10 ** through the history database is saved.
16 #include "inn/innconf.h"
25 ** Pointer to the message ID to storage token ternary search tree
27 static struct tst *msgidcache;
30 ** Count of message IDs in the cache so that someone doing GROUP,
31 ** XOVER, GROUP, XOVER etc. for example doesn't blow up with out of
34 static int msgcachecount;
42 static struct list unused, used;
45 ** Add a translation from HASH, h, to TOKEN, t, to the message ID
49 cache_add(const HASH h, const TOKEN t)
51 if (innconf->msgidcachesize != 0) {
52 struct cache_entry *entry;
53 const unsigned char *p;
54 struct cache_entry *exist;
57 msgidcache = tst_init((innconf->msgidcachesize + 9) / 10);
62 entry = xmalloc(sizeof *entry);
65 p = (unsigned char *) HashToText(h);
66 if (tst_insert(msgidcache, p, entry,
67 0, (void **)&exist) == TST_DUPLICATE_KEY) {
69 list_remove(&exist->node);
70 list_addtail(&unused, &exist->node);
72 list_addtail(&unused, &entry->node);
75 if (msgcachecount >= innconf->msgidcachesize) {
76 /* need to throw away a node */
77 entry = (struct cache_entry *)list_remhead(&used);
79 entry = (struct cache_entry *)list_remhead(&unused);
81 tst_delete(msgidcache,
82 (unsigned char *) HashToText(entry->hash));
91 ** Lookup (and remove if found) a MessageID to TOKEN mapping. If this
92 ** is a final lookup (ARTICLE or BODY) we remove it if we find it
93 ** since this matches the observed behaviour of most clients, but
94 ** cache it just in case we can reuse it if they issue multiple
95 ** commands against the same message ID (e.g. HEAD, BODY).
98 cache_get(const HASH h, bool final)
100 static HASH last_hash;
101 static TOKEN last_token;
102 static const TOKEN empty_token = { TOKEN_EMPTY, 0, "" };
104 if (HashCompare(&h, &last_hash) == 0 && !HashEmpty(last_hash))
108 struct cache_entry *entry;
110 entry = tst_search(msgidcache, (unsigned char *) HashToText(h));
112 list_remove(&entry->node);
114 list_addtail(&unused, &entry->node);
116 list_addtail(&used, &entry->node);
117 last_hash = entry->hash;
118 last_token = entry->token;