From 86d7f49fc64f0c766d4bec6b3f34879f108fc8a9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 7 Feb 2011 22:44:36 +0000 Subject: [PATCH] stuff --- src/fs/gnunet-service-fs_cp.c | 15 +++ src/fs/gnunet-service-fs_cp.h | 11 ++ src/fs/gnunet-service-fs_pe.c | 191 +++++++++++++++++++++++++++++++--- src/fs/gnunet-service-fs_pe.h | 27 +++-- 4 files changed, 225 insertions(+), 19 deletions(-) diff --git a/src/fs/gnunet-service-fs_cp.c b/src/fs/gnunet-service-fs_cp.c index 4c7c1b52d..0bacb3ec3 100644 --- a/src/fs/gnunet-service-fs_cp.c +++ b/src/fs/gnunet-service-fs_cp.c @@ -777,6 +777,21 @@ GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it, } +/** + * Obtain the identity of a connected peer. + * + * @param cp peer to reserve bandwidth from + * @param id identity to set (written to) + */ +void +GSF_connected_peer_get_identity_ (const struct GSF_ConnectedPeer *cp, + struct GNUNET_PeerIdentity *id) +{ + GNUNET_PEER_resolve (cp->pid, + &id); +} + + /** * Write host-trust information to a file - flush the buffer entry! * diff --git a/src/fs/gnunet-service-fs_cp.h b/src/fs/gnunet-service-fs_cp.h index 8b11dcd5d..4ad27afd8 100644 --- a/src/fs/gnunet-service-fs_cp.h +++ b/src/fs/gnunet-service-fs_cp.h @@ -284,6 +284,17 @@ GSF_connected_peer_change_preference_ (struct GSF_ConnectedPeer *cp, uint64_t pref); +/** + * Obtain the identity of a connected peer. + * + * @param cp peer to reserve bandwidth from + * @param id identity to set (written to) + */ +void +GSF_connected_peer_get_identity_ (const struct GSF_ConnectedPeer *cp, + struct GNUNET_PeerIdentity *id); + + /** * Iterate over all connected peers. * diff --git a/src/fs/gnunet-service-fs_pe.c b/src/fs/gnunet-service-fs_pe.c index ec6f315ff..6797a13fb 100644 --- a/src/fs/gnunet-service-fs_pe.c +++ b/src/fs/gnunet-service-fs_pe.c @@ -24,8 +24,33 @@ * @author Christian Grothoff */ #include "platform.h" +#include "gnunet-service-fs_cp.h" #include "gnunet-service-fs_pe.h" +/** + * Hash map from peer identities to GNUNET_CONTAINER_Heap's with + * pending requests as entries. + */ +static struct GNUNET_CONTAINER_MultiHashMap *plans; + + +/** + * Get the size of the request queue for the given peer. + * + * @param cp connected peer to query + * @return number of entries in this peer's request queue + */ +static struct GNUNET_CONTAINER_Heap * +get_heap (const struct GSF_ConnectedPeer *cp) +{ + struct GNUNET_CONTAINER_Heap *h; + struct GNUNET_PeerIdentity id; + + GSF_connected_peer_get_identity_ (cp, &id); + return GNUNET_CONTAINER_multihashmap_get (plans, + &id.hashPubKey); +} + /** * Create a new query plan entry. @@ -36,11 +61,28 @@ * lower weights are earlier in the queue */ void -GSF_plan_add_ (struct GSF_ConnectedPeer *cp, +GSF_plan_add_ (const struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr, - double weight) + GNUNET_CONTAINER_HeapCostType weight) { - // FIXME + struct GNUNET_PeerIdentity id; + struct GNUNET_CONTAINER_Heap *h; + struct GSF_PendingRequest *pr; + + GSF_connected_peer_get_identity_ (cp, &id); + h = GNUNET_CONTAINER_multihashmap_get (plans, + &id.hashPubKey); + if (NULL == h) + { + h = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); + GNUNET_CONTAINER_multihashmap_put (plans, + &id.hashPubKey, + h, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + } + GNUNET_CONTAINER_heap_insert (h, + pr, + weight); } @@ -51,22 +93,111 @@ GSF_plan_add_ (struct GSF_ConnectedPeer *cp, * @param cp connected peer */ void -GSF_plan_notify_peer_disconnect_ (struct GSF_ConnectedPeer *cp) +GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp) { - // FIXME + struct GNUNET_PeerIdentity id; + struct GNUNET_CONTAINER_Heap *h; + struct GSF_PendingRequest *pr; + + GSF_connected_peer_get_identity_ (cp, &id); + h = GNUNET_CONTAINER_multihashmap_get (plans, + &id.hashPubKey); + GNUNET_CONTAINER_multihashmap_remove (plans, + &id.hashPubKey, + h); + GNUNET_CONTAINER_heap_destroy (h); } /** - * Notify the plan about a request being done; - * destroy all entries associated with this request. + * Closure for 'find_request'. + */ +struct FindRequestClosure +{ + /** + * Place to store the node that was found (NULL for none). + */ + struct GNUNET_CONTAINER_HeapNode *node; + + /** + * Value we're looking for + */ + const struct GSF_PendingRequest *pr; +}; + + +/** + * Find a heap node where the value matches the + * pending request given in the closure. + * + * @param cls the 'struct FindRequestClosure' + * @param node heap structure we're looking for on a match + * @param element the pending request stored in the heap + * @param cost weight of the request + * @return GNUNET_YES to continue looking + */ +static int +find_request (void *cls, + struct GNUNET_CONTAINER_HeapNode *node, + void *element, + GNUNET_CONTAINER_HeapCostType cost) +{ + struct FindRequestClosure *frc = cls; + struct GSF_PendingRequest *pr = element; + + if (pr == frc->pr) + { + frc->node = node; + return GNUNET_NO; + } + return GNUNET_YES; +} + + +/** + * Remove the given request from all heaps. * + * + * @param cls 'struct GSF_PendingRequest' to purge + * @param key identity of the peer we're currently looking at (unused) + * @param value request heap for the given peer to search for the 'cls' + * @return GNUNET_OK (continue iteration) + */ +static int +remove_request (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + const struct GSF_PendingRequest *pr = cls; + struct GNUNET_CONTAINER_Heap *h = value; + struct FindRequestClosure frc; + + frc.pr = pr; + do + { + frc.node = NULL; + GNUNET_CONTAINER_heap_iterate (h, &find_request, &frc); + if (frc.node != NULL) + GNUNET_CONTAINER_heap_remove_node (h, frc.node); + } + while (NULL != frc.node); + return GNUNET_OK; +} + + +/** + * Notify the plan about a request being done; destroy all entries + * associated with this request. Note that this implementation is + * currently terribly inefficient (O(n)) and could instead be done in + * O(1). But for now, I first want to see it work correctly... * * @param pr request that is done */ void -GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr) +GSF_plan_notify_request_done_ (const struct GSF_PendingRequest *pr) { - // FIXME + GNUNET_CONTAINER_multihashmap_iterate (plans, + &remove_request, + (void*) pr); } @@ -78,9 +209,15 @@ GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr) * @return NULL if the queue for this peer is empty */ struct GSF_PendingRequest * -GSF_plan_get_ (struct GSF_ConnectedPeer *cp) +GSF_plan_get_ (const struct GSF_ConnectedPeer *cp) { - return NULL; // FIXME + struct GNUNET_CONTAINER_Heap *h; + struct GSF_PendingRequest *pr; + + h = get_heap (cp); + if (NULL == h) + return NULL; + return GNUNET_CONTAINER_heap_remove_root (h); } @@ -91,9 +228,37 @@ GSF_plan_get_ (struct GSF_ConnectedPeer *cp) * @return number of entries in this peer's request queue */ unsigned int -GSF_plan_size_ (struct GSF_ConnectedPeer *cp) +GSF_plan_size_ (const struct GSF_ConnectedPeer *cp) +{ + struct GNUNET_CONTAINER_Heap *h; + + h = get_heap (cp); + if (NULL == h) + return 0; + return GNUNET_CONTAINER_heap_get_size (h); +} + + + +/** + * Initialize plan subsystem. + */ +void +GSF_plan_init () +{ + plans = GNUNET_CONTAINER_multihashmap_create (256); +} + + +/** + * Shutdown plan subsystem. + */ +void +GSF_plan_done () { - return 0; // FIXME + GNUNET_assert (0 == + GNUNET_CONTAINER_multihashmap_get_size (plans)); + GNUNET_CONTAINER_multihashmap_destroy (plans); } diff --git a/src/fs/gnunet-service-fs_pe.h b/src/fs/gnunet-service-fs_pe.h index 09baebc1a..d70001356 100644 --- a/src/fs/gnunet-service-fs_pe.h +++ b/src/fs/gnunet-service-fs_pe.h @@ -38,9 +38,9 @@ * lower weights are earlier in the queue */ void -GSF_plan_add_ (struct GSF_ConnectedPeer *cp, +GSF_plan_add_ (const struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr, - double weight); + GNUNET_CONTAINER_HeapCostType weight); /** @@ -50,7 +50,7 @@ GSF_plan_add_ (struct GSF_ConnectedPeer *cp, * @param cp connected peer */ void -GSF_plan_notify_peer_disconnect_ (struct GSF_ConnectedPeer *cp); +GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp); /** @@ -60,7 +60,7 @@ GSF_plan_notify_peer_disconnect_ (struct GSF_ConnectedPeer *cp); * @param pr request that is done */ void -GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr); +GSF_plan_notify_request_done_ (const struct GSF_PendingRequest *pr); /** @@ -71,7 +71,7 @@ GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr); * @return NULL if the queue for this peer is empty */ struct GSF_PendingRequest * -GSF_plan_get_ (struct GSF_ConnectedPeer *cp); +GSF_plan_get_ (const struct GSF_ConnectedPeer *cp); /** @@ -81,7 +81,22 @@ GSF_plan_get_ (struct GSF_ConnectedPeer *cp); * @return number of entries in this peer's request queue */ unsigned int -GSF_plan_size_ (struct GSF_ConnectedPeer *cp); +GSF_plan_size_ (const struct GSF_ConnectedPeer *cp); + + +/** + * Initialize plan subsystem. + */ +void +GSF_plan_init (void); + + +/** + * Shutdown plan subsystem. + */ +void +GSF_plan_done (void); + #endif /* end of gnunet-service-fs_pe.h */ -- 2.25.1