/**
* @file testbed/gnunet-service-testbed_connectionpool.c
* @brief connection pooling for connections to peers' services
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
*/
#include "gnunet-service-testbed.h"
* Did we call the pool_connection_ready_cb already?
*/
int connection_ready_called;
+
+ /**
+ * Are we waiting for any peer connect notifications?
+ */
+ int notify_waiting;
};
static unsigned int max_size;
+/**
+ * Cancel the expiration task of the give #PooledConnection object
+ *
+ * @param entry the #PooledConnection object
+ */
+static void
+expire_task_cancel (struct PooledConnection *entry);
+
+
/**
* Destroy a #PooledConnection object
*
GNUNET_assert ((NULL == entry->head_waiting) && (NULL ==
entry->tail_waiting));
GNUNET_assert (0 == entry->demand);
- GNUNET_free_non_null (entry->peer_identity);
+ expire_task_cancel (entry);
if (entry->in_lru)
GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry);
if (entry->in_pool)
- GNUNET_assert (GNUNET_OK ==
+ GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap32_remove (map,
entry->index,
entry));
+ if (GNUNET_SCHEDULER_NO_TASK != entry->notify_task)
+ {
+ GNUNET_SCHEDULER_cancel (entry->notify_task);
+ entry->notify_task = GNUNET_SCHEDULER_NO_TASK;
+ }
LOG_DEBUG ("Cleaning up handles of a pooled connection\n");
if (NULL != entry->handle_transport)
GNUNET_assert (NULL != entry->op_transport);
}
+/**
+ * Cancel the expiration task of the give #PooledConnection object
+ *
+ * @param entry the #PooledConnection object
+ */
static void
expire_task_cancel (struct PooledConnection *entry)
{
if (NULL != gh->next)
gh_next = search_waiting (entry, gh->next);
GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh);
- gh->connection_ready_called = GNUNET_YES;
+ gh->connection_ready_called = 1;
if (NULL != gh_next)
entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry);
if ( (NULL != gh->target) && (NULL != gh->connect_notify_cb) )
- GNUNET_CONTAINER_DLL_insert_tail (entry->head_notify, entry->tail_notify, gh);
- LOG_DEBUG ("Calling notify for handle type %u\n", gh->service);
+ {
+ GNUNET_CONTAINER_DLL_insert_tail (entry->head_notify, entry->tail_notify,
+ gh);
+ gh->notify_waiting = 1;
+ }
+ LOG_DEBUG ("Connection ready for handle type %u\n", gh->service);
gh->cb (gh->cb_cls, entry->handle_core, entry->handle_transport,
entry->peer_identity);
}
/**
* Function called from peer connect notify callbacks from CORE and TRANSPORT
- * connections. This function calls the pendning peer connect notify callbacks
+ * connections. This function calls the pending peer connect notify callbacks
* which are queued in an entry.
*
* @param cls the #PooledConnection object
cb_cls = gh->connect_notify_cb_cls;
gh_next = gh->next;
GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh);
+ gh->notify_waiting = 0;
+ LOG_DEBUG ("Peer connected to peer %u at service %u\n", entry->index, gh->service);
gh = gh_next;
cb (cb_cls, peer);
}
const struct GNUNET_PeerIdentity *peer)
{
struct PooledConnection *entry = cls;
-
+
peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_TRANSPORT);
}
core_peer_connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer)
{
struct PooledConnection *entry = cls;
-
+
peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_CORE);
}
* @param my_identity ID of this peer, NULL if we failed
*/
static void
-core_startup_cb (void *cls,
+core_startup_cb (void *cls,
const struct GNUNET_PeerIdentity *my_identity)
{
struct PooledConnection *entry = cls;
void *value)
{
struct PooledConnection *entry = value;
-
+
GNUNET_assert (NULL != entry);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap32_remove (map, key, entry));
- if (entry->in_lru)
- GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry);
destroy_pooled_connection (entry);
return GNUNET_YES;
}
GST_connection_pool_destroy ()
{
struct PooledConnection *entry;
-
+
if (NULL != map)
{
GNUNET_assert (GNUNET_SYSERR !=
GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry);
destroy_pooled_connection (entry);
}
+ GNUNET_assert (NULL == head_not_pooled);
}
*
* @note @a connect_notify_cb will not be called if @a target is
* already connected @a service level. Use
- * GNUNET_TRANSPORT_check_neighbour_connected() or a similar function from the
+ * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the
* respective @a service's API to check if the target peer is already connected or
* not. @a connect_notify_cb will be called only once or never (in case @a target
* cannot be connected or is already connected).
uint32_t peer_id32;
peer_id32 = (uint32_t) peer_id;
+ handle = NULL;
entry = NULL;
if (NULL != map)
entry = GNUNET_CONTAINER_multihashmap32_get (map, peer_id32);
{
entry = GNUNET_new (struct PooledConnection);
entry->index = peer_id32;
- if ((NULL != map)
+ if ((NULL != map)
&& (GNUNET_CONTAINER_multihashmap32_size (map) < max_size))
{
GNUNET_assert (GNUNET_OK ==
struct PooledConnection *entry;
entry = gh->entry;
+ LOG_DEBUG ("Cleaning up get handle %p for service %u, peer %u\n",
+ gh,
+ gh->service, entry->index);
if (!gh->connection_ready_called)
+ {
GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh);
- else if ((NULL != gh->next) || (NULL != gh->prev))
- GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->head_notify, gh);
+ if ( (NULL == search_waiting (entry, entry->head_waiting))
+ && (GNUNET_SCHEDULER_NO_TASK != entry->notify_task) )
+ {
+ GNUNET_SCHEDULER_cancel (entry->notify_task);
+ entry->notify_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ }
+ if (gh->notify_waiting)
+ {
+ GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh);
+ gh->notify_waiting = 0;
+ }
GNUNET_free (gh);
gh = NULL;
- GNUNET_assert (!entry->in_lru);
- if ( (!entry->in_pool) && (NULL != map) )
+ GNUNET_assert (!entry->in_lru);
+ if (!entry->in_pool)
+ GNUNET_CONTAINER_DLL_remove (head_not_pooled, tail_not_pooled, entry);
+ if (NULL != map)
{
if (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_contains (map,
entry->index))
goto unallocate;
- if ((GNUNET_CONTAINER_multihashmap32_size (map) == max_size)
- && (NULL == head_lru))
- goto unallocate;
- destroy_pooled_connection (head_lru);
- GNUNET_CONTAINER_DLL_remove (head_not_pooled, tail_not_pooled, entry);
+ if (GNUNET_CONTAINER_multihashmap32_size (map) == max_size)
+ {
+ if (NULL == head_lru)
+ goto unallocate;
+ destroy_pooled_connection (head_lru);
+ }
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap32_put (map,
- entry->index,
+ GNUNET_CONTAINER_multihashmap32_put (map,
+ entry->index,
entry,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
entry->in_pool = GNUNET_YES;
}
+
unallocate:
GNUNET_assert (0 < entry->demand);
entry->demand--;