aboutsummaryrefslogtreecommitdiff
path: root/src/consensus
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2014-02-10 00:30:23 +0000
committerFlorian Dold <florian.dold@gmail.com>2014-02-10 00:30:23 +0000
commit8c669666c7756352e9cb93e48e973e1785bfc43f (patch)
tree35aec89dd4164b3216244d03b1b6ed7ec0cbe9ed /src/consensus
parentf41fa68561b05a68dbcea690fbd10fda7d0d4460 (diff)
downloadgnunet-8c669666c7756352e9cb93e48e973e1785bfc43f.tar.gz
gnunet-8c669666c7756352e9cb93e48e973e1785bfc43f.zip
- correct handling of timeouts in consensus
- fixed segfault in secretsharing profiler
Diffstat (limited to 'src/consensus')
-rw-r--r--src/consensus/consensus_protocol.h2
-rw-r--r--src/consensus/gnunet-consensus-profiler.c7
-rw-r--r--src/consensus/gnunet-service-consensus.c175
-rw-r--r--src/consensus/test_consensus.conf3
4 files changed, 136 insertions, 51 deletions
diff --git a/src/consensus/consensus_protocol.h b/src/consensus/consensus_protocol.h
index 128ca2c16..e84768161 100644
--- a/src/consensus/consensus_protocol.h
+++ b/src/consensus/consensus_protocol.h
@@ -45,7 +45,7 @@ struct GNUNET_CONSENSUS_RoundContextMessage
45 */ 45 */
46 struct GNUNET_MessageHeader header; 46 struct GNUNET_MessageHeader header;
47 uint32_t round; 47 uint32_t round;
48 uint32_t exp_round; 48 uint32_t exp_repetition;
49 uint32_t exp_subround; 49 uint32_t exp_subround;
50}; 50};
51 51
diff --git a/src/consensus/gnunet-consensus-profiler.c b/src/consensus/gnunet-consensus-profiler.c
index d7a14f68e..ef8e08e08 100644
--- a/src/consensus/gnunet-consensus-profiler.c
+++ b/src/consensus/gnunet-consensus-profiler.c
@@ -37,6 +37,8 @@ static unsigned int num_values = 5;
37 37
38static struct GNUNET_TIME_Relative conclude_timeout; 38static struct GNUNET_TIME_Relative conclude_timeout;
39 39
40static struct GNUNET_TIME_Relative consensus_delay;
41
40static struct GNUNET_CONSENSUS_Handle **consensus_handles; 42static struct GNUNET_CONSENSUS_Handle **consensus_handles;
41 43
42static struct GNUNET_TESTBED_Operation **testbed_operations; 44static struct GNUNET_TESTBED_Operation **testbed_operations;
@@ -408,7 +410,7 @@ run (void *cls, char *const *args, const char *cfgfile,
408 return; 410 return;
409 } 411 }
410 412
411 start = GNUNET_TIME_absolute_get (); 413 start = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), consensus_delay);
412 deadline = GNUNET_TIME_absolute_add (start, conclude_timeout); 414 deadline = GNUNET_TIME_absolute_add (start, conclude_timeout);
413 415
414 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 416 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -443,6 +445,9 @@ main (int argc, char **argv)
443 { 't', "timeout", NULL, 445 { 't', "timeout", NULL,
444 gettext_noop ("consensus timeout"), 446 gettext_noop ("consensus timeout"),
445 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &conclude_timeout }, 447 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &conclude_timeout },
448 { 'd', "delay", NULL,
449 gettext_noop ("delay until consensus starts"),
450 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &consensus_delay },
446 { 'V', "verbose", NULL, 451 { 'V', "verbose", NULL,
447 gettext_noop ("be more verbose (print received values)"), 452 gettext_noop ("be more verbose (print received values)"),
448 GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose }, 453 GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose },
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c
index ffd9786d3..95c4e5783 100644
--- a/src/consensus/gnunet-service-consensus.c
+++ b/src/consensus/gnunet-service-consensus.c
@@ -36,6 +36,10 @@
36 36
37/** 37/**
38 * Log macro that prefixes the local peer and the peer we are in contact with. 38 * Log macro that prefixes the local peer and the peer we are in contact with.
39 *
40 * @param kind log level
41 * @param cpi ConsensusPeerInformation of the partner peer
42 * @param m log message
39 */ 43 */
40#define LOG_PP(kind, cpi, m,...) GNUNET_log (kind, "P%d for P%d: " m, \ 44#define LOG_PP(kind, cpi, m,...) GNUNET_log (kind, "P%d for P%d: " m, \
41 cpi->session->local_peer_idx, (int) (cpi - cpi->session->info),##__VA_ARGS__) 45 cpi->session->local_peer_idx, (int) (cpi - cpi->session->info),##__VA_ARGS__)
@@ -44,7 +48,8 @@
44/** 48/**
45 * Number of exponential rounds, used in the exp and completion round. 49 * Number of exponential rounds, used in the exp and completion round.
46 */ 50 */
47#define NUM_EXP_ROUNDS 4 51#define NUM_EXP_REPETITIONS 4
52
48 53
49/* forward declarations */ 54/* forward declarations */
50 55
@@ -70,13 +75,7 @@ enum ConsensusRound
70 */ 75 */
71 CONSENSUS_ROUND_EXCHANGE, 76 CONSENSUS_ROUND_EXCHANGE,
72 /** 77 /**
73 * Exchange which elements each peer has, but don't 78 * Collect and distribute missing values.
74 * transmit the element's data, only their SHA-512 hashes.
75 * This round uses the all-to-all scheme.
76 */
77 CONSENSUS_ROUND_INVENTORY,
78 /**
79 * Collect and distribute missing values with the exponential scheme.
80 */ 79 */
81 CONSENSUS_ROUND_COMPLETION, 80 CONSENSUS_ROUND_COMPLETION,
82 /** 81 /**
@@ -88,8 +87,7 @@ enum ConsensusRound
88 87
89 88
90/** 89/**
91 * Complete information about the current round and all 90 * Information about the current round.
92 * subrounds.
93 */ 91 */
94struct RoundInfo 92struct RoundInfo
95{ 93{
@@ -98,10 +96,10 @@ struct RoundInfo
98 */ 96 */
99 enum ConsensusRound round; 97 enum ConsensusRound round;
100 /** 98 /**
101 * The current exp round, valid if 99 * The current exp round repetition, valid if
102 * the main round is an exp round. 100 * the main round is an exp round.
103 */ 101 */
104 uint32_t exp_round; 102 uint32_t exp_repetition;
105 /** 103 /**
106 * The current exp subround, valid if 104 * The current exp subround, valid if
107 * the main round is an exp round. 105 * the main round is an exp round.
@@ -154,7 +152,7 @@ struct ConsensusSession
154 struct GNUNET_TIME_Absolute conclude_deadline; 152 struct GNUNET_TIME_Absolute conclude_deadline;
155 153
156 /** 154 /**
157 * Timeout task identifier for the current round. 155 * Timeout task identifier for the current round or subround.
158 */ 156 */
159 GNUNET_SCHEDULER_TaskIdentifier round_timeout_tid; 157 GNUNET_SCHEDULER_TaskIdentifier round_timeout_tid;
160 158
@@ -192,7 +190,7 @@ struct ConsensusSession
192 /** 190 /**
193 * Current round of the exponential scheme. 191 * Current round of the exponential scheme.
194 */ 192 */
195 uint32_t exp_round; 193 uint32_t exp_repetition;
196 194
197 /** 195 /**
198 * Current sub-round of the exponential scheme. 196 * Current sub-round of the exponential scheme.
@@ -200,12 +198,16 @@ struct ConsensusSession
200 uint32_t exp_subround; 198 uint32_t exp_subround;
201 199
202 /** 200 /**
203 * The partner for the current exp-round 201 * The partner for the current exp-round.
202 * The local peer will initiate the set reconciliation with the
203 * outgoing peer.
204 */ 204 */
205 struct ConsensusPeerInformation *partner_outgoing; 205 struct ConsensusPeerInformation *partner_outgoing;
206 206
207 /** 207 /**
208 * The partner for the current exp-round 208 * The partner for the current exp-round
209 * The incoming peer will initiate the set reconciliation with
210 * the incoming peer.
209 */ 211 */
210 struct ConsensusPeerInformation *partner_incoming; 212 struct ConsensusPeerInformation *partner_incoming;
211 213
@@ -239,9 +241,9 @@ struct ConsensusPeerInformation
239 struct ConsensusSession *session; 241 struct ConsensusSession *session;
240 242
241 /** 243 /**
242 * We have finishes the exp-subround with the peer. 244 * Have we finished the set operation for this (sub-)round?
243 */ 245 */
244 int exp_subround_finished; 246 int set_op_finished;
245 247
246 /** 248 /**
247 * Set operation we are currently executing with this peer. 249 * Set operation we are currently executing with this peer.
@@ -286,16 +288,27 @@ static struct GNUNET_SERVER_Handle *srv;
286static struct GNUNET_PeerIdentity my_peer; 288static struct GNUNET_PeerIdentity my_peer;
287 289
288 290
291/**
292 * Check if the current subround has finished.
293 * Must only be called when an exp-round is the current round.
294 *
295 * @param session session to check for exp-round completion
296 * @return GNUNET_YES if the subround has finished,
297 * GNUNET_NO if not
298 */
289static int 299static int
290have_exp_subround_finished (const struct ConsensusSession *session) 300have_exp_subround_finished (const struct ConsensusSession *session)
291{ 301{
292 int not_finished; 302 int not_finished;
303
304 GNUNET_assert (CONSENSUS_ROUND_EXCHANGE == session->current_round);
305
293 not_finished = 0; 306 not_finished = 0;
294 if ( (NULL != session->partner_outgoing) && 307 if ( (NULL != session->partner_outgoing) &&
295 (GNUNET_NO == session->partner_outgoing->exp_subround_finished) ) 308 (GNUNET_NO == session->partner_outgoing->set_op_finished) )
296 not_finished++; 309 not_finished++;
297 if ( (NULL != session->partner_incoming) && 310 if ( (NULL != session->partner_incoming) &&
298 (GNUNET_NO == session->partner_incoming->exp_subround_finished) ) 311 (GNUNET_NO == session->partner_incoming->set_op_finished) )
299 not_finished++; 312 not_finished++;
300 if (0 == not_finished) 313 if (0 == not_finished)
301 return GNUNET_YES; 314 return GNUNET_YES;
@@ -413,6 +426,8 @@ static void
413round_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 426round_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
414{ 427{
415 struct ConsensusSession *session; 428 struct ConsensusSession *session;
429 unsigned int i;
430 int res;
416 431
417 /* don't kick off next round if we're shutting down */ 432 /* don't kick off next round if we're shutting down */
418 if ((NULL != tc) && (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 433 if ((NULL != tc) && (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
@@ -421,24 +436,48 @@ round_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
421 session = cls; 436 session = cls;
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: round over\n", session->local_peer_idx); 437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: round over\n", session->local_peer_idx);
423 438
439 if (tc != NULL)
440 session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK;
441
424 if (session->round_timeout_tid != GNUNET_SCHEDULER_NO_TASK) 442 if (session->round_timeout_tid != GNUNET_SCHEDULER_NO_TASK)
425 { 443 {
426 GNUNET_SCHEDULER_cancel (session->round_timeout_tid); 444 GNUNET_SCHEDULER_cancel (session->round_timeout_tid);
427 session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK; 445 session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK;
428 } 446 }
429 447
448 for (i = 0; i < session->num_peers; i++)
449 {
450 if (NULL != session->info[i].set_op)
451 {
452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: canceling stray op with P%d\n",
453 session->local_peer_idx, i);
454 GNUNET_SET_operation_cancel (session->info[i].set_op);
455 session->info[i].set_op = NULL;
456 }
457 /* we're in the new round, nothing finished yet */
458 session->info[i].set_op_finished = GNUNET_NO;
459 }
460
430 switch (session->current_round) 461 switch (session->current_round)
431 { 462 {
432 case CONSENSUS_ROUND_BEGIN: 463 case CONSENSUS_ROUND_BEGIN:
433 session->current_round = CONSENSUS_ROUND_EXCHANGE; 464 session->current_round = CONSENSUS_ROUND_EXCHANGE;
434 session->exp_round = 0; 465 session->exp_repetition = 0;
435 subround_over (session, NULL); 466 subround_over (session, NULL);
436 break; 467 break;
437 case CONSENSUS_ROUND_EXCHANGE: 468 case CONSENSUS_ROUND_EXCHANGE:
438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: finished, sending elements to client\n", 469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: finished, sending elements to client\n",
439 session->local_peer_idx); 470 session->local_peer_idx);
440 session->current_round = CONSENSUS_ROUND_FINISH; 471 session->current_round = CONSENSUS_ROUND_FINISH;
441 GNUNET_SET_iterate (session->element_set, send_to_client_iter, session); 472 res = GNUNET_SET_iterate (session->element_set, send_to_client_iter, session);
473 if (GNUNET_SYSERR == res)
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "can't iterate set: set invalid\n");
476 }
477 else if (GNUNET_NO == res)
478 {
479 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "can't iterate set: iterator already active\n");
480 }
442 break; 481 break;
443 default: 482 default:
444 GNUNET_assert (0); 483 GNUNET_assert (0);
@@ -465,7 +504,7 @@ shuffle (struct ConsensusSession *session)
465 session->shuffle_inv = GNUNET_malloc (session->num_peers * sizeof (*session->shuffle_inv)); 504 session->shuffle_inv = GNUNET_malloc (session->num_peers * sizeof (*session->shuffle_inv));
466 505
467 GNUNET_CRYPTO_kdf (randomness, sizeof (randomness), 506 GNUNET_CRYPTO_kdf (randomness, sizeof (randomness),
468 &session->exp_round, sizeof (uint32_t), 507 &session->exp_repetition, sizeof (uint32_t),
469 &session->global_id, sizeof (struct GNUNET_HashCode), 508 &session->global_id, sizeof (struct GNUNET_HashCode),
470 NULL); 509 NULL);
471 510
@@ -521,7 +560,7 @@ find_partners (struct ConsensusSession *session)
521 /* we are outgoing */ 560 /* we are outgoing */
522 partner_idx = (my_idx + arc) % session->num_peers; 561 partner_idx = (my_idx + arc) % session->num_peers;
523 session->partner_outgoing = &session->info[session->shuffle_inv[partner_idx]]; 562 session->partner_outgoing = &session->info[session->shuffle_inv[partner_idx]];
524 session->partner_outgoing->exp_subround_finished = GNUNET_NO; 563 GNUNET_assert (GNUNET_NO == session->partner_outgoing->set_op_finished);
525 /* are we a 'ghost' of a peer that would exist if 564 /* are we a 'ghost' of a peer that would exist if
526 * the number of peers was a power of two, and thus have to partner 565 * the number of peers was a power of two, and thus have to partner
527 * with an additional peer? 566 * with an additional peer?
@@ -539,7 +578,7 @@ find_partners (struct ConsensusSession *session)
539 { 578 {
540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ghost partner is %d\n", ghost_partner_idx); 579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ghost partner is %d\n", ghost_partner_idx);
541 session->partner_incoming = &session->info[session->shuffle_inv[ghost_partner_idx]]; 580 session->partner_incoming = &session->info[session->shuffle_inv[ghost_partner_idx]];
542 session->partner_incoming->exp_subround_finished = GNUNET_NO; 581 GNUNET_assert (GNUNET_NO == session->partner_incoming->set_op_finished);
543 return; 582 return;
544 } 583 }
545 } 584 }
@@ -552,7 +591,7 @@ find_partners (struct ConsensusSession *session)
552 partner_idx += session->num_peers; 591 partner_idx += session->num_peers;
553 session->partner_outgoing = NULL; 592 session->partner_outgoing = NULL;
554 session->partner_incoming = &session->info[session->shuffle_inv[partner_idx]]; 593 session->partner_incoming = &session->info[session->shuffle_inv[partner_idx]];
555 session->partner_incoming->exp_subround_finished = GNUNET_NO; 594 GNUNET_assert (GNUNET_NO == session->partner_incoming->set_op_finished);
556} 595}
557 596
558 597
@@ -591,7 +630,7 @@ set_result_cb (void *cls,
591 case GNUNET_SET_STATUS_DONE: 630 case GNUNET_SET_STATUS_DONE:
592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: set result from P%u: done\n", 631 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: set result from P%u: done\n",
593 local_idx, remote_idx); 632 local_idx, remote_idx);
594 cpi->exp_subround_finished = GNUNET_YES; 633 cpi->set_op_finished = GNUNET_YES;
595 cpi->set_op = NULL; 634 cpi->set_op = NULL;
596 if (have_exp_subround_finished (cpi->session) == GNUNET_YES) 635 if (have_exp_subround_finished (cpi->session) == GNUNET_YES)
597 { 636 {
@@ -612,6 +651,7 @@ set_result_cb (void *cls,
612 651
613 switch (cpi->session->current_round) 652 switch (cpi->session->current_round)
614 { 653 {
654 case CONSENSUS_ROUND_COMPLETION:
615 case CONSENSUS_ROUND_EXCHANGE: 655 case CONSENSUS_ROUND_EXCHANGE:
616 GNUNET_SET_add_element (cpi->session->element_set, element, NULL, NULL); 656 GNUNET_SET_add_element (cpi->session->element_set, element, NULL, NULL);
617 break; 657 break;
@@ -640,9 +680,9 @@ rounds_compare (struct ConsensusSession *session,
640 return 1; 680 return 1;
641 if (session->current_round == CONSENSUS_ROUND_EXCHANGE) 681 if (session->current_round == CONSENSUS_ROUND_EXCHANGE)
642 { 682 {
643 if (session->exp_round < ri->exp_round) 683 if (session->exp_repetition < ri->exp_repetition)
644 return -1; 684 return -1;
645 if (session->exp_round > ri->exp_round) 685 if (session->exp_repetition > ri->exp_repetition)
646 return 1; 686 return 1;
647 if (session->exp_subround < ri->exp_subround) 687 if (session->exp_subround < ri->exp_subround)
648 return -1; 688 return -1;
@@ -650,8 +690,8 @@ rounds_compare (struct ConsensusSession *session,
650 return 1; 690 return 1;
651 return 0; 691 return 0;
652 } 692 }
653 /* comparing rounds when we are not in a exp round */ 693 /* other rounds have no subrounds / repetitions to compare */
654 GNUNET_assert (0); 694 return 0;
655} 695}
656 696
657 697
@@ -667,12 +707,24 @@ static void
667subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 707subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
668{ 708{
669 struct ConsensusSession *session; 709 struct ConsensusSession *session;
710 struct GNUNET_TIME_Relative subround_timeout;
670 int i; 711 int i;
671 712
672 /* don't kick off next subround if we're shutting down */ 713 /* don't kick off next subround if we're shutting down */
673 if ((NULL != tc) && (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 714 if ((NULL != tc) && (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
674 return; 715 return;
716
675 session = cls; 717 session = cls;
718
719 GNUNET_assert (CONSENSUS_ROUND_EXCHANGE == session->current_round);
720
721 if (tc != NULL)
722 {
723 session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK;
724 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: consensus subround timed out\n",
725 session->local_peer_idx);
726 }
727
676 /* cancel timeout */ 728 /* cancel timeout */
677 if (session->round_timeout_tid != GNUNET_SCHEDULER_NO_TASK) 729 if (session->round_timeout_tid != GNUNET_SCHEDULER_NO_TASK)
678 { 730 {
@@ -680,16 +732,29 @@ subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
680 session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK; 732 session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK;
681 } 733 }
682 734
683 if (session->exp_round >= NUM_EXP_ROUNDS) 735 for (i = 0; i < session->num_peers; i++)
736 {
737 if (NULL != session->info[i].set_op)
738 {
739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: canceling stray op with P%d\n",
740 session->local_peer_idx, i);
741 GNUNET_SET_operation_cancel (session->info[i].set_op);
742 session->info[i].set_op = NULL;
743 }
744 /* we're in the new round, nothing finished yet */
745 session->info[i].set_op_finished = GNUNET_NO;
746 }
747
748 if (session->exp_repetition >= NUM_EXP_REPETITIONS)
684 { 749 {
685 round_over (session, NULL); 750 round_over (session, NULL);
686 return; 751 return;
687 } 752 }
688 753
689 if (session->exp_round == 0) 754 if (session->exp_repetition == 0)
690 { 755 {
691 /* initialize everything for the log-rounds */ 756 /* initialize everything for the log-rounds */
692 session->exp_round = 1; 757 session->exp_repetition = 1;
693 session->exp_subround = 0; 758 session->exp_subround = 0;
694 if (NULL == session->shuffle) 759 if (NULL == session->shuffle)
695 session->shuffle = GNUNET_malloc ((sizeof (int)) * session->num_peers); 760 session->shuffle = GNUNET_malloc ((sizeof (int)) * session->num_peers);
@@ -701,7 +766,7 @@ subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
701 else if (session->exp_subround + 1 >= (int) ceil (log2 (session->num_peers))) 766 else if (session->exp_subround + 1 >= (int) ceil (log2 (session->num_peers)))
702 { 767 {
703 /* subrounds done, start new log-round */ 768 /* subrounds done, start new log-round */
704 session->exp_round++; 769 session->exp_repetition++;
705 session->exp_subround = 0; 770 session->exp_subround = 0;
706 shuffle (session); 771 shuffle (session);
707 } 772 }
@@ -710,6 +775,14 @@ subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
710 session->exp_subround++; 775 session->exp_subround++;
711 } 776 }
712 777
778 subround_timeout =
779 GNUNET_TIME_relative_divide (GNUNET_TIME_absolute_get_difference (session->conclude_start, session->conclude_deadline),
780 2 * NUM_EXP_REPETITIONS * ((int) ceil (log2 (session->num_peers))));
781
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "subround timeout: %u ms\n", subround_timeout.rel_value_us / 1000);
783
784 session->round_timeout_tid = GNUNET_SCHEDULER_add_delayed (subround_timeout, subround_over, session);
785
713 /* determine the incoming and outgoing partner */ 786 /* determine the incoming and outgoing partner */
714 find_partners (session); 787 find_partners (session);
715 788
@@ -724,11 +797,12 @@ subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
724 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT); 797 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
725 msg->header.size = htons (sizeof *msg); 798 msg->header.size = htons (sizeof *msg);
726 msg->round = htonl (session->current_round); 799 msg->round = htonl (session->current_round);
727 msg->exp_round = htonl (session->exp_round); 800 msg->exp_repetition = htonl (session->exp_repetition);
728 msg->exp_subround = htonl (session->exp_subround); 801 msg->exp_subround = htonl (session->exp_subround);
729 802
730 if (NULL != session->partner_outgoing->set_op) 803 if (NULL != session->partner_outgoing->set_op)
731 { 804 {
805 GNUNET_break (0);
732 GNUNET_SET_operation_cancel (session->partner_outgoing->set_op); 806 GNUNET_SET_operation_cancel (session->partner_outgoing->set_op);
733 } 807 }
734 session->partner_outgoing->set_op = 808 session->partner_outgoing->set_op =
@@ -749,6 +823,7 @@ subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
749 823
750 if (NULL != session->partner_incoming->set_op) 824 if (NULL != session->partner_incoming->set_op)
751 { 825 {
826 GNUNET_break (0);
752 GNUNET_SET_operation_cancel (session->partner_incoming->set_op); 827 GNUNET_SET_operation_cancel (session->partner_incoming->set_op);
753 session->partner_incoming->set_op = NULL; 828 session->partner_incoming->set_op = NULL;
754 } 829 }
@@ -780,7 +855,7 @@ subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
780 else 855 else
781 in = (int) (session->partner_incoming - session->info); 856 in = (int) (session->partner_incoming - session->info);
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: doing exp-round, r=%d, sub=%d, in: %d, out: %d\n", session->local_peer_idx, 857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: doing exp-round, r=%d, sub=%d, in: %d, out: %d\n", session->local_peer_idx,
783 session->exp_round, session->exp_subround, in, out); 858 session->exp_repetition, session->exp_subround, in, out);
784 } 859 }
785#endif /* GNUNET_EXTRA_LOGGING */ 860#endif /* GNUNET_EXTRA_LOGGING */
786 861
@@ -837,18 +912,16 @@ compute_global_id (struct ConsensusSession *session,
837 912
838 913
839/** 914/**
840 * Although GNUNET_CRYPTO_hash_cmp exisits, it does not have 915 * Compare two peer identities.
841 * the correct signature to be used with e.g. qsort.
842 * We use this function instead.
843 * 916 *
844 * @param h1 some hash code 917 * @param h1 some peer identity
845 * @param h2 some hash code 918 * @param h2 some peer identity
846 * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. 919 * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.
847 */ 920 */
848static int 921static int
849hash_cmp (const void *h1, const void *h2) 922peer_id_cmp (const void *h1, const void *h2)
850{ 923{
851 return GNUNET_CRYPTO_hash_cmp ((struct GNUNET_HashCode *) h1, (struct GNUNET_HashCode *) h2); 924 return memcmp (h1, h2, sizeof (struct GNUNET_PeerIdentity));
852} 925}
853 926
854 927
@@ -894,7 +967,7 @@ initialize_session_peer_list (struct ConsensusSession *session,
894 peers[session->num_peers - 1] = my_peer; 967 peers[session->num_peers - 1] = my_peer;
895 968
896 memcpy (peers, msg_peers, listed_peers * sizeof (struct GNUNET_PeerIdentity)); 969 memcpy (peers, msg_peers, listed_peers * sizeof (struct GNUNET_PeerIdentity));
897 qsort (peers, session->num_peers, sizeof (struct GNUNET_PeerIdentity), &hash_cmp); 970 qsort (peers, session->num_peers, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp);
898 971
899 session->info = GNUNET_malloc (session->num_peers * sizeof (struct ConsensusPeerInformation)); 972 session->info = GNUNET_malloc (session->num_peers * sizeof (struct ConsensusPeerInformation));
900 973
@@ -954,7 +1027,7 @@ set_listen_cb (void *cls,
954 } 1027 }
955 1028
956 round_info.round = ntohl (msg->round); 1029 round_info.round = ntohl (msg->round);
957 round_info.exp_round = ntohl (msg->exp_round); 1030 round_info.exp_repetition = ntohl (msg->exp_repetition);
958 round_info.exp_subround = ntohl (msg->exp_subround); 1031 round_info.exp_subround = ntohl (msg->exp_subround);
959 1032
960 cpi = &session->info[index]; 1033 cpi = &session->info[index];
@@ -979,11 +1052,12 @@ set_listen_cb (void *cls,
979 * complete the old one! */ 1052 * complete the old one! */
980 if (NULL != cpi->set_op) 1053 if (NULL != cpi->set_op)
981 { 1054 {
1055 LOG_PP (GNUNET_ERROR_TYPE_INFO, cpi, "got new request from same peer, canceling old one\n");
982 GNUNET_SET_operation_cancel (cpi->set_op); 1056 GNUNET_SET_operation_cancel (cpi->set_op);
983 cpi->set_op = NULL; 1057 cpi->set_op = NULL;
984 } 1058 }
985 set_op = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED, 1059 set_op = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED,
986 set_result_cb, &session->info[index]); 1060 set_result_cb, &session->info[index]);
987 if (cmp == 0) 1061 if (cmp == 0)
988 { 1062 {
989 cpi->set_op = set_op; 1063 cpi->set_op = set_op;
@@ -992,10 +1066,12 @@ set_listen_cb (void *cls,
992 } 1066 }
993 else 1067 else
994 { 1068 {
995 /* if there's a exp subround running, mark it as finished, as the set op has been canceled! */ 1069 /* we still have wait until we have finished the current round,
1070 * as the other peer's round is larger */
996 cpi->delayed_set_op = set_op; 1071 cpi->delayed_set_op = set_op;
997 cpi->delayed_round_info = round_info; 1072 cpi->delayed_round_info = round_info;
998 cpi->exp_subround_finished = GNUNET_YES; 1073 /* The current setop is finished, as we canceled the current setop above. */
1074 cpi->set_op_finished = GNUNET_YES;
999 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d delaying set request from P%d\n", session->local_peer_idx, index); 1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d delaying set request from P%d\n", session->local_peer_idx, index);
1000 } 1076 }
1001 break; 1077 break;
@@ -1242,7 +1318,10 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1242 return; 1318 return;
1243 if ((CONSENSUS_ROUND_BEGIN == session->current_round) || 1319 if ((CONSENSUS_ROUND_BEGIN == session->current_round) ||
1244 (CONSENSUS_ROUND_FINISH == session->current_round)) 1320 (CONSENSUS_ROUND_FINISH == session->current_round))
1321 {
1322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected, destroying session\n");
1245 destroy_session (session); 1323 destroy_session (session);
1324 }
1246 else 1325 else
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected, but waiting for consensus to finish\n"); 1326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected, but waiting for consensus to finish\n");
1248} 1327}
diff --git a/src/consensus/test_consensus.conf b/src/consensus/test_consensus.conf
index a134da9dc..714422879 100644
--- a/src/consensus/test_consensus.conf
+++ b/src/consensus/test_consensus.conf
@@ -4,7 +4,7 @@ PORT = 2110
4HOSTNAME = localhost 4HOSTNAME = localhost
5BINARY = gnunet-service-consensus 5BINARY = gnunet-service-consensus
6#PREFIX = gdbserver :12345 6#PREFIX = gdbserver :12345
7#PREFIX = valgrind --leak-check=full 7#PREFIX = valgrind
8ACCEPT_FROM = 127.0.0.1; 8ACCEPT_FROM = 127.0.0.1;
9ACCEPT_FROM6 = ::1; 9ACCEPT_FROM6 = ::1;
10UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-consensus.sock 10UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-consensus.sock
@@ -23,6 +23,7 @@ DEFAULTSERVICES = core consensus set
23[set] 23[set]
24OPTIONS = -L INFO 24OPTIONS = -L INFO
25#PREFIX = valgrind --leak-check=full 25#PREFIX = valgrind --leak-check=full
26#PREFIX = valgrind
26 27
27 28
28[testbed] 29[testbed]