2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file testbed/gnunet-service-testbed_hc.h
23 * @brief testbed cache implementation
24 * @author Sree Harsha Totakura
26 #include "gnunet-service-testbed.h"
29 * Redefine LOG with a changed log component string
34 #define LOG(kind,...) \
35 GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__)
39 * Type of cache-get requests
44 * Get transport handle
46 CGT_TRANSPORT_HANDLE = 1,
56 * The cache-get request handle
58 struct GSTCacheGetHandle;
62 * This context structure is used to maintain a queue of notifications to check
63 * which of them are to be notified when a peer is connected.
65 struct ConnectNotifyContext
68 * The next ptr for the DLL
70 struct ConnectNotifyContext *next;
73 * The prev ptr for the DLL
75 struct ConnectNotifyContext *prev;
78 * The peer identity of the target peer. When this target peer is connected,
79 * call the notify callback
81 const struct GNUNET_PeerIdentity *target;
84 * The notify callback to be called when the target peer is connected
86 GST_cache_peer_connect_notify cb;
89 * The closure for the notify callback
94 * The GSTCacheGetHandle reposible for creating this context
96 struct GSTCacheGetHandle *cgh;
102 * The cache-get request handle
104 struct GSTCacheGetHandle
107 * The next ptr for the DLL. Used in struct CacheEntry
109 struct GSTCacheGetHandle *next;
112 * The prev ptr for the DLL. Used in struct CacheEntry
114 struct GSTCacheGetHandle *prev;
117 * The cache entry object this handle corresponds to
119 struct CacheEntry *entry;
122 * The cache callback to call when a handle is available
124 GST_cache_callback cb;
127 * The closure for the above callback
132 * The peer connect notify context created for this handle; can be NULL
134 struct ConnectNotifyContext *nctxt;
137 * The type of this cache-get request
139 enum CacheGetType type;
142 * Did we call the cache callback already?
153 * DLL next ptr for least recently used cache entries
155 struct CacheEntry *next;
158 * DLL prev ptr for least recently used cache entries
160 struct CacheEntry *prev;
163 * The transport handle to the peer corresponding to this entry; can be NULL
165 struct GNUNET_TRANSPORT_Handle *transport_handle_;
168 * The operation handle for transport handle
170 struct GNUNET_TESTBED_Operation *transport_op_;
173 * The core handle to the peer corresponding to this entry; can be NULL
175 struct GNUNET_CORE_Handle *core_handle;
178 * The operation handle for core handle
180 struct GNUNET_TESTBED_Operation *core_op;
183 * The peer identity of this peer. Will be set upon opening a connection to
184 * the peers CORE service. Will be NULL until then and after the CORE
185 * connection is closed
187 struct GNUNET_PeerIdentity *peer_identity;
190 * The configuration of the peer. Should be not NULL as long as the core_handle
191 * or transport_handle are valid
193 struct GNUNET_CONFIGURATION_Handle *cfg;
196 * The key for this entry
198 struct GNUNET_HashCode key;
203 struct GNUNET_MessageHeader *hello;
206 * the head of the CacheGetHandle queue
208 struct GSTCacheGetHandle *cgh_qhead;
211 * the tail of the CacheGetHandle queue
213 struct GSTCacheGetHandle *cgh_qtail;
216 * DLL head for the queue of notifications contexts to check which of them are to
217 * be notified when a peer is connected.
219 struct ConnectNotifyContext *nctxt_qhead;
222 * DLL tail for the queue of notifications contexts to check which of them are to
223 * be notified when a peer is connected.
225 struct ConnectNotifyContext *nctxt_qtail;
228 * The task that calls the cache callback
230 GNUNET_SCHEDULER_TaskIdentifier notify_task;
233 * Number of operations this cache entry is being used
238 * The id of the peer this entry corresponds to
240 unsigned int peer_id;
245 * Hashmap to maintain cache
247 static struct GNUNET_CONTAINER_MultiHashMap *cache;
250 * DLL head for least recently used cache entries; least recently used
251 * cache items are at the head. The cache enties are added to this queue when
252 * their demand becomes zero. They are removed from the queue when they are
253 * needed by any operation.
255 static struct CacheEntry *lru_cache_head;
258 * DLL tail for least recently used cache entries; recently used cache
259 * items are at the tail.The cache enties are added to this queue when
260 * their demand becomes zero. They are removed from the queue when they are
261 * needed by any operation.
263 static struct CacheEntry *lru_cache_tail;
266 * the size of the LRU queue
268 static unsigned int lru_cache_size;
271 * the threshold size for the LRU queue
273 static unsigned int lru_cache_threshold_size;
276 * The total number of elements in cache
278 static unsigned int cache_size;
282 * Looks up in the cache and returns the entry
284 * @param id the peer identity of the peer whose corresponding entry has to be looked up
285 * @return the HELLO message; NULL if not found
287 static struct CacheEntry *
288 cache_lookup (const struct GNUNET_HashCode *key)
290 struct CacheEntry *entry;
294 entry = GNUNET_CONTAINER_multihashmap_get (cache, key);
299 static struct CacheEntry *
300 cache_lookup_handles (const struct GNUNET_HashCode *pid,
301 struct GNUNET_TRANSPORT_Handle **th,
302 struct GNUNET_CORE_Handle **ch)
304 struct CacheEntry *entry;
306 GNUNET_assert ((NULL != th) || (NULL != ch));
307 entry = cache_lookup (pid);
310 if ((NULL != entry->transport_handle_) && (NULL != th))
311 *th = entry->transport_handle_;
312 if ((NULL != entry->core_handle) && (NULL != ch))
313 *ch = entry->core_handle;
319 cache_remove (struct CacheEntry *entry)
321 struct ConnectNotifyContext *ctxt;
323 /* We keep the entry in the hash table so that the HELLO can still be found
324 in cache; we will however disconnect the core and transport handles */
325 GNUNET_assert (0 == entry->demand);
326 if ((NULL != entry->next) || (NULL != entry->prev))
327 GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry);
328 while (NULL != (ctxt = entry->nctxt_qhead))
330 GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, ctxt);
333 LOG_DEBUG ("Cleaning up handles from an entry in cache\n");
334 if (NULL != entry->transport_handle_)
336 GNUNET_assert (NULL != entry->transport_op_);
337 GNUNET_TESTBED_operation_done (entry->transport_op_);
338 entry->transport_op_ = NULL;
340 if (NULL != entry->core_handle)
342 GNUNET_assert (NULL != entry->core_op);
343 GNUNET_TESTBED_operation_done (entry->core_op);
344 entry->core_op = NULL;
346 if (NULL != entry->cfg)
348 GNUNET_CONFIGURATION_destroy (entry->cfg);
354 static struct CacheEntry *
355 add_entry (const struct GNUNET_HashCode *key, unsigned int peer_id)
357 struct CacheEntry *entry;
359 entry = GNUNET_malloc (sizeof (struct CacheEntry));
360 entry->peer_id = peer_id;
361 memcpy (&entry->key, key, sizeof (struct GNUNET_HashCode));
362 GNUNET_assert (GNUNET_OK ==
363 GNUNET_CONTAINER_multihashmap_put (cache, &entry->key,
365 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
371 static struct GSTCacheGetHandle *
372 search_suitable_cgh (const struct CacheEntry *entry,
373 const struct GSTCacheGetHandle *head)
375 const struct GSTCacheGetHandle *cgh;
377 for (cgh=head; NULL != cgh; cgh=cgh->next)
379 if (GNUNET_YES == cgh->notify_called)
383 case CGT_TRANSPORT_HANDLE:
384 if (NULL == entry->transport_handle_)
387 case CGT_CORE_HANDLE:
388 if (NULL == entry->core_handle)
394 return (struct GSTCacheGetHandle *) cgh;
399 call_cgh_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
401 struct CacheEntry *entry = cls;
402 struct GSTCacheGetHandle *cgh;
403 const struct GSTCacheGetHandle *cgh2;
405 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != entry->notify_task);
406 entry->notify_task = GNUNET_SCHEDULER_NO_TASK;
407 cgh = search_suitable_cgh (entry, entry->cgh_qhead);
408 GNUNET_assert (NULL != cgh);
410 if (NULL != cgh->next)
411 cgh2 = search_suitable_cgh (entry, cgh->next);
412 GNUNET_CONTAINER_DLL_remove (entry->cgh_qhead, entry->cgh_qtail, cgh);
413 cgh->notify_called = GNUNET_YES;
414 GNUNET_CONTAINER_DLL_insert_tail (entry->cgh_qhead, entry->cgh_qtail, cgh);
416 entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry);
417 cgh->cb (cgh->cb_cls, entry->core_handle,
418 entry->transport_handle_, entry->peer_identity);
422 * Function called to notify transport users that another
423 * peer connected to us.
426 * @param peer the peer that connected
427 * @param type the type of the handle this notification is for
430 peer_connect_notify_cb (void *cls,
431 const struct GNUNET_PeerIdentity *peer,
432 const enum CacheGetType type)
434 struct CacheEntry *entry = cls;
435 struct ConnectNotifyContext *ctxt;
436 GST_cache_peer_connect_notify cb;
440 for (ctxt=entry->nctxt_qhead; NULL != ctxt; ctxt=ctxt->next)
442 GNUNET_assert (NULL != ctxt->cgh);
443 if (type != ctxt->cgh->type)
445 if (0 == memcmp (ctxt->target, peer, sizeof (struct GNUNET_PeerIdentity)))
451 cb_cls = ctxt->cb_cls;
452 ctxt->cgh->nctxt = NULL;
453 GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, ctxt);
460 * Function called to notify transport users that another
461 * peer connected to us.
464 * @param peer the peer that connected
465 * @param ats performance data
466 * @param ats_count number of entries in ats (excluding 0-termination)
469 transport_peer_connect_notify_cb (void *cls,
470 const struct GNUNET_PeerIdentity *peer,
471 const struct GNUNET_ATS_Information *ats,
474 peer_connect_notify_cb (cls, peer, CGT_TRANSPORT_HANDLE);
479 opstart_get_handle_transport (void *cls)
481 struct CacheEntry *entry = cls;
483 GNUNET_assert (NULL != entry);
484 LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->peer_id);
485 entry->transport_handle_ =
486 GNUNET_TRANSPORT_connect (entry->cfg,
489 &transport_peer_connect_notify_cb, NULL);
490 if (NULL == entry->transport_handle_)
495 //GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task);
496 if (0 == entry->demand)
498 if (GNUNET_NO == entry->cgh_qhead->notify_called)
499 entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry);
504 oprelease_get_handle_transport (void *cls)
506 struct CacheEntry *entry = cls;
508 if (NULL == entry->transport_handle_)
510 GNUNET_TRANSPORT_disconnect (entry->transport_handle_);
511 entry->transport_handle_ = NULL;
516 * Function called after GNUNET_CORE_connect has succeeded (or failed
517 * for good). Note that the private key of the peer is intentionally
518 * not exposed here; if you need it, your process should try to read
519 * the private key file directly (which should work if you are
520 * authorized...). Implementations of this function must not call
521 * GNUNET_CORE_disconnect (other than by scheduling a new task to
525 * @param server handle to the server, NULL if we failed
526 * @param my_identity ID of this peer, NULL if we failed
529 core_startup_cb (void *cls,
530 struct GNUNET_CORE_Handle * server,
531 const struct GNUNET_PeerIdentity *my_identity)
533 struct CacheEntry *entry = cls;
535 if (NULL == my_identity)
540 GNUNET_assert (NULL == entry->peer_identity);
541 entry->core_handle = server;
542 entry->peer_identity = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
543 memcpy (entry->peer_identity, my_identity,
544 sizeof (struct GNUNET_PeerIdentity));
545 if (0 == entry->demand)
547 if (GNUNET_NO == entry->cgh_qhead->notify_called)
548 entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry);
553 * Method called whenever a given peer connects.
556 * @param peer peer identity this notification is about
557 * @param atsi performance data for the connection
558 * @param atsi_count number of records in 'atsi'
561 core_peer_connect_cb (void *cls,
562 const struct GNUNET_PeerIdentity * peer,
563 const struct GNUNET_ATS_Information * atsi,
564 unsigned int atsi_count)
566 peer_connect_notify_cb (cls, peer, CGT_CORE_HANDLE);
571 opstart_get_handle_core (void *cls)
573 struct CacheEntry *entry = cls;
574 const struct GNUNET_CORE_MessageHandler no_handlers[] = {
578 GNUNET_assert (NULL != entry);
579 LOG_DEBUG ("Opening a CORE connection to peer %u\n", entry->peer_id);
580 /* void?: We also get the handle when the connection to CORE is successful */
581 (void) GNUNET_CORE_connect (entry->cfg,
584 &core_peer_connect_cb,
585 NULL, /* disconnect cb */
586 NULL, /* inbound notify */
588 NULL, /* outbound notify */
591 if (NULL == entry->core_handle)
596 //GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task);
601 oprelease_get_handle_core (void *cls)
603 struct CacheEntry *entry = cls;
605 if (NULL == entry->core_handle)
607 GNUNET_CORE_disconnect (entry->core_handle);
608 entry->core_handle = NULL;
609 GNUNET_free_non_null (entry->peer_identity);
610 entry->peer_identity = NULL;
614 static struct GSTCacheGetHandle *
615 cache_get_handle (unsigned int peer_id,
616 struct GSTCacheGetHandle *cgh,
617 const struct GNUNET_CONFIGURATION_Handle *cfg,
618 const struct GNUNET_PeerIdentity *target,
619 GST_cache_peer_connect_notify connect_notify_cb,
620 void *connect_notify_cb_cls)
622 struct GNUNET_HashCode key;
624 struct CacheEntry *entry;
625 struct ConnectNotifyContext *ctxt;
626 struct GNUNET_TESTBED_Operation *op;
628 GNUNET_assert (0 != cgh->type);
629 GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key);
634 case CGT_TRANSPORT_HANDLE:
635 entry = cache_lookup_handles (&key, (struct GNUNET_TRANSPORT_Handle **)
638 LOG_DEBUG ("Found TRANSPORT handle in cache for peer %u\n", entry->peer_id);
640 case CGT_CORE_HANDLE:
641 entry = cache_lookup_handles (&key, NULL,
642 (struct GNUNET_CORE_Handle **) &handle);
644 LOG_DEBUG ("Found CORE handle in cache for peer %u\n", entry->peer_id);
649 GNUNET_assert (NULL != entry);
650 if (0 == entry->demand)
651 GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry);
654 entry = add_entry (&key, peer_id);
655 if (NULL == entry->cfg)
656 entry->cfg = GNUNET_CONFIGURATION_dup (cfg);
659 GNUNET_CONTAINER_DLL_insert (entry->cgh_qhead, entry->cgh_qtail, cgh);
660 if ((NULL != target) && (NULL != connect_notify_cb))
662 ctxt = GNUNET_malloc (sizeof (struct ConnectNotifyContext));
663 ctxt->target = target;
664 ctxt->cb = connect_notify_cb;
665 ctxt->cb_cls = connect_notify_cb_cls;
666 GNUNET_assert (NULL == cgh->nctxt);
669 GNUNET_CONTAINER_DLL_insert_tail (entry->nctxt_qhead, entry->nctxt_qtail, ctxt);
673 if (GNUNET_SCHEDULER_NO_TASK == entry->notify_task)
674 entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry);
679 case CGT_TRANSPORT_HANDLE:
680 if (NULL != entry->transport_op_)
682 op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_transport,
683 &oprelease_get_handle_transport);
684 entry->transport_op_ = op;
686 case CGT_CORE_HANDLE:
687 if (NULL != entry->core_op)
689 op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_core,
690 &oprelease_get_handle_core);
694 GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, op);
695 GNUNET_TESTBED_operation_begin_wait_ (op);
700 * Iterator over hash map entries.
703 * @param key current key code
704 * @param value value in the hash map
705 * @return GNUNET_YES if we should continue to
710 cache_clear_iterator (void *cls,
711 const struct GNUNET_HashCode * key,
714 struct CacheEntry *entry = value;
715 static unsigned int ncleared;
717 GNUNET_assert (NULL != entry);
718 GNUNET_break (0 == entry->demand);
719 LOG_DEBUG ("Clearing entry %u of %u\n", ++ncleared, cache_size);
720 GNUNET_CONTAINER_multihashmap_remove (cache, key, value);
721 if (0 == entry->demand)
722 cache_remove (entry);
723 GNUNET_free_non_null (entry->hello);
724 GNUNET_break (NULL == entry->transport_handle_);
725 GNUNET_break (NULL == entry->transport_op_);
726 GNUNET_break (NULL == entry->core_handle);
727 GNUNET_break (NULL == entry->core_op);
728 GNUNET_break (NULL == entry->cfg);
729 GNUNET_assert (NULL == entry->cgh_qhead);
730 GNUNET_assert (NULL == entry->cgh_qtail);
731 GNUNET_assert (NULL == entry->nctxt_qhead);
732 GNUNET_assert (NULL == entry->nctxt_qtail);
744 GNUNET_CONTAINER_multihashmap_iterate (cache, &cache_clear_iterator, NULL);
745 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cache));
746 GNUNET_CONTAINER_multihashmap_destroy (cache);
751 * Initializes the cache
753 * @param size the size of the cache
756 GST_cache_init (unsigned int size)
760 lru_cache_threshold_size = size;
763 cache = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_YES);
768 * Mark the GetCacheHandle as being done if a handle has been provided already
769 * or as being cancelled if the callback for the handle hasn't been called.
771 * @param cgh the CacheGetHandle handle
774 GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh)
776 struct CacheEntry *entry;
779 GNUNET_assert (NULL != entry);
780 GNUNET_assert (0 < entry->demand);
782 if (GNUNET_SCHEDULER_NO_TASK != entry->notify_task)
784 GNUNET_SCHEDULER_cancel (entry->notify_task);
785 entry->notify_task = GNUNET_SCHEDULER_NO_TASK;
787 GNUNET_CONTAINER_DLL_remove (entry->cgh_qhead, entry->cgh_qtail, cgh);
788 if (NULL != cgh->nctxt)
790 GNUNET_assert (cgh == cgh->nctxt->cgh);
791 GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, cgh->nctxt);
792 GNUNET_free (cgh->nctxt);
795 if (0 == entry->demand)
797 GNUNET_CONTAINER_DLL_insert_tail (lru_cache_head, lru_cache_tail, entry);
798 if (lru_cache_size > lru_cache_threshold_size)
799 cache_remove (lru_cache_head);
803 if (GNUNET_NO == entry->cgh_qhead->notify_called)
804 entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry);
811 * Get a transport handle with the given configuration. If the handle is already
812 * cached before, it will be retured in the given callback; the peer_id is used to lookup in the
813 * cache. If not a new operation is started to open the transport handle and
814 * will be given in the callback when it is available.
816 * @param peer_id the index of the peer
817 * @param cfg the configuration with which the transport handle has to be
818 * created if it was not present in the cache
819 * @param cb the callback to notify when the transport handle is available
820 * @param cb_cls the closure for the above callback
821 * @param target the peer identify of the peer whose connection to our TRANSPORT
822 * subsystem will be notified through the connect_notify_cb. Can be NULL
823 * @param connect_notify_cb the callback to call when the given target peer is
824 * connected. This callback will only be called once or never again (in
825 * case the target peer cannot be connected). Can be NULL
826 * @param connect_notify_cb_cls the closure for the above callback
827 * @return the handle which can be used cancel or mark that the handle is no
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,
835 const struct GNUNET_PeerIdentity *target,
836 GST_cache_peer_connect_notify connect_notify_cb,
837 void *connect_notify_cb_cls)
839 struct GSTCacheGetHandle *cgh;
841 cgh = GNUNET_malloc (sizeof (struct GSTCacheGetHandle));
843 cgh->cb_cls = cb_cls;
844 cgh->type = CGT_TRANSPORT_HANDLE;
845 return cache_get_handle (peer_id, cgh, cfg,
846 target, connect_notify_cb, connect_notify_cb_cls);
851 * Get a CORE handle with the given configuration. If the handle is already
852 * cached before, it will be retured in the given callback; the peer_id is used
853 * to lookup in the cache. If the handle is not cached before, a new operation
854 * is started to open the CORE handle and will be given in the callback when it
855 * is available along with the peer identity
857 * @param peer_id the index of the peer
858 * @param cfg the configuration with which the transport handle has to be
859 * created if it was not present in the cache
860 * @param cb the callback to notify when the transport handle is available
861 * @param cb_cls the closure for the above callback
862 * @param target the peer identify of the peer whose connection to our CORE
863 * subsystem will be notified through the connect_notify_cb. Can be NULL
864 * @param connect_notify_cb the callback to call when the given target peer is
865 * connected. This callback will only be called once or never again (in
866 * case the target peer cannot be connected). Can be NULL
867 * @param connect_notify_cb_cls the closure for the above callback
868 * @return the handle which can be used cancel or mark that the handle is no
871 struct GSTCacheGetHandle *
872 GST_cache_get_handle_core (unsigned int peer_id,
873 const struct GNUNET_CONFIGURATION_Handle *cfg,
874 GST_cache_callback cb,
876 const struct GNUNET_PeerIdentity *target,
877 GST_cache_peer_connect_notify connect_notify_cb,
878 void *connect_notify_cb_cls)
880 struct GSTCacheGetHandle *cgh;
882 cgh = GNUNET_malloc (sizeof (struct GSTCacheGetHandle));
884 cgh->cb_cls = cb_cls;
885 cgh->type = CGT_CORE_HANDLE;
886 return cache_get_handle (peer_id, cgh, cfg,
887 target, connect_notify_cb, connect_notify_cb_cls);
892 * Looks up in the hello cache and returns the HELLO of the given peer
894 * @param peer_id the index of the peer whose HELLO has to be looked up
895 * @return the HELLO message; NULL if not found
897 const struct GNUNET_MessageHeader *
898 GST_cache_lookup_hello (const unsigned int peer_id)
900 struct CacheEntry *entry;
901 struct GNUNET_HashCode key;
903 LOG_DEBUG ("Looking up HELLO for peer %u\n", peer_id);
904 GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key);
905 entry = cache_lookup (&key);
908 if (NULL != entry->hello)
909 LOG_DEBUG ("HELLO found for peer %u\n", peer_id);
915 * Caches the HELLO of the given peer. Updates the HELLO if it was already
918 * @param id the peer identity of the peer whose HELLO has to be cached
919 * @param hello the HELLO message
922 GST_cache_add_hello (const unsigned int peer_id,
923 const struct GNUNET_MessageHeader *hello)
925 struct CacheEntry *entry;
926 struct GNUNET_HashCode key;
928 GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key);
929 entry = GNUNET_CONTAINER_multihashmap_get (cache, &key);
931 entry = add_entry (&key, peer_id);
932 GNUNET_free_non_null (entry->hello);
933 entry->hello = GNUNET_copy_message (hello);
936 /* end of gnunet-service-testbed_hc.c */