aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/gnunet-service-testbed_hc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/gnunet-service-testbed_hc.c')
-rw-r--r--src/testbed/gnunet-service-testbed_hc.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/testbed/gnunet-service-testbed_hc.c b/src/testbed/gnunet-service-testbed_hc.c
new file mode 100644
index 000000000..569dc18f8
--- /dev/null
+++ b/src/testbed/gnunet-service-testbed_hc.c
@@ -0,0 +1,194 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file testbed/gnunet-service-testbed_hc.h
23 * @brief testbed cache implementation
24 * @author Sree Harsha Totakura
25 */
26
27#include "gnunet-service-testbed.h"
28
29/**
30 * Hello cache entry
31 */
32struct HelloCacheEntry
33{
34 /**
35 * DLL next ptr for least recently used hello cache entries
36 */
37 struct HelloCacheEntry *next;
38
39 /**
40 * DLL prev ptr for least recently used hello cache entries
41 */
42 struct HelloCacheEntry *prev;
43
44 /**
45 * The key for this entry
46 */
47 struct GNUNET_HashCode key;
48
49 /**
50 * The HELLO message
51 */
52 struct GNUNET_MessageHeader *hello;
53};
54
55/**
56 * Hashmap to maintain HELLO cache
57 */
58static struct GNUNET_CONTAINER_MultiHashMap *hello_cache;
59
60/**
61 * DLL head for least recently used hello cache entries; least recently used
62 * cache items are at the head
63 */
64static struct HelloCacheEntry *lru_hcache_head;
65
66/**
67 * DLL tail for least recently used hello cache entries; recently used cache
68 * items are at the tail
69 */
70static struct HelloCacheEntry *lru_hcache_tail;
71
72/**
73 * The size of HELLO cache
74 */
75static unsigned int hello_cache_size;
76
77
78/**
79 * Looks up in the hello cache and returns the HELLO of the given peer
80 *
81 * @param id the peer identity of the peer whose HELLO has to be looked up
82 * @return the HELLO message; NULL if not found
83 */
84const struct GNUNET_MessageHeader *
85TESTBED_hello_cache_lookup (const struct GNUNET_PeerIdentity *id)
86{
87 struct HelloCacheEntry *entry;
88
89 if (NULL == hello_cache)
90 return NULL;
91 entry = GNUNET_CONTAINER_multihashmap_get (hello_cache, &id->hashPubKey);
92 if (NULL == entry)
93 return NULL;
94 GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry);
95 GNUNET_CONTAINER_DLL_insert_tail (lru_hcache_head, lru_hcache_tail, entry);
96 return entry->hello;
97}
98
99
100/**
101 * Removes the given hello cache centry from hello cache and frees its resources
102 *
103 * @param entry the entry to remove
104 */
105static void
106TESTBED_hello_cache_remove (struct HelloCacheEntry *entry)
107{
108 GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry);
109 GNUNET_assert (GNUNET_YES ==
110 GNUNET_CONTAINER_multihashmap_remove (hello_cache,
111 &entry->key,
112 entry));
113 GNUNET_free (entry->hello);
114 GNUNET_free (entry);
115}
116
117
118/**
119 * Caches the HELLO of the given peer. Updates the HELLO if it was already
120 * cached before
121 *
122 * @param id the peer identity of the peer whose HELLO has to be cached
123 * @param hello the HELLO message
124 */
125void
126TESTBED_hello_cache_add (const struct GNUNET_PeerIdentity *id,
127 const struct GNUNET_MessageHeader *hello)
128{
129 struct HelloCacheEntry *entry;
130
131 if (NULL == hello_cache)
132 return;
133 entry = GNUNET_CONTAINER_multihashmap_get (hello_cache, &id->hashPubKey);
134 if (NULL == entry)
135 {
136 entry = GNUNET_malloc (sizeof (struct HelloCacheEntry));
137 memcpy (&entry->key, &id->hashPubKey, sizeof (struct GNUNET_HashCode));
138 if (GNUNET_CONTAINER_multihashmap_size (hello_cache) == hello_cache_size)
139 {
140 GNUNET_assert (NULL != lru_hcache_head);
141 TESTBED_hello_cache_remove (lru_hcache_head);
142 }
143 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put
144 (hello_cache,
145 &entry->key,
146 entry,
147 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
148 }
149 else
150 {
151 GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry);
152 GNUNET_free (entry->hello);
153 }
154 entry->hello = GNUNET_copy_message (hello);
155 GNUNET_CONTAINER_DLL_insert_tail (lru_hcache_head, lru_hcache_tail, entry);
156}
157
158
159/**
160 * Initializes the cache
161 *
162 * @param size the size of the cache
163 */
164void
165TESTBED_cache_init (unsigned int size)
166{
167 if (0 == size)
168 return;
169 hello_cache_size = size;
170 if (size > 1)
171 size = size / 2;
172 hello_cache = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_YES);
173}
174
175
176/**
177 * Clear cache
178 */
179void
180TESTBED_cache_clear ()
181{
182 if (NULL != hello_cache)
183 GNUNET_assert
184 (GNUNET_CONTAINER_multihashmap_size (hello_cache) <= hello_cache_size);
185 while (NULL != lru_hcache_head)
186 TESTBED_hello_cache_remove (lru_hcache_head);
187 if (NULL != hello_cache)
188 {
189 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (hello_cache));
190 GNUNET_CONTAINER_multihashmap_destroy (hello_cache);
191 }
192}
193
194/* end of gnunet-service-testbed_hc.c */