diff options
-rw-r--r-- | src/testbed/gnunet-service-testbed.h | 115 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_hc.c | 428 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_oc.c | 4 |
3 files changed, 442 insertions, 105 deletions
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h index 157adc2ea..72ad5d15a 100644 --- a/src/testbed/gnunet-service-testbed.h +++ b/src/testbed/gnunet-service-testbed.h | |||
@@ -647,43 +647,6 @@ GST_destroy_peer (struct Peer *peer); | |||
647 | 647 | ||
648 | 648 | ||
649 | /** | 649 | /** |
650 | * Looks up in the hello cache and returns the HELLO of the given peer | ||
651 | * | ||
652 | * @param id the peer identity of the peer whose HELLO has to be looked up | ||
653 | * @return the HELLO message; NULL if not found | ||
654 | */ | ||
655 | const struct GNUNET_MessageHeader * | ||
656 | GST_cache_lookup (const struct GNUNET_PeerIdentity *id); | ||
657 | |||
658 | /** | ||
659 | * Caches the HELLO of the given peer. Updates the HELLO if it was already | ||
660 | * cached before | ||
661 | * | ||
662 | * @param id the peer identity of the peer whose HELLO has to be cached | ||
663 | * @param hello the HELLO message | ||
664 | */ | ||
665 | void | ||
666 | GST_cache_add (const struct GNUNET_PeerIdentity *id, | ||
667 | const struct GNUNET_MessageHeader *hello); | ||
668 | |||
669 | |||
670 | /** | ||
671 | * Initializes the cache | ||
672 | * | ||
673 | * @param size the size of the cache | ||
674 | */ | ||
675 | void | ||
676 | GST_cache_init (unsigned int size); | ||
677 | |||
678 | |||
679 | /** | ||
680 | * Clear cache | ||
681 | */ | ||
682 | void | ||
683 | GST_cache_clear (); | ||
684 | |||
685 | |||
686 | /** | ||
687 | * Finds the route with directly connected host as destination through which | 650 | * Finds the route with directly connected host as destination through which |
688 | * the destination host can be reached | 651 | * the destination host can be reached |
689 | * | 652 | * |
@@ -801,5 +764,83 @@ void | |||
801 | GST_free_roccq (); | 764 | GST_free_roccq (); |
802 | 765 | ||
803 | 766 | ||
767 | /** | ||
768 | * Initializes the cache | ||
769 | * | ||
770 | * @param size the size of the cache | ||
771 | */ | ||
772 | void | ||
773 | GST_cache_init (unsigned int size); | ||
774 | |||
775 | |||
776 | /** | ||
777 | * Clear cache | ||
778 | */ | ||
779 | void | ||
780 | GST_cache_clear (); | ||
781 | |||
782 | |||
783 | /** | ||
784 | * Looks up in the hello cache and returns the HELLO of the given peer | ||
785 | * | ||
786 | * @param peer_id the index of the peer whose HELLO has to be looked up | ||
787 | * @return the HELLO message; NULL if not found | ||
788 | */ | ||
789 | const struct GNUNET_MessageHeader * | ||
790 | GST_cache_lookup_hello (const unsigned int peer_id); | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Caches the HELLO of the given peer. Updates the HELLO if it was already | ||
795 | * cached before | ||
796 | * | ||
797 | * @param id the peer identity of the peer whose HELLO has to be cached | ||
798 | * @param hello the HELLO message | ||
799 | */ | ||
800 | void | ||
801 | GST_cache_add_hello (const unsigned int peer_id, | ||
802 | const struct GNUNET_MessageHeader *hello); | ||
803 | |||
804 | |||
805 | /** | ||
806 | * Callback from cache with needed handles set | ||
807 | * | ||
808 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
809 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
810 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
811 | */ | ||
812 | typedef void (*GST_cache_callback) (void *cls, struct GNUNET_CORE_Handle *ch, | ||
813 | struct GNUNET_TRANSPORT_Handle *th); | ||
814 | |||
815 | |||
816 | /** | ||
817 | * Get a transport handle with the given configuration. If the handle is already | ||
818 | * cached before, it will be retured in the given callback; the peer_id is used to lookup in the | ||
819 | * cache. If not a new operation is started to open the transport handle and | ||
820 | * will be given in the callback when it is available. | ||
821 | * | ||
822 | * @param peer_id the index of the peer | ||
823 | * @param cfg the configuration with which the transport handle has to be | ||
824 | * created if it was not present in the cache | ||
825 | * @param cb the callback to notify when the transport handle is available | ||
826 | * @param cb_cls the closure for the above callback | ||
827 | * @return the handle which can be used cancel or mark that the handle is no | ||
828 | * longer being used | ||
829 | */ | ||
830 | struct GSTCacheGetHandle * | ||
831 | GST_cache_get_handle_transport (unsigned int peer_id, | ||
832 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
833 | GST_cache_callback cb, | ||
834 | void *cb_cls); | ||
835 | |||
836 | |||
837 | /** | ||
838 | * Mark the GetCacheHandle as being done if a handle has been provided already | ||
839 | * or as being cancelled if the callback for the handle hasn't been called. | ||
840 | * | ||
841 | * @param cgh the CacheGetHandle handle | ||
842 | */ | ||
843 | void | ||
844 | GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh); | ||
804 | 845 | ||
805 | /* End of gnunet-service-testbed.h */ | 846 | /* End of gnunet-service-testbed.h */ |
diff --git a/src/testbed/gnunet-service-testbed_hc.c b/src/testbed/gnunet-service-testbed_hc.c index d1198dab1..de35c91e0 100644 --- a/src/testbed/gnunet-service-testbed_hc.c +++ b/src/testbed/gnunet-service-testbed_hc.c | |||
@@ -26,6 +26,47 @@ | |||
26 | 26 | ||
27 | #include "gnunet-service-testbed.h" | 27 | #include "gnunet-service-testbed.h" |
28 | 28 | ||
29 | |||
30 | #ifdef LOG | ||
31 | #undef LOG | ||
32 | #endif | ||
33 | |||
34 | #define LOG(kind,...) \ | ||
35 | GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) | ||
36 | |||
37 | /* #define LOG_DEBUG(...) \ */ | ||
38 | /* LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) */ | ||
39 | |||
40 | |||
41 | enum CacheGetType | ||
42 | { | ||
43 | CGT_TRANSPORT_HANDLE = 1 | ||
44 | }; | ||
45 | |||
46 | |||
47 | struct GSTCacheGetHandle | ||
48 | { | ||
49 | struct GNUNET_TESTBED_Operation *op; | ||
50 | |||
51 | struct CacheEntry *entry; | ||
52 | |||
53 | struct GNUNET_CORE_Handle *ch; | ||
54 | |||
55 | struct GNUNET_TRANSPORT_Handle *th; | ||
56 | |||
57 | void *handle; | ||
58 | |||
59 | GST_cache_callback cb; | ||
60 | |||
61 | void *cb_cls; | ||
62 | |||
63 | GNUNET_SCHEDULER_TaskIdentifier notify_task; | ||
64 | |||
65 | enum CacheGetType type; | ||
66 | |||
67 | int notify_called; | ||
68 | }; | ||
69 | |||
29 | /** | 70 | /** |
30 | * Cache entry | 71 | * Cache entry |
31 | */ | 72 | */ |
@@ -42,6 +83,29 @@ struct CacheEntry | |||
42 | struct CacheEntry *prev; | 83 | struct CacheEntry *prev; |
43 | 84 | ||
44 | /** | 85 | /** |
86 | * The transport handle to the peer corresponding to this entry; can be NULL | ||
87 | */ | ||
88 | struct GNUNET_TRANSPORT_Handle *transport_handle; | ||
89 | |||
90 | /** | ||
91 | * The operation handle for transport handle | ||
92 | */ | ||
93 | struct GNUNET_TESTBED_Operation *transport_op; | ||
94 | |||
95 | /** | ||
96 | * The configuration of the peer. Should be not NULL as long as the core_handle | ||
97 | * or transport_handle are valid | ||
98 | */ | ||
99 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
100 | |||
101 | /** | ||
102 | * The cache get handle which created this entry. Will be NULL after the | ||
103 | * operation for creating a core or transport handler is started, i.e. in the | ||
104 | * function opstart_get_handle_transport | ||
105 | */ | ||
106 | struct GSTCacheGetHandle *cgh; | ||
107 | |||
108 | /** | ||
45 | * The key for this entry | 109 | * The key for this entry |
46 | */ | 110 | */ |
47 | struct GNUNET_HashCode key; | 111 | struct GNUNET_HashCode key; |
@@ -50,6 +114,11 @@ struct CacheEntry | |||
50 | * The HELLO message | 114 | * The HELLO message |
51 | */ | 115 | */ |
52 | struct GNUNET_MessageHeader *hello; | 116 | struct GNUNET_MessageHeader *hello; |
117 | |||
118 | /** | ||
119 | * Number of operations this cache entry is being used | ||
120 | */ | ||
121 | unsigned int demand; | ||
53 | }; | 122 | }; |
54 | 123 | ||
55 | /** | 124 | /** |
@@ -59,98 +128,246 @@ static struct GNUNET_CONTAINER_MultiHashMap *cache; | |||
59 | 128 | ||
60 | /** | 129 | /** |
61 | * DLL head for least recently used cache entries; least recently used | 130 | * DLL head for least recently used cache entries; least recently used |
62 | * cache items are at the head | 131 | * cache items are at the head. The cache enties are added to this queue when |
132 | * their demand becomes zero. They are removed from the queue when they are | ||
133 | * needed by any operation. | ||
63 | */ | 134 | */ |
64 | static struct CacheEntry *lru_hcache_head; | 135 | static struct CacheEntry *lru_cache_head; |
65 | 136 | ||
66 | /** | 137 | /** |
67 | * DLL tail for least recently used cache entries; recently used cache | 138 | * DLL tail for least recently used cache entries; recently used cache |
68 | * items are at the tail | 139 | * items are at the tail.The cache enties are added to this queue when |
140 | * their demand becomes zero. They are removed from the queue when they are | ||
141 | * needed by any operation. | ||
142 | */ | ||
143 | static struct CacheEntry *lru_cache_tail; | ||
144 | |||
145 | /** | ||
146 | * the size of the LRU queue | ||
69 | */ | 147 | */ |
70 | static struct CacheEntry *lru_hcache_tail; | 148 | static unsigned int lru_cache_size; |
71 | 149 | ||
72 | /** | 150 | /** |
73 | * The size of cache | 151 | * the threshold size for the LRU queue |
74 | */ | 152 | */ |
75 | static unsigned int cache_size; | 153 | static unsigned int lru_cache_threshold_size; |
76 | 154 | ||
77 | 155 | ||
78 | /** | 156 | /** |
79 | * Looks up in the cache and returns the HELLO of the given peer | 157 | * Looks up in the cache and returns the entry |
80 | * | 158 | * |
81 | * @param id the peer identity of the peer whose HELLO has to be looked up | 159 | * @param id the peer identity of the peer whose corresponding entry has to be looked up |
82 | * @return the HELLO message; NULL if not found | 160 | * @return the HELLO message; NULL if not found |
83 | */ | 161 | */ |
84 | const struct GNUNET_MessageHeader * | 162 | static struct CacheEntry * |
85 | GST_cache_lookup (const struct GNUNET_PeerIdentity *id) | 163 | cache_lookup (const struct GNUNET_HashCode *key) |
86 | { | 164 | { |
87 | struct CacheEntry *entry; | 165 | struct CacheEntry *entry; |
88 | 166 | ||
89 | if (NULL == cache) | 167 | if (NULL == cache) |
90 | return NULL; | 168 | return NULL; |
91 | entry = GNUNET_CONTAINER_multihashmap_get (cache, &id->hashPubKey); | 169 | entry = GNUNET_CONTAINER_multihashmap_get (cache, key); |
170 | return entry; | ||
171 | } | ||
172 | |||
173 | |||
174 | static struct CacheEntry * | ||
175 | cache_lookup_handles (const struct GNUNET_HashCode *pid, | ||
176 | struct GNUNET_TRANSPORT_Handle **th) | ||
177 | { | ||
178 | struct CacheEntry *entry; | ||
179 | |||
180 | GNUNET_assert ((NULL != th)); | ||
181 | entry = cache_lookup (pid); | ||
92 | if (NULL == entry) | 182 | if (NULL == entry) |
93 | return NULL; | 183 | return NULL; |
94 | GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry); | 184 | if (0 == entry->demand) |
95 | GNUNET_CONTAINER_DLL_insert_tail (lru_hcache_head, lru_hcache_tail, entry); | 185 | GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry); |
96 | return entry->hello; | 186 | if ((NULL != th) && (NULL != entry->transport_handle)) |
187 | *th = entry->transport_handle; | ||
188 | return entry; | ||
97 | } | 189 | } |
98 | 190 | ||
99 | 191 | ||
100 | /** | ||
101 | * Removes the given cache entry from cache and frees its resources | ||
102 | * | ||
103 | * @param entry the entry to remove | ||
104 | */ | ||
105 | static void | 192 | static void |
106 | GST_cache_remove (struct CacheEntry *entry) | 193 | cache_remove (struct CacheEntry *entry) |
107 | { | 194 | { |
108 | GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry); | 195 | /* We keep the entry in the hash table so that the HELLO can still be found |
109 | GNUNET_assert (GNUNET_YES == | 196 | in cache; we will however disconnect the core and transport handles */ |
110 | GNUNET_CONTAINER_multihashmap_remove (cache, &entry->key, | 197 | GNUNET_assert (0 == entry->demand); |
111 | entry)); | 198 | GNUNET_assert (NULL != entry->cfg); |
112 | GNUNET_free (entry->hello); | 199 | GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry); |
113 | GNUNET_free (entry); | 200 | if (NULL != entry->transport_handle) |
201 | { | ||
202 | GNUNET_assert (NULL != entry->transport_op); | ||
203 | GNUNET_TESTBED_operation_done (entry->transport_op); | ||
204 | entry->transport_op = NULL; | ||
205 | } | ||
206 | GNUNET_CONFIGURATION_destroy (entry->cfg); | ||
207 | entry->cfg = NULL; | ||
114 | } | 208 | } |
115 | 209 | ||
116 | 210 | ||
117 | /** | 211 | static struct CacheEntry * |
118 | * Caches the HELLO of the given peer. Updates the HELLO if it was already | 212 | add_entry (const struct GNUNET_HashCode *key) |
119 | * cached before | ||
120 | * | ||
121 | * @param id the peer identity of the peer whose HELLO has to be cached | ||
122 | * @param hello the HELLO message | ||
123 | */ | ||
124 | void | ||
125 | GST_cache_add (const struct GNUNET_PeerIdentity *id, | ||
126 | const struct GNUNET_MessageHeader *hello) | ||
127 | { | 213 | { |
128 | struct CacheEntry *entry; | 214 | struct CacheEntry *entry; |
129 | 215 | ||
130 | if (NULL == cache) | 216 | entry = GNUNET_malloc (sizeof (struct CacheEntry)); |
217 | memcpy (&entry->key, key, sizeof (struct GNUNET_HashCode)); | ||
218 | GNUNET_assert (GNUNET_OK == | ||
219 | GNUNET_CONTAINER_multihashmap_put (cache, &entry->key, | ||
220 | entry, | ||
221 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
222 | return entry; | ||
223 | } | ||
224 | |||
225 | |||
226 | static void | ||
227 | cache_notify_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
228 | { | ||
229 | struct GSTCacheGetHandle *cgh = cls; | ||
230 | |||
231 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != cgh->notify_task); | ||
232 | cgh->notify_task = GNUNET_SCHEDULER_NO_TASK; | ||
233 | GNUNET_assert (NULL != cgh->entry); | ||
234 | cgh->entry->demand++; | ||
235 | cgh->notify_called = GNUNET_YES; | ||
236 | switch (cgh->type) | ||
237 | { | ||
238 | case CGT_TRANSPORT_HANDLE: | ||
239 | cgh->cb (cgh->cb_cls, NULL, cgh->handle); | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | |||
245 | static void | ||
246 | opstart_get_handle_transport (void *cls) | ||
247 | { | ||
248 | struct CacheEntry *entry = cls; | ||
249 | struct GSTCacheGetHandle *cgh = entry->cgh; | ||
250 | |||
251 | GNUNET_assert (NULL != entry); | ||
252 | GNUNET_assert (NULL != cgh); | ||
253 | GNUNET_assert (NULL != entry->cfg); | ||
254 | LOG_DEBUG ("Opening a transport connection\n"); | ||
255 | entry->cgh = NULL; | ||
256 | entry->transport_handle = GNUNET_TRANSPORT_connect (entry->cfg, | ||
257 | NULL, NULL, | ||
258 | NULL, | ||
259 | NULL, | ||
260 | NULL); | ||
261 | if (NULL == entry->transport_handle) | ||
262 | { | ||
263 | GNUNET_break (0); | ||
131 | return; | 264 | return; |
132 | entry = GNUNET_CONTAINER_multihashmap_get (cache, &id->hashPubKey); | 265 | } |
133 | if (NULL == entry) | 266 | cgh->handle = entry->transport_handle; |
267 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == cgh->notify_task); | ||
268 | cgh->notify_task = GNUNET_SCHEDULER_add_now (&cache_notify_callback, cgh); | ||
269 | } | ||
270 | |||
271 | |||
272 | static void | ||
273 | oprelease_get_handle_transport (void *cls) | ||
274 | { | ||
275 | struct CacheEntry *entry = cls; | ||
276 | |||
277 | if (NULL == entry->transport_handle) | ||
278 | return; | ||
279 | GNUNET_TRANSPORT_disconnect (entry->transport_handle); | ||
280 | entry->transport_handle = NULL; | ||
281 | } | ||
282 | |||
283 | |||
284 | static struct GSTCacheGetHandle * | ||
285 | cache_get_handle (unsigned int peer_id, | ||
286 | struct GSTCacheGetHandle *cgh, | ||
287 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
288 | { | ||
289 | struct GNUNET_HashCode key; | ||
290 | struct GNUNET_CORE_Handle *ch; | ||
291 | void *handle; | ||
292 | struct CacheEntry *entry; | ||
293 | |||
294 | GNUNET_assert (0 != cgh->type); | ||
295 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); | ||
296 | ch = NULL; | ||
297 | handle = NULL; | ||
298 | entry = NULL; | ||
299 | switch (cgh->type) | ||
134 | { | 300 | { |
135 | entry = GNUNET_malloc (sizeof (struct CacheEntry)); | 301 | case CGT_TRANSPORT_HANDLE: |
136 | memcpy (&entry->key, &id->hashPubKey, sizeof (struct GNUNET_HashCode)); | 302 | entry = cache_lookup_handles (&key, (struct GNUNET_TRANSPORT_Handle **) &handle); |
137 | if (GNUNET_CONTAINER_multihashmap_size (cache) == cache_size) | 303 | break; |
138 | { | ||
139 | GNUNET_assert (NULL != lru_hcache_head); | ||
140 | GST_cache_remove (lru_hcache_head); | ||
141 | } | ||
142 | GNUNET_assert (GNUNET_OK == | ||
143 | GNUNET_CONTAINER_multihashmap_put (cache, &entry->key, | ||
144 | entry, | ||
145 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
146 | } | 304 | } |
147 | else | 305 | if (NULL != handle) |
148 | { | 306 | { |
149 | GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry); | 307 | GNUNET_assert (NULL != entry); |
150 | GNUNET_free (entry->hello); | 308 | LOG_DEBUG ("Found existing transport handle in cache\n"); |
309 | cgh->entry = entry; | ||
310 | cgh->ch = ch; | ||
311 | cgh->handle = handle; | ||
312 | cgh->notify_task = GNUNET_SCHEDULER_add_now (&cache_notify_callback, cgh); | ||
313 | return cgh; | ||
151 | } | 314 | } |
152 | entry->hello = GNUNET_copy_message (hello); | 315 | if (NULL == entry) |
153 | GNUNET_CONTAINER_DLL_insert_tail (lru_hcache_head, lru_hcache_tail, entry); | 316 | entry = add_entry (&key); |
317 | if (NULL == entry->cfg) | ||
318 | entry->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
319 | cgh->entry = entry; | ||
320 | entry->cgh = cgh; | ||
321 | switch (cgh->type) | ||
322 | { | ||
323 | case CGT_TRANSPORT_HANDLE: | ||
324 | GNUNET_assert (NULL == entry->transport_op); | ||
325 | LOG_DEBUG ("Creating an operation for opening transport handle"); | ||
326 | entry->transport_op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_transport, | ||
327 | &oprelease_get_handle_transport); | ||
328 | GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, | ||
329 | entry->transport_op); | ||
330 | GNUNET_TESTBED_operation_begin_wait_ (entry->transport_op); | ||
331 | break; | ||
332 | } | ||
333 | return cgh; | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * Iterator over hash map entries. | ||
338 | * | ||
339 | * @param cls closure | ||
340 | * @param key current key code | ||
341 | * @param value value in the hash map | ||
342 | * @return GNUNET_YES if we should continue to | ||
343 | * iterate, | ||
344 | * GNUNET_NO if not. | ||
345 | */ | ||
346 | static int | ||
347 | cache_clear_iterator (void *cls, | ||
348 | const struct GNUNET_HashCode * key, | ||
349 | void *value) | ||
350 | { | ||
351 | struct CacheEntry *entry = value; | ||
352 | |||
353 | GNUNET_assert (NULL != entry); | ||
354 | GNUNET_CONTAINER_multihashmap_remove (cache, key, value); | ||
355 | GNUNET_free_non_null (entry->hello); | ||
356 | GNUNET_break (NULL == entry->transport_handle); | ||
357 | GNUNET_free (entry); | ||
358 | return GNUNET_YES; | ||
359 | } | ||
360 | |||
361 | |||
362 | /** | ||
363 | * Clear cache | ||
364 | */ | ||
365 | void | ||
366 | GST_cache_clear () | ||
367 | { | ||
368 | GNUNET_CONTAINER_multihashmap_iterate (cache, &cache_clear_iterator, NULL); | ||
369 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cache)); | ||
370 | GNUNET_CONTAINER_multihashmap_destroy (cache); | ||
154 | } | 371 | } |
155 | 372 | ||
156 | 373 | ||
@@ -164,7 +381,7 @@ GST_cache_init (unsigned int size) | |||
164 | { | 381 | { |
165 | if (0 == size) | 382 | if (0 == size) |
166 | return; | 383 | return; |
167 | cache_size = size; | 384 | lru_cache_threshold_size = size; |
168 | if (size > 1) | 385 | if (size > 1) |
169 | size = size / 2; | 386 | size = size / 2; |
170 | cache = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_YES); | 387 | cache = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_YES); |
@@ -172,21 +389,100 @@ GST_cache_init (unsigned int size) | |||
172 | 389 | ||
173 | 390 | ||
174 | /** | 391 | /** |
175 | * Clear cache | 392 | * Mark the GetCacheHandle as being done if a handle has been provided already |
393 | * or as being cancelled if the callback for the handle hasn't been called. | ||
394 | * | ||
395 | * @param cgh the CacheGetHandle handle | ||
176 | */ | 396 | */ |
177 | void | 397 | void |
178 | GST_cache_clear () | 398 | GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh) |
179 | { | 399 | { |
180 | if (NULL != cache) | 400 | if (GNUNET_SCHEDULER_NO_TASK != cgh->notify_task) |
181 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_size (cache) <= | 401 | GNUNET_SCHEDULER_cancel (cgh->notify_task); |
182 | cache_size); | 402 | if (GNUNET_YES == cgh->notify_called) |
183 | while (NULL != lru_hcache_head) | ||
184 | GST_cache_remove (lru_hcache_head); | ||
185 | if (NULL != cache) | ||
186 | { | 403 | { |
187 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cache)); | 404 | cgh->entry->demand--; |
188 | GNUNET_CONTAINER_multihashmap_destroy (cache); | 405 | if (0 == cgh->entry->demand) |
406 | { | ||
407 | GNUNET_CONTAINER_DLL_insert_tail (lru_cache_head, lru_cache_tail, cgh->entry); | ||
408 | if (lru_cache_size > lru_cache_threshold_size) | ||
409 | cache_remove (lru_cache_head); | ||
410 | } | ||
189 | } | 411 | } |
412 | GNUNET_free (cgh); | ||
413 | } | ||
414 | |||
415 | |||
416 | /** | ||
417 | * Get a transport handle with the given configuration. If the handle is already | ||
418 | * cached before, it will be retured in the given callback; the peer_id is used to lookup in the | ||
419 | * cache. If not a new operation is started to open the transport handle and | ||
420 | * will be given in the callback when it is available. | ||
421 | * | ||
422 | * @param peer_id the index of the peer | ||
423 | * @param cfg the configuration with which the transport handle has to be | ||
424 | * created if it was not present in the cache | ||
425 | * @param cb the callback to notify when the transport handle is available | ||
426 | * @param cb_cls the closure for the above callback | ||
427 | * @return the handle which can be used cancel or mark that the handle is no | ||
428 | * longer being used | ||
429 | */ | ||
430 | struct GSTCacheGetHandle * | ||
431 | GST_cache_get_handle_transport (unsigned int peer_id, | ||
432 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
433 | GST_cache_callback cb, | ||
434 | void *cb_cls) | ||
435 | { | ||
436 | struct GSTCacheGetHandle *cgh; | ||
437 | |||
438 | cgh = GNUNET_malloc (sizeof (struct GSTCacheGetHandle)); | ||
439 | cgh->cb = cb; | ||
440 | cgh->cb_cls = cb_cls; | ||
441 | cgh->type = CGT_TRANSPORT_HANDLE; | ||
442 | return cache_get_handle (peer_id, cgh, cfg); | ||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Looks up in the hello cache and returns the HELLO of the given peer | ||
448 | * | ||
449 | * @param peer_id the index of the peer whose HELLO has to be looked up | ||
450 | * @return the HELLO message; NULL if not found | ||
451 | */ | ||
452 | const struct GNUNET_MessageHeader * | ||
453 | GST_cache_lookup_hello (const unsigned int peer_id) | ||
454 | { | ||
455 | struct CacheEntry *entry; | ||
456 | struct GNUNET_HashCode key; | ||
457 | |||
458 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); | ||
459 | entry = cache_lookup (&key); | ||
460 | if (NULL == entry) | ||
461 | return NULL; | ||
462 | return entry->hello; | ||
463 | } | ||
464 | |||
465 | |||
466 | /** | ||
467 | * Caches the HELLO of the given peer. Updates the HELLO if it was already | ||
468 | * cached before | ||
469 | * | ||
470 | * @param id the peer identity of the peer whose HELLO has to be cached | ||
471 | * @param hello the HELLO message | ||
472 | */ | ||
473 | void | ||
474 | GST_cache_add_hello (const unsigned int peer_id, | ||
475 | const struct GNUNET_MessageHeader *hello) | ||
476 | { | ||
477 | struct CacheEntry *entry; | ||
478 | struct GNUNET_HashCode key; | ||
479 | |||
480 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); | ||
481 | entry = GNUNET_CONTAINER_multihashmap_get (cache, &key); | ||
482 | if (NULL == entry) | ||
483 | entry = add_entry (&key); | ||
484 | GNUNET_free_non_null (entry->hello); | ||
485 | entry->hello = GNUNET_copy_message (hello); | ||
190 | } | 486 | } |
191 | 487 | ||
192 | /* end of gnunet-service-testbed_hc.c */ | 488 | /* end of gnunet-service-testbed_hc.c */ |
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c index ccfdf162d..c437f8225 100644 --- a/src/testbed/gnunet-service-testbed_oc.c +++ b/src/testbed/gnunet-service-testbed_oc.c | |||
@@ -792,7 +792,7 @@ hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello) | |||
792 | LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id, | 792 | LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id, |
793 | GNUNET_i2s (&occ->peer_identity)); | 793 | GNUNET_i2s (&occ->peer_identity)); |
794 | occ->hello = GNUNET_malloc (msize); | 794 | occ->hello = GNUNET_malloc (msize); |
795 | GST_cache_add (&occ->peer_identity, hello); | 795 | GST_cache_add_hello (occ->peer_id, hello); |
796 | memcpy (occ->hello, hello, msize); | 796 | memcpy (occ->hello, hello, msize); |
797 | GNUNET_TRANSPORT_get_hello_cancel (occ->ghh); | 797 | GNUNET_TRANSPORT_get_hello_cancel (occ->ghh); |
798 | occ->ghh = NULL; | 798 | occ->ghh = NULL; |
@@ -837,7 +837,7 @@ core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server, | |||
837 | LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id, | 837 | LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id, |
838 | GNUNET_i2s (&occ->peer_identity)); | 838 | GNUNET_i2s (&occ->peer_identity)); |
839 | /* Lookup for HELLO in hello cache */ | 839 | /* Lookup for HELLO in hello cache */ |
840 | if (NULL != (hello = GST_cache_lookup (&occ->peer_identity))) | 840 | if (NULL != (hello = GST_cache_lookup_hello (occ->peer_id))) |
841 | { | 841 | { |
842 | LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id, | 842 | LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id, |
843 | GNUNET_i2s (&occ->peer_identity)); | 843 | GNUNET_i2s (&occ->peer_identity)); |