aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-service-fs_pe.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-10-24 11:00:08 +0000
committerChristian Grothoff <christian@grothoff.org>2011-10-24 11:00:08 +0000
commitf7cb5c5357256c548188a7684ff228cdf270edee (patch)
tree0ce8640caa16f05e258b789510febfa193240141 /src/fs/gnunet-service-fs_pe.c
parent569b1de87540e90a894a719bdee57adf229c47b7 (diff)
downloadgnunet-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.c80
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 */
37struct PendingRequestList; 37struct PendingRequestList;
38 38
39/**
40 * Transmission plan for a peer.
41 */
42struct 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 */
227static const GNUNET_HashCode *
228get_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 */
456static int 490static int
457merge_pr (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, 491merge_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);