diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-10-24 11:00:08 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-10-24 11:00:08 +0000 |
commit | f7cb5c5357256c548188a7684ff228cdf270edee (patch) | |
tree | 0ce8640caa16f05e258b789510febfa193240141 /src/fs/gnunet-service-fs_pe.c | |
parent | 569b1de87540e90a894a719bdee57adf229c47b7 (diff) | |
download | gnunet-f7cb5c5357256c548188a7684ff228cdf270edee.tar.gz gnunet-f7cb5c5357256c548188a7684ff228cdf270edee.zip |
fixing 1837
Diffstat (limited to 'src/fs/gnunet-service-fs_pe.c')
-rw-r--r-- | src/fs/gnunet-service-fs_pe.c | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/src/fs/gnunet-service-fs_pe.c b/src/fs/gnunet-service-fs_pe.c index 4555355d2..e85cafe90 100644 --- a/src/fs/gnunet-service-fs_pe.c +++ b/src/fs/gnunet-service-fs_pe.c | |||
@@ -36,6 +36,11 @@ | |||
36 | */ | 36 | */ |
37 | struct PendingRequestList; | 37 | struct PendingRequestList; |
38 | 38 | ||
39 | /** | ||
40 | * Transmission plan for a peer. | ||
41 | */ | ||
42 | struct PeerPlan; | ||
43 | |||
39 | 44 | ||
40 | /** | 45 | /** |
41 | * DLL of request plans a particular pending request is | 46 | * DLL of request plans a particular pending request is |
@@ -84,7 +89,7 @@ struct PendingRequestList | |||
84 | struct PendingRequestList *prev; | 89 | struct PendingRequestList *prev; |
85 | 90 | ||
86 | /** | 91 | /** |
87 | * Array of associated pending requests. | 92 | * Associated pending request. |
88 | */ | 93 | */ |
89 | struct GSF_PendingRequest *pr; | 94 | struct GSF_PendingRequest *pr; |
90 | 95 | ||
@@ -121,6 +126,11 @@ struct GSF_RequestPlan | |||
121 | struct GNUNET_CONTAINER_HeapNode *hn; | 126 | struct GNUNET_CONTAINER_HeapNode *hn; |
122 | 127 | ||
123 | /** | 128 | /** |
129 | * The transmission plan for a peer that this request is associated with. | ||
130 | */ | ||
131 | struct PeerPlan *pp; | ||
132 | |||
133 | /** | ||
124 | * Head of list of associated pending requests. | 134 | * Head of list of associated pending requests. |
125 | */ | 135 | */ |
126 | struct PendingRequestList *prl_head; | 136 | struct PendingRequestList *prl_head; |
@@ -169,6 +179,13 @@ struct PeerPlan | |||
169 | struct GNUNET_CONTAINER_Heap *delay_heap; | 179 | struct GNUNET_CONTAINER_Heap *delay_heap; |
170 | 180 | ||
171 | /** | 181 | /** |
182 | * Map of queries to plan entries. All entries in the priority_heap or delay_heap | ||
183 | * should be in the plan map. Note that it IS possible for the plan map to have | ||
184 | * multiple entries for the same query. | ||
185 | */ | ||
186 | struct GNUNET_CONTAINER_MultiHashMap *plan_map; | ||
187 | |||
188 | /** | ||
172 | * Current transmission request handle. | 189 | * Current transmission request handle. |
173 | */ | 190 | */ |
174 | struct GSF_PeerTransmitHandle *pth; | 191 | struct GSF_PeerTransmitHandle *pth; |
@@ -202,6 +219,19 @@ static unsigned long long plan_count; | |||
202 | 219 | ||
203 | 220 | ||
204 | /** | 221 | /** |
222 | * Return the query (key in the plan_map) for the given request plan. | ||
223 | * | ||
224 | * @param rp a request plan | ||
225 | * @return the associated query | ||
226 | */ | ||
227 | static const GNUNET_HashCode * | ||
228 | get_rp_key (struct GSF_RequestPlan *rp) | ||
229 | { | ||
230 | return &GSF_pending_request_get_data_ (rp->prl_head->pr)->query; | ||
231 | } | ||
232 | |||
233 | |||
234 | /** | ||
205 | * Figure out when and how to transmit to the given peer. | 235 | * Figure out when and how to transmit to the given peer. |
206 | * | 236 | * |
207 | * @param cls the 'struct GSF_ConnectedPeer' for transmission | 237 | * @param cls the 'struct GSF_ConnectedPeer' for transmission |
@@ -224,6 +254,7 @@ plan (struct PeerPlan *pp, struct GSF_RequestPlan *rp) | |||
224 | struct GSF_PendingRequestData *prd; | 254 | struct GSF_PendingRequestData *prd; |
225 | struct GNUNET_TIME_Relative delay; | 255 | struct GNUNET_TIME_Relative delay; |
226 | 256 | ||
257 | GNUNET_assert (rp->pp == pp); | ||
227 | GNUNET_STATISTICS_set (GSF_stats, | 258 | GNUNET_STATISTICS_set (GSF_stats, |
228 | gettext_noop ("# average retransmission delay (ms)"), | 259 | gettext_noop ("# average retransmission delay (ms)"), |
229 | total_delay * 1000LL / plan_count, GNUNET_NO); | 260 | total_delay * 1000LL / plan_count, GNUNET_NO); |
@@ -263,6 +294,10 @@ plan (struct PeerPlan *pp, struct GSF_RequestPlan *rp) | |||
263 | rp->hn = | 294 | rp->hn = |
264 | GNUNET_CONTAINER_heap_insert (pp->delay_heap, rp, | 295 | GNUNET_CONTAINER_heap_insert (pp->delay_heap, rp, |
265 | rp->earliest_transmission.abs_value); | 296 | rp->earliest_transmission.abs_value); |
297 | GNUNET_assert (GNUNET_YES == | ||
298 | GNUNET_CONTAINER_multihashmap_contains_value (pp->plan_map, | ||
299 | get_rp_key (rp), | ||
300 | rp)); | ||
266 | if (GNUNET_SCHEDULER_NO_TASK != pp->task) | 301 | if (GNUNET_SCHEDULER_NO_TASK != pp->task) |
267 | GNUNET_SCHEDULER_cancel (pp->task); | 302 | GNUNET_SCHEDULER_cancel (pp->task); |
268 | pp->task = GNUNET_SCHEDULER_add_now (&schedule_peer_transmission, pp); | 303 | pp->task = GNUNET_SCHEDULER_add_now (&schedule_peer_transmission, pp); |
@@ -447,15 +482,15 @@ struct MergeContext | |||
447 | * present for this peer. | 482 | * present for this peer. |
448 | * | 483 | * |
449 | * @param cls closure | 484 | * @param cls closure |
450 | * @param node internal node of the heap (ignored) | 485 | * @param query the query |
451 | * @param element request plan stored at the node | 486 | * @param element request plan stored at the node |
452 | * @param cost cost associated with the node (ignored) | ||
453 | * @return GNUNET_YES if we should continue to iterate, | 487 | * @return GNUNET_YES if we should continue to iterate, |
454 | * GNUNET_NO if not (merge success) | 488 | * GNUNET_NO if not (merge success) |
455 | */ | 489 | */ |
456 | static int | 490 | static int |
457 | merge_pr (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, | 491 | merge_pr (void *cls, |
458 | GNUNET_CONTAINER_HeapCostType cost) | 492 | const GNUNET_HashCode *query, |
493 | void *element) | ||
459 | { | 494 | { |
460 | struct MergeContext *mpr = cls; | 495 | struct MergeContext *mpr = cls; |
461 | struct GSF_RequestPlan *rp = element; | 496 | struct GSF_RequestPlan *rp = element; |
@@ -515,6 +550,8 @@ GSF_plan_add_ (struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr) | |||
515 | if (NULL == pp) | 550 | if (NULL == pp) |
516 | { | 551 | { |
517 | pp = GNUNET_malloc (sizeof (struct PeerPlan)); | 552 | pp = GNUNET_malloc (sizeof (struct PeerPlan)); |
553 | pp->plan_map = | ||
554 | GNUNET_CONTAINER_multihashmap_create (128); | ||
518 | pp->priority_heap = | 555 | pp->priority_heap = |
519 | GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); | 556 | GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); |
520 | pp->delay_heap = | 557 | pp->delay_heap = |
@@ -525,12 +562,14 @@ GSF_plan_add_ (struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr) | |||
525 | } | 562 | } |
526 | mpc.merged = GNUNET_NO; | 563 | mpc.merged = GNUNET_NO; |
527 | mpc.pr = pr; | 564 | mpc.pr = pr; |
528 | /* FIXME: O(n) call here, LRN reports this is a performance | 565 | GNUNET_CONTAINER_multihashmap_get_multiple (pp->plan_map, |
529 | problem. Try using hash map!? */ | 566 | &GSF_pending_request_get_data_ (pr)->query, |
530 | GNUNET_CONTAINER_heap_iterate (pp->priority_heap, &merge_pr, &mpc); | 567 | &merge_pr, &mpc); |
531 | if (mpc.merged != GNUNET_NO) | 568 | if (mpc.merged != GNUNET_NO) |
532 | return; | 569 | return; |
533 | GNUNET_CONTAINER_heap_iterate (pp->delay_heap, &merge_pr, &mpc); | 570 | GNUNET_CONTAINER_multihashmap_get_multiple (pp->plan_map, |
571 | &GSF_pending_request_get_data_ (pr)->query, | ||
572 | &merge_pr, &mpc); | ||
534 | if (mpc.merged != GNUNET_NO) | 573 | if (mpc.merged != GNUNET_NO) |
535 | return; | 574 | return; |
536 | plan_count++; | 575 | plan_count++; |
@@ -551,6 +590,12 @@ GSF_plan_add_ (struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr) | |||
551 | prl->pr = pr; | 590 | prl->pr = pr; |
552 | GNUNET_CONTAINER_DLL_insert (prd->rpr_head, prd->rpr_tail, rpr); | 591 | GNUNET_CONTAINER_DLL_insert (prd->rpr_head, prd->rpr_tail, rpr); |
553 | GNUNET_CONTAINER_DLL_insert (rp->prl_head, rp->prl_tail, prl); | 592 | GNUNET_CONTAINER_DLL_insert (rp->prl_head, rp->prl_tail, prl); |
593 | rp->pp = pp; | ||
594 | GNUNET_assert (GNUNET_YES == | ||
595 | GNUNET_CONTAINER_multihashmap_put (pp->plan_map, | ||
596 | get_rp_key (rp), | ||
597 | rp, | ||
598 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
554 | plan (pp, rp); | 599 | plan (pp, rp); |
555 | } | 600 | } |
556 | 601 | ||
@@ -586,6 +631,10 @@ GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp) | |||
586 | } | 631 | } |
587 | while (NULL != (rp = GNUNET_CONTAINER_heap_remove_root (pp->priority_heap))) | 632 | while (NULL != (rp = GNUNET_CONTAINER_heap_remove_root (pp->priority_heap))) |
588 | { | 633 | { |
634 | GNUNET_assert (GNUNET_YES == | ||
635 | GNUNET_CONTAINER_multihashmap_remove (pp->plan_map, | ||
636 | get_rp_key (rp), | ||
637 | rp)); | ||
589 | while (NULL != (prl = rp->prl_head)) | 638 | while (NULL != (prl = rp->prl_head)) |
590 | { | 639 | { |
591 | GNUNET_CONTAINER_DLL_remove (rp->prl_head, rp->prl_tail, prl); | 640 | GNUNET_CONTAINER_DLL_remove (rp->prl_head, rp->prl_tail, prl); |
@@ -599,6 +648,9 @@ GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp) | |||
599 | GNUNET_CONTAINER_heap_destroy (pp->priority_heap); | 648 | GNUNET_CONTAINER_heap_destroy (pp->priority_heap); |
600 | while (NULL != (rp = GNUNET_CONTAINER_heap_remove_root (pp->delay_heap))) | 649 | while (NULL != (rp = GNUNET_CONTAINER_heap_remove_root (pp->delay_heap))) |
601 | { | 650 | { |
651 | GNUNET_CONTAINER_multihashmap_remove (pp->plan_map, | ||
652 | get_rp_key (rp), | ||
653 | rp); | ||
602 | while (NULL != (prl = rp->prl_head)) | 654 | while (NULL != (prl = rp->prl_head)) |
603 | { | 655 | { |
604 | GNUNET_CONTAINER_DLL_remove (rp->prl_head, rp->prl_tail, prl); | 656 | GNUNET_CONTAINER_DLL_remove (rp->prl_head, rp->prl_tail, prl); |
@@ -613,6 +665,7 @@ GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp) | |||
613 | plan_count, GNUNET_NO); | 665 | plan_count, GNUNET_NO); |
614 | 666 | ||
615 | GNUNET_CONTAINER_heap_destroy (pp->delay_heap); | 667 | GNUNET_CONTAINER_heap_destroy (pp->delay_heap); |
668 | GNUNET_CONTAINER_multihashmap_destroy (pp->plan_map); | ||
616 | GNUNET_free (pp); | 669 | GNUNET_free (pp); |
617 | } | 670 | } |
618 | 671 | ||
@@ -636,14 +689,17 @@ GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr) | |||
636 | GNUNET_CONTAINER_DLL_remove (prd->rpr_head, prd->rpr_tail, rpr); | 689 | GNUNET_CONTAINER_DLL_remove (prd->rpr_head, prd->rpr_tail, rpr); |
637 | rp = rpr->rp; | 690 | rp = rpr->rp; |
638 | GNUNET_CONTAINER_DLL_remove (rp->prl_head, rp->prl_tail, rpr->prl); | 691 | GNUNET_CONTAINER_DLL_remove (rp->prl_head, rp->prl_tail, rpr->prl); |
639 | GNUNET_free (rpr->prl); | 692 | if (NULL == rp->prl_head) |
640 | GNUNET_free (rpr); | ||
641 | if (rp->prl_head == 0) | ||
642 | { | 693 | { |
643 | GNUNET_CONTAINER_heap_remove_node (rp->hn); | 694 | GNUNET_CONTAINER_heap_remove_node (rp->hn); |
644 | plan_count--; | 695 | plan_count--; |
696 | GNUNET_CONTAINER_multihashmap_remove (rp->pp->plan_map, | ||
697 | &GSF_pending_request_get_data_ (rpr->prl->pr)->query, | ||
698 | rp); | ||
645 | GNUNET_free (rp); | 699 | GNUNET_free (rp); |
646 | } | 700 | } |
701 | GNUNET_free (rpr->prl); | ||
702 | GNUNET_free (rpr); | ||
647 | } | 703 | } |
648 | GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# query plan entries"), | 704 | GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# query plan entries"), |
649 | plan_count, GNUNET_NO); | 705 | plan_count, GNUNET_NO); |