[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r25931 - gnunet/src/testbed
From: |
gnunet |
Subject: |
[GNUnet-SVN] r25931 - gnunet/src/testbed |
Date: |
Tue, 29 Jan 2013 13:25:09 +0100 |
Author: harsha
Date: 2013-01-29 13:25:09 +0100 (Tue, 29 Jan 2013)
New Revision: 25931
Modified:
gnunet/src/testbed/gnunet-service-testbed.h
gnunet/src/testbed/gnunet-service-testbed_hc.c
gnunet/src/testbed/gnunet-service-testbed_oc.c
Log:
- towards caching transport handles along with HELLO messages
Modified: gnunet/src/testbed/gnunet-service-testbed.h
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed.h 2013-01-28 23:05:08 UTC (rev
25930)
+++ gnunet/src/testbed/gnunet-service-testbed.h 2013-01-29 12:25:09 UTC (rev
25931)
@@ -647,43 +647,6 @@
/**
- * Looks up in the hello cache and returns the HELLO of the given peer
- *
- * @param id the peer identity of the peer whose HELLO has to be looked up
- * @return the HELLO message; NULL if not found
- */
-const struct GNUNET_MessageHeader *
-GST_cache_lookup (const struct GNUNET_PeerIdentity *id);
-
-/**
- * Caches the HELLO of the given peer. Updates the HELLO if it was already
- * cached before
- *
- * @param id the peer identity of the peer whose HELLO has to be cached
- * @param hello the HELLO message
- */
-void
-GST_cache_add (const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_MessageHeader *hello);
-
-
-/**
- * Initializes the cache
- *
- * @param size the size of the cache
- */
-void
-GST_cache_init (unsigned int size);
-
-
-/**
- * Clear cache
- */
-void
-GST_cache_clear ();
-
-
-/**
* Finds the route with directly connected host as destination through which
* the destination host can be reached
*
@@ -801,5 +764,83 @@
GST_free_roccq ();
+/**
+ * Initializes the cache
+ *
+ * @param size the size of the cache
+ */
+void
+GST_cache_init (unsigned int size);
+
+/**
+ * Clear cache
+ */
+void
+GST_cache_clear ();
+
+
+/**
+ * Looks up in the hello cache and returns the HELLO of the given peer
+ *
+ * @param peer_id the index of the peer whose HELLO has to be looked up
+ * @return the HELLO message; NULL if not found
+ */
+const struct GNUNET_MessageHeader *
+GST_cache_lookup_hello (const unsigned int peer_id);
+
+
+/**
+ * Caches the HELLO of the given peer. Updates the HELLO if it was already
+ * cached before
+ *
+ * @param id the peer identity of the peer whose HELLO has to be cached
+ * @param hello the HELLO message
+ */
+void
+GST_cache_add_hello (const unsigned int peer_id,
+ const struct GNUNET_MessageHeader *hello);
+
+
+/**
+ * Callback from cache with needed handles set
+ *
+ * @param cls the closure passed to GST_cache_get_handle_transport()
+ * @param ch the handle to CORE. Can be NULL if it is not requested
+ * @param th the handle to TRANSPORT. Can be NULL if it is not requested
+ */
+typedef void (*GST_cache_callback) (void *cls, struct GNUNET_CORE_Handle *ch,
+ struct GNUNET_TRANSPORT_Handle *th);
+
+
+/**
+ * Get a transport handle with the given configuration. If the handle is
already
+ * cached before, it will be retured in the given callback; the peer_id is
used to lookup in the
+ * cache. If not a new operation is started to open the transport handle and
+ * will be given in the callback when it is available.
+ *
+ * @param peer_id the index of the peer
+ * @param cfg the configuration with which the transport handle has to be
+ * created if it was not present in the cache
+ * @param cb the callback to notify when the transport handle is available
+ * @param cb_cls the closure for the above callback
+ * @return the handle which can be used cancel or mark that the handle is no
+ * longer being used
+ */
+struct GSTCacheGetHandle *
+GST_cache_get_handle_transport (unsigned int peer_id,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ GST_cache_callback cb,
+ void *cb_cls);
+
+
+/**
+ * Mark the GetCacheHandle as being done if a handle has been provided already
+ * or as being cancelled if the callback for the handle hasn't been called.
+ *
+ * @param cgh the CacheGetHandle handle
+ */
+void
+GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh);
+
/* End of gnunet-service-testbed.h */
Modified: gnunet/src/testbed/gnunet-service-testbed_hc.c
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed_hc.c 2013-01-28 23:05:08 UTC
(rev 25930)
+++ gnunet/src/testbed/gnunet-service-testbed_hc.c 2013-01-29 12:25:09 UTC
(rev 25931)
@@ -26,6 +26,47 @@
#include "gnunet-service-testbed.h"
+
+#ifdef LOG
+#undef LOG
+#endif
+
+#define LOG(kind,...) \
+ GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__)
+
+/* #define LOG_DEBUG(...) \ */
+/* LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) */
+
+
+enum CacheGetType
+{
+ CGT_TRANSPORT_HANDLE = 1
+};
+
+
+struct GSTCacheGetHandle
+{
+ struct GNUNET_TESTBED_Operation *op;
+
+ struct CacheEntry *entry;
+
+ struct GNUNET_CORE_Handle *ch;
+
+ struct GNUNET_TRANSPORT_Handle *th;
+
+ void *handle;
+
+ GST_cache_callback cb;
+
+ void *cb_cls;
+
+ GNUNET_SCHEDULER_TaskIdentifier notify_task;
+
+ enum CacheGetType type;
+
+ int notify_called;
+};
+
/**
* Cache entry
*/
@@ -42,6 +83,29 @@
struct CacheEntry *prev;
/**
+ * The transport handle to the peer corresponding to this entry; can be NULL
+ */
+ struct GNUNET_TRANSPORT_Handle *transport_handle;
+
+ /**
+ * The operation handle for transport handle
+ */
+ struct GNUNET_TESTBED_Operation *transport_op;
+
+ /**
+ * The configuration of the peer. Should be not NULL as long as the
core_handle
+ * or transport_handle are valid
+ */
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * The cache get handle which created this entry. Will be NULL after the
+ * operation for creating a core or transport handler is started, i.e. in the
+ * function opstart_get_handle_transport
+ */
+ struct GSTCacheGetHandle *cgh;
+
+ /**
* The key for this entry
*/
struct GNUNET_HashCode key;
@@ -50,6 +114,11 @@
* The HELLO message
*/
struct GNUNET_MessageHeader *hello;
+
+ /**
+ * Number of operations this cache entry is being used
+ */
+ unsigned int demand;
};
/**
@@ -59,102 +128,250 @@
/**
* DLL head for least recently used cache entries; least recently used
- * cache items are at the head
+ * cache items are at the head. The cache enties are added to this queue when
+ * their demand becomes zero. They are removed from the queue when they are
+ * needed by any operation.
*/
-static struct CacheEntry *lru_hcache_head;
+static struct CacheEntry *lru_cache_head;
/**
* DLL tail for least recently used cache entries; recently used cache
- * items are at the tail
+ * items are at the tail.The cache enties are added to this queue when
+ * their demand becomes zero. They are removed from the queue when they are
+ * needed by any operation.
*/
-static struct CacheEntry *lru_hcache_tail;
+static struct CacheEntry *lru_cache_tail;
/**
- * The size of cache
+ * the size of the LRU queue
*/
-static unsigned int cache_size;
+static unsigned int lru_cache_size;
+/**
+ * the threshold size for the LRU queue
+ */
+static unsigned int lru_cache_threshold_size;
+
/**
- * Looks up in the cache and returns the HELLO of the given peer
+ * Looks up in the cache and returns the entry
*
- * @param id the peer identity of the peer whose HELLO has to be looked up
+ * @param id the peer identity of the peer whose corresponding entry has to be
looked up
* @return the HELLO message; NULL if not found
*/
-const struct GNUNET_MessageHeader *
-GST_cache_lookup (const struct GNUNET_PeerIdentity *id)
+static struct CacheEntry *
+cache_lookup (const struct GNUNET_HashCode *key)
{
struct CacheEntry *entry;
if (NULL == cache)
return NULL;
- entry = GNUNET_CONTAINER_multihashmap_get (cache, &id->hashPubKey);
+ entry = GNUNET_CONTAINER_multihashmap_get (cache, key);
+ return entry;
+}
+
+
+static struct CacheEntry *
+cache_lookup_handles (const struct GNUNET_HashCode *pid,
+ struct GNUNET_TRANSPORT_Handle **th)
+{
+ struct CacheEntry *entry;
+
+ GNUNET_assert ((NULL != th));
+ entry = cache_lookup (pid);
if (NULL == entry)
return NULL;
- GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry);
- GNUNET_CONTAINER_DLL_insert_tail (lru_hcache_head, lru_hcache_tail, entry);
- return entry->hello;
+ if (0 == entry->demand)
+ GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry);
+ if ((NULL != th) && (NULL != entry->transport_handle))
+ *th = entry->transport_handle;
+ return entry;
}
-/**
- * Removes the given cache entry from cache and frees its resources
- *
- * @param entry the entry to remove
- */
static void
-GST_cache_remove (struct CacheEntry *entry)
+cache_remove (struct CacheEntry *entry)
{
- GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry);
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (cache, &entry->key,
- entry));
- GNUNET_free (entry->hello);
- GNUNET_free (entry);
+ /* We keep the entry in the hash table so that the HELLO can still be found
+ in cache; we will however disconnect the core and transport handles */
+ GNUNET_assert (0 == entry->demand);
+ GNUNET_assert (NULL != entry->cfg);
+ GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry);
+ if (NULL != entry->transport_handle)
+ {
+ GNUNET_assert (NULL != entry->transport_op);
+ GNUNET_TESTBED_operation_done (entry->transport_op);
+ entry->transport_op = NULL;
+ }
+ GNUNET_CONFIGURATION_destroy (entry->cfg);
+ entry->cfg = NULL;
}
-/**
- * Caches the HELLO of the given peer. Updates the HELLO if it was already
- * cached before
- *
- * @param id the peer identity of the peer whose HELLO has to be cached
- * @param hello the HELLO message
- */
-void
-GST_cache_add (const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_MessageHeader *hello)
+static struct CacheEntry *
+add_entry (const struct GNUNET_HashCode *key)
{
struct CacheEntry *entry;
- if (NULL == cache)
+ entry = GNUNET_malloc (sizeof (struct CacheEntry));
+ memcpy (&entry->key, key, sizeof (struct GNUNET_HashCode));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (cache, &entry->key,
+ entry,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+ return entry;
+}
+
+
+static void
+cache_notify_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext
*tc)
+{
+ struct GSTCacheGetHandle *cgh = cls;
+
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != cgh->notify_task);
+ cgh->notify_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_assert (NULL != cgh->entry);
+ cgh->entry->demand++;
+ cgh->notify_called = GNUNET_YES;
+ switch (cgh->type)
+ {
+ case CGT_TRANSPORT_HANDLE:
+ cgh->cb (cgh->cb_cls, NULL, cgh->handle);
+ break;
+ }
+}
+
+
+static void
+opstart_get_handle_transport (void *cls)
+{
+ struct CacheEntry *entry = cls;
+ struct GSTCacheGetHandle *cgh = entry->cgh;
+
+ GNUNET_assert (NULL != entry);
+ GNUNET_assert (NULL != cgh);
+ GNUNET_assert (NULL != entry->cfg);
+ LOG_DEBUG ("Opening a transport connection\n");
+ entry->cgh = NULL;
+ entry->transport_handle = GNUNET_TRANSPORT_connect (entry->cfg,
+ NULL, NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (NULL == entry->transport_handle)
+ {
+ GNUNET_break (0);
return;
- entry = GNUNET_CONTAINER_multihashmap_get (cache, &id->hashPubKey);
- if (NULL == entry)
+ }
+ cgh->handle = entry->transport_handle;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == cgh->notify_task);
+ cgh->notify_task = GNUNET_SCHEDULER_add_now (&cache_notify_callback, cgh);
+}
+
+
+static void
+oprelease_get_handle_transport (void *cls)
+{
+ struct CacheEntry *entry = cls;
+
+ if (NULL == entry->transport_handle)
+ return;
+ GNUNET_TRANSPORT_disconnect (entry->transport_handle);
+ entry->transport_handle = NULL;
+}
+
+
+static struct GSTCacheGetHandle *
+cache_get_handle (unsigned int peer_id,
+ struct GSTCacheGetHandle *cgh,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_HashCode key;
+ struct GNUNET_CORE_Handle *ch;
+ void *handle;
+ struct CacheEntry *entry;
+
+ GNUNET_assert (0 != cgh->type);
+ GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key);
+ ch = NULL;
+ handle = NULL;
+ entry = NULL;
+ switch (cgh->type)
{
- entry = GNUNET_malloc (sizeof (struct CacheEntry));
- memcpy (&entry->key, &id->hashPubKey, sizeof (struct GNUNET_HashCode));
- if (GNUNET_CONTAINER_multihashmap_size (cache) == cache_size)
- {
- GNUNET_assert (NULL != lru_hcache_head);
- GST_cache_remove (lru_hcache_head);
- }
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (cache, &entry->key,
- entry,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+ case CGT_TRANSPORT_HANDLE:
+ entry = cache_lookup_handles (&key, (struct GNUNET_TRANSPORT_Handle **)
&handle);
+ break;
}
- else
+ if (NULL != handle)
{
- GNUNET_CONTAINER_DLL_remove (lru_hcache_head, lru_hcache_tail, entry);
- GNUNET_free (entry->hello);
+ GNUNET_assert (NULL != entry);
+ LOG_DEBUG ("Found existing transport handle in cache\n");
+ cgh->entry = entry;
+ cgh->ch = ch;
+ cgh->handle = handle;
+ cgh->notify_task = GNUNET_SCHEDULER_add_now (&cache_notify_callback, cgh);
+ return cgh;
}
- entry->hello = GNUNET_copy_message (hello);
- GNUNET_CONTAINER_DLL_insert_tail (lru_hcache_head, lru_hcache_tail, entry);
+ if (NULL == entry)
+ entry = add_entry (&key);
+ if (NULL == entry->cfg)
+ entry->cfg = GNUNET_CONFIGURATION_dup (cfg);
+ cgh->entry = entry;
+ entry->cgh = cgh;
+ switch (cgh->type)
+ {
+ case CGT_TRANSPORT_HANDLE:
+ GNUNET_assert (NULL == entry->transport_op);
+ LOG_DEBUG ("Creating an operation for opening transport handle");
+ entry->transport_op = GNUNET_TESTBED_operation_create_ (entry,
&opstart_get_handle_transport,
+
&oprelease_get_handle_transport);
+ GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds,
+ entry->transport_op);
+ GNUNET_TESTBED_operation_begin_wait_ (entry->transport_op);
+ break;
+ }
+ return cgh;
}
+/**
+ * Iterator over hash map entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to
+ * iterate,
+ * GNUNET_NO if not.
+ */
+static int
+cache_clear_iterator (void *cls,
+ const struct GNUNET_HashCode * key,
+ void *value)
+{
+ struct CacheEntry *entry = value;
+ GNUNET_assert (NULL != entry);
+ GNUNET_CONTAINER_multihashmap_remove (cache, key, value);
+ GNUNET_free_non_null (entry->hello);
+ GNUNET_break (NULL == entry->transport_handle);
+ GNUNET_free (entry);
+ return GNUNET_YES;
+}
+
+
/**
+ * Clear cache
+ */
+void
+GST_cache_clear ()
+{
+ GNUNET_CONTAINER_multihashmap_iterate (cache, &cache_clear_iterator, NULL);
+ GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cache));
+ GNUNET_CONTAINER_multihashmap_destroy (cache);
+}
+
+
+/**
* Initializes the cache
*
* @param size the size of the cache
@@ -164,7 +381,7 @@
{
if (0 == size)
return;
- cache_size = size;
+ lru_cache_threshold_size = size;
if (size > 1)
size = size / 2;
cache = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_YES);
@@ -172,21 +389,100 @@
/**
- * Clear cache
+ * Mark the GetCacheHandle as being done if a handle has been provided already
+ * or as being cancelled if the callback for the handle hasn't been called.
+ *
+ * @param cgh the CacheGetHandle handle
*/
void
-GST_cache_clear ()
+GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh)
{
- if (NULL != cache)
- GNUNET_assert (GNUNET_CONTAINER_multihashmap_size (cache) <=
- cache_size);
- while (NULL != lru_hcache_head)
- GST_cache_remove (lru_hcache_head);
- if (NULL != cache)
+ if (GNUNET_SCHEDULER_NO_TASK != cgh->notify_task)
+ GNUNET_SCHEDULER_cancel (cgh->notify_task);
+ if (GNUNET_YES == cgh->notify_called)
{
- GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cache));
- GNUNET_CONTAINER_multihashmap_destroy (cache);
+ cgh->entry->demand--;
+ if (0 == cgh->entry->demand)
+ {
+ GNUNET_CONTAINER_DLL_insert_tail (lru_cache_head, lru_cache_tail,
cgh->entry);
+ if (lru_cache_size > lru_cache_threshold_size)
+ cache_remove (lru_cache_head);
+ }
}
+ GNUNET_free (cgh);
}
+
+/**
+ * Get a transport handle with the given configuration. If the handle is
already
+ * cached before, it will be retured in the given callback; the peer_id is
used to lookup in the
+ * cache. If not a new operation is started to open the transport handle and
+ * will be given in the callback when it is available.
+ *
+ * @param peer_id the index of the peer
+ * @param cfg the configuration with which the transport handle has to be
+ * created if it was not present in the cache
+ * @param cb the callback to notify when the transport handle is available
+ * @param cb_cls the closure for the above callback
+ * @return the handle which can be used cancel or mark that the handle is no
+ * longer being used
+ */
+struct GSTCacheGetHandle *
+GST_cache_get_handle_transport (unsigned int peer_id,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ GST_cache_callback cb,
+ void *cb_cls)
+{
+ struct GSTCacheGetHandle *cgh;
+
+ cgh = GNUNET_malloc (sizeof (struct GSTCacheGetHandle));
+ cgh->cb = cb;
+ cgh->cb_cls = cb_cls;
+ cgh->type = CGT_TRANSPORT_HANDLE;
+ return cache_get_handle (peer_id, cgh, cfg);
+}
+
+
+/**
+ * Looks up in the hello cache and returns the HELLO of the given peer
+ *
+ * @param peer_id the index of the peer whose HELLO has to be looked up
+ * @return the HELLO message; NULL if not found
+ */
+const struct GNUNET_MessageHeader *
+GST_cache_lookup_hello (const unsigned int peer_id)
+{
+ struct CacheEntry *entry;
+ struct GNUNET_HashCode key;
+
+ GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key);
+ entry = cache_lookup (&key);
+ if (NULL == entry)
+ return NULL;
+ return entry->hello;
+}
+
+
+/**
+ * Caches the HELLO of the given peer. Updates the HELLO if it was already
+ * cached before
+ *
+ * @param id the peer identity of the peer whose HELLO has to be cached
+ * @param hello the HELLO message
+ */
+void
+GST_cache_add_hello (const unsigned int peer_id,
+ const struct GNUNET_MessageHeader *hello)
+{
+ struct CacheEntry *entry;
+ struct GNUNET_HashCode key;
+
+ GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key);
+ entry = GNUNET_CONTAINER_multihashmap_get (cache, &key);
+ if (NULL == entry)
+ entry = add_entry (&key);
+ GNUNET_free_non_null (entry->hello);
+ entry->hello = GNUNET_copy_message (hello);
+}
+
/* end of gnunet-service-testbed_hc.c */
Modified: gnunet/src/testbed/gnunet-service-testbed_oc.c
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed_oc.c 2013-01-28 23:05:08 UTC
(rev 25930)
+++ gnunet/src/testbed/gnunet-service-testbed_oc.c 2013-01-29 12:25:09 UTC
(rev 25931)
@@ -792,7 +792,7 @@
LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
GNUNET_i2s (&occ->peer_identity));
occ->hello = GNUNET_malloc (msize);
- GST_cache_add (&occ->peer_identity, hello);
+ GST_cache_add_hello (occ->peer_id, hello);
memcpy (occ->hello, hello, msize);
GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
occ->ghh = NULL;
@@ -837,7 +837,7 @@
LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
GNUNET_i2s (&occ->peer_identity));
/* Lookup for HELLO in hello cache */
- if (NULL != (hello = GST_cache_lookup (&occ->peer_identity)))
+ if (NULL != (hello = GST_cache_lookup_hello (occ->peer_id)))
{
LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
GNUNET_i2s (&occ->peer_identity));
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r25931 - gnunet/src/testbed,
gnunet <=