/** * Shutdown routing subsystem. */ void GDS_ROUTING_done () { while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) expire_oldest_entry (); GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap)); GNUNET_CONTAINER_heap_destroy (recent_heap); recent_heap = NULL; GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map)); GNUNET_CONTAINER_multihashmap_destroy (recent_map); recent_map = NULL; }
/** * Figure out when and how to transmit to the given peer. * * @param cls the 'struct PeerPlan' * @param tc scheduler context */ static void schedule_peer_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerPlan *pp = cls; struct GSF_RequestPlan *rp; size_t msize; struct GNUNET_TIME_Relative delay; pp->task = GNUNET_SCHEDULER_NO_TASK; if (NULL != pp->pth) { GSF_peer_transmit_cancel_ (pp->pth); pp->pth = NULL; } /* move ready requests to priority queue */ while ((NULL != (rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap))) && (GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission).rel_value == 0)) { GNUNET_assert (rp == GNUNET_CONTAINER_heap_remove_root (pp->delay_heap)); rp->hn = GNUNET_CONTAINER_heap_insert (pp->priority_heap, rp, rp->priority); } if (0 == GNUNET_CONTAINER_heap_get_size (pp->priority_heap)) { /* priority heap (still) empty, check for delay... */ rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap); if (NULL == rp) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No active requests for plan %p.\n", pp); return; /* both queues empty */ } delay = GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sleeping for %llu ms before retrying requests on plan %p.\n", (unsigned long long) delay.rel_value, pp); GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# delay heap timeout"), delay.rel_value, GNUNET_NO); pp->task = GNUNET_SCHEDULER_add_delayed (delay, &schedule_peer_transmission, pp); return; } #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query plans executed"), 1, GNUNET_NO); #endif /* process from priority heap */ rp = GNUNET_CONTAINER_heap_peek (pp->priority_heap); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing query plan %p\n", rp); GNUNET_assert (NULL != rp); msize = GSF_pending_request_get_message_ (get_latest (rp), 0, NULL); pp->pth = GSF_peer_transmit_ (pp->cp, GNUNET_YES, rp->priority, GNUNET_TIME_UNIT_FOREVER_REL, msize, &transmit_message_callback, pp); GNUNET_assert (NULL != pp->pth); }
/** * Add a new entry to our routing table. * * @param sender peer that originated the request * @param type type of the block * @param options options for processing * @param key key for the content * @param xquery extended query * @param xquery_size number of bytes in xquery * @param reply_bf bloomfilter to filter duplicates * @param reply_bf_mutator mutator for reply_bf */ void GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender, enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode * key, const void *xquery, size_t xquery_size, const struct GNUNET_CONTAINER_BloomFilter *reply_bf, uint32_t reply_bf_mutator) { struct RecentRequest *recent_req; while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT) expire_oldest_entry (); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Entries added to routing table"), 1, GNUNET_NO); recent_req = GNUNET_malloc (sizeof (struct RecentRequest) + xquery_size); recent_req->peer = *sender; recent_req->key = *key; recent_req->reply_bf = GNUNET_CONTAINER_bloomfilter_copy (reply_bf); recent_req->type = type; recent_req->options = options; recent_req->xquery = &recent_req[1]; memcpy (&recent_req[1], xquery, xquery_size); recent_req->xquery_size = xquery_size; recent_req->reply_bf_mutator = reply_bf_mutator; if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &try_combine_recent, recent_req)) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# DHT requests combined"), 1, GNUNET_NO); return; } recent_req->heap_node = GNUNET_CONTAINER_heap_insert (recent_heap, recent_req, GNUNET_TIME_absolute_get ().abs_value); GNUNET_CONTAINER_multihashmap_put (recent_map, key, recent_req, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); }
/** * Shutdown client subsystem. */ void GDS_CLIENTS_done () { GNUNET_assert (client_head == NULL); GNUNET_assert (client_tail == NULL); if (GNUNET_SCHEDULER_NO_TASK != retry_task) { GNUNET_SCHEDULER_cancel (retry_task); retry_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != retry_heap) { GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (retry_heap)); GNUNET_CONTAINER_heap_destroy (retry_heap); retry_heap = NULL; } if (NULL != forward_map) { GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (forward_map)); GNUNET_CONTAINER_multihashmap_destroy (forward_map); forward_map = NULL; } }
static int check () { struct GNUNET_CONTAINER_Heap *myHeap; struct GNUNET_CONTAINER_HeapNode *n1; struct GNUNET_CONTAINER_HeapNode *n2; struct GNUNET_CONTAINER_HeapNode *n3; struct GNUNET_CONTAINER_HeapNode *n4; struct GNUNET_CONTAINER_HeapNode *n5; struct GNUNET_CONTAINER_HeapNode *n6; struct GNUNET_CONTAINER_HeapNode *n7; struct GNUNET_CONTAINER_HeapNode *n8; const char *r; myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); // GNUNET_CONTAINER_heap_remove_root heap empty, taking if-branch n1 = GNUNET_CONTAINER_heap_remove_root (myHeap); GNUNET_assert (NULL == n1); // GNUNET_CONTAINER_heap_peek heap empty, taking if-branch n1 = GNUNET_CONTAINER_heap_peek (myHeap); GNUNET_assert (NULL == n1); // GNUNET_CONTAINER_heap_walk_get_next: heap empty, taking if-branch n1 = GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (NULL == n1); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "11", 11); GNUNET_assert (NULL != n1); // GNUNET_CONTAINER_heap_peek not empty, taking if-branch n2 = NULL; n2 = GNUNET_CONTAINER_heap_peek (myHeap); GNUNET_assert (NULL != n2); // GNUNET_CONTAINER_heap_walk_get_next: 1 element n1 = NULL; n1 = GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (NULL != n1); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_assert (1 == GNUNET_CONTAINER_heap_get_size (myHeap)); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "78", 78); GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_assert (0 == strcmp ("78", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (1 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "15", 5); GNUNET_CONTAINER_heap_update_cost (myHeap, n3, 15); GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); n4 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); GNUNET_CONTAINER_heap_update_cost (myHeap, n4, 50); GNUNET_assert (3 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); n5 = GNUNET_CONTAINER_heap_insert (myHeap, "100", 100); n6 = GNUNET_CONTAINER_heap_insert (myHeap, "30/200", 30); GNUNET_assert (5 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_remove_node (n5); r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n1 */ GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("11", r)); GNUNET_CONTAINER_heap_update_cost (myHeap, n6, 200); GNUNET_CONTAINER_heap_remove_node (n3); r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n4 */ GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("50", r)); r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n6 */ GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("30/200", r)); GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_destroy (myHeap); // My additions to a complete testcase // Testing a GNUNET_CONTAINER_HEAP_ORDER_MIN // Testing remove_node myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15); r = GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("10", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); GNUNET_CONTAINER_heap_walk_get_next (myHeap); r = GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("20", r)); r = GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("10", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); r = GNUNET_CONTAINER_heap_remove_root (myHeap); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("30", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); r = GNUNET_CONTAINER_heap_remove_node (n3); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("30", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 20); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 30); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_root (myHeap))); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_root (myHeap))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 20); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 30); n4 = GNUNET_CONTAINER_heap_insert (myHeap, "40", 40); n5 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); n6 = GNUNET_CONTAINER_heap_insert (myHeap, "60", 60); // Inserting nodes deeper in the tree with lower costs n7 = GNUNET_CONTAINER_heap_insert (myHeap, "70", 10); n8 = GNUNET_CONTAINER_heap_insert (myHeap, "80", 10); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_node (n3))); // Cleaning up... GNUNET_assert (0 == nstrcmp ("60", GNUNET_CONTAINER_heap_remove_node (n6))); GNUNET_assert (0 == nstrcmp ("50", GNUNET_CONTAINER_heap_remove_node (n5))); // Testing heap_walk_get_next GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap);; GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("40", GNUNET_CONTAINER_heap_remove_node (n4))); GNUNET_assert (0 == nstrcmp ("70", GNUNET_CONTAINER_heap_remove_node (n7))); GNUNET_assert (0 == nstrcmp ("80", GNUNET_CONTAINER_heap_remove_node (n8))); // End Testing remove_node // Testing a GNUNET_CONTAINER_HEAP_ORDER_MAX GNUNET_CONTAINER_heap_destroy (myHeap); myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_root (myHeap))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_node (n3))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 20); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 30); n4 = GNUNET_CONTAINER_heap_insert (myHeap, "40", 40); n5 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); n6 = GNUNET_CONTAINER_heap_insert (myHeap, "60", 60); // Inserting nodes deeper in the tree with lower costs n7 = GNUNET_CONTAINER_heap_insert (myHeap, "70", 10); n8 = GNUNET_CONTAINER_heap_insert (myHeap, "80", 10); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_node (n3))); // Cleaning up... GNUNET_assert (0 == nstrcmp ("60", GNUNET_CONTAINER_heap_remove_node (n6))); GNUNET_assert (0 == nstrcmp ("50", GNUNET_CONTAINER_heap_remove_node (n5))); // Testing heap_walk_get_next GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap);; GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("40", GNUNET_CONTAINER_heap_remove_node (n4))); GNUNET_assert (0 == nstrcmp ("70", GNUNET_CONTAINER_heap_remove_node (n7))); GNUNET_assert (0 == nstrcmp ("80", GNUNET_CONTAINER_heap_remove_node (n8))); // End Testing remove_node GNUNET_CONTAINER_heap_destroy (myHeap); return 0; }
/** * Figure out when and how to transmit to the given peer. * * @param cls the `struct PeerPlan` */ static void schedule_peer_transmission (void *cls) { struct PeerPlan *pp = cls; struct GSF_RequestPlan *rp; struct GNUNET_TIME_Relative delay; if (NULL != pp->task) { pp->task = NULL; } else { GNUNET_assert (NULL != pp->env); pp->env = NULL; } /* move ready requests to priority queue */ while ((NULL != (rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap))) && (0 == GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission).rel_value_us)) { GNUNET_assert (rp == GNUNET_CONTAINER_heap_remove_root (pp->delay_heap)); rp->hn = GNUNET_CONTAINER_heap_insert (pp->priority_heap, rp, rp->priority); } if (0 == GNUNET_CONTAINER_heap_get_size (pp->priority_heap)) { /* priority heap (still) empty, check for delay... */ rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap); if (NULL == rp) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No active requests for plan %p.\n", pp); return; /* both queues empty */ } delay = GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sleeping for %s before retrying requests on plan %p.\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES), pp); GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# delay heap timeout (ms)"), delay.rel_value_us / 1000LL, GNUNET_NO); pp->task = GNUNET_SCHEDULER_add_delayed (delay, &schedule_peer_transmission, pp); return; } #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query plans executed"), 1, GNUNET_NO); #endif /* process from priority heap */ rp = GNUNET_CONTAINER_heap_remove_root (pp->priority_heap); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing query plan %p\n", rp); GNUNET_assert (NULL != rp); rp->hn = NULL; rp->last_transmission = GNUNET_TIME_absolute_get (); rp->transmission_counter++; total_delay++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing plan %p executed %u times, planning retransmission\n", rp, rp->transmission_counter); GNUNET_assert (NULL == pp->env); pp->env = GSF_pending_request_get_message_ (get_latest (rp)); GNUNET_MQ_notify_sent (pp->env, &schedule_peer_transmission, pp); GSF_peer_transmit_ (pp->cp, GNUNET_YES, rp->priority, pp->env); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query messages sent to other peers"), 1, GNUNET_NO); plan (pp, rp); }