diff options
Diffstat (limited to 'src/gns/gnunet-service-gns.c')
-rw-r--r-- | src/gns/gnunet-service-gns.c | 238 |
1 files changed, 154 insertions, 84 deletions
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index 2a9d86a8b..ea271e9dd 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c | |||
@@ -46,11 +46,16 @@ | |||
46 | #define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS | 46 | #define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * The upper bound for the zone iteration interval in milliseconds | 49 | * The lower bound for the zone iteration interval |
50 | */ | 50 | */ |
51 | #define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS | 51 | #define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS |
52 | 52 | ||
53 | /** | 53 | /** |
54 | * The upper bound for the zone iteration interval | ||
55 | */ | ||
56 | #define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) | ||
57 | |||
58 | /** | ||
54 | * The default put interval for the zone iteration. In case | 59 | * The default put interval for the zone iteration. In case |
55 | * no option is found | 60 | * no option is found |
56 | */ | 61 | */ |
@@ -401,6 +406,12 @@ dht_put_continuation (void *cls, | |||
401 | } | 406 | } |
402 | else | 407 | else |
403 | next_put_interval = put_interval; | 408 | next_put_interval = put_interval; |
409 | next_put_interval = GNUNET_TIME_relative_min (next_put_interval, | ||
410 | MAXIMUM_ZONE_ITERATION_INTERVAL); | ||
411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
412 | "PUT complete, next PUT in %s!\n", | ||
413 | GNUNET_STRINGS_relative_time_to_string (next_put_interval, | ||
414 | GNUNET_YES)); | ||
404 | 415 | ||
405 | GNUNET_STATISTICS_set (statistics, | 416 | GNUNET_STATISTICS_set (statistics, |
406 | "Current zone iteration interval (ms)", | 417 | "Current zone iteration interval (ms)", |
@@ -509,7 +520,8 @@ perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | |||
509 | label, | 520 | label, |
510 | GNUNET_STRINGS_absolute_time_to_string (expire), | 521 | GNUNET_STRINGS_absolute_time_to_string (expire), |
511 | GNUNET_h2s (&query)); | 522 | GNUNET_h2s (&query)); |
512 | ret = GNUNET_DHT_put (dht_handle, &query, | 523 | ret = GNUNET_DHT_put (dht_handle, |
524 | &query, | ||
513 | DHT_GNS_REPLICATION_LEVEL, | 525 | DHT_GNS_REPLICATION_LEVEL, |
514 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | 526 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, |
515 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | 527 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, |
@@ -524,6 +536,98 @@ perform_dht_put (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | |||
524 | 536 | ||
525 | 537 | ||
526 | /** | 538 | /** |
539 | * We encountered an error in our zone iteration. | ||
540 | */ | ||
541 | static void | ||
542 | zone_iteration_error (void *cls) | ||
543 | { | ||
544 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
545 | "Got disconnected from namestore database, retrying.\n"); | ||
546 | namestore_iter = NULL; | ||
547 | /* We end up here on error/disconnect/shutdown, so potentially | ||
548 | while a zone publish task or a DHT put is still running; hence | ||
549 | we need to cancel those. */ | ||
550 | if (NULL != zone_publish_task) | ||
551 | { | ||
552 | GNUNET_SCHEDULER_cancel (zone_publish_task); | ||
553 | zone_publish_task = NULL; | ||
554 | } | ||
555 | if (NULL != active_put) | ||
556 | { | ||
557 | GNUNET_DHT_put_cancel (active_put); | ||
558 | active_put = NULL; | ||
559 | } | ||
560 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, | ||
561 | NULL); | ||
562 | } | ||
563 | |||
564 | |||
565 | /** | ||
566 | * Zone iteration is completed. | ||
567 | */ | ||
568 | static void | ||
569 | zone_iteration_finished (void *cls) | ||
570 | { | ||
571 | /* we're done with one iteration, calculate when to do the next one */ | ||
572 | namestore_iter = NULL; | ||
573 | last_num_public_records = num_public_records; | ||
574 | first_zone_iteration = GNUNET_NO; | ||
575 | if (0 == num_public_records) | ||
576 | { | ||
577 | /** | ||
578 | * If no records are known (startup) or none present | ||
579 | * we can safely set the interval to the value for a single | ||
580 | * record | ||
581 | */ | ||
582 | put_interval = zone_publish_time_window; | ||
583 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | ||
584 | "No records in namestore database.\n"); | ||
585 | } | ||
586 | else | ||
587 | { | ||
588 | /* If records are present, next publication is based on the minimum | ||
589 | * relative expiration time of the records published divided by 4 | ||
590 | */ | ||
591 | zone_publish_time_window | ||
592 | = GNUNET_TIME_relative_min (GNUNET_TIME_relative_divide (min_relative_record_time, 4), | ||
593 | zone_publish_time_window_default); | ||
594 | put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, | ||
595 | num_public_records); | ||
596 | } | ||
597 | /* reset for next iteration */ | ||
598 | min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL; | ||
599 | put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL, | ||
600 | put_interval); | ||
601 | put_interval = GNUNET_TIME_relative_min (put_interval, | ||
602 | MAXIMUM_ZONE_ITERATION_INTERVAL); | ||
603 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
604 | "Zone iteration finished. Adjusted zone iteration interval to %s\n", | ||
605 | GNUNET_STRINGS_relative_time_to_string (put_interval, | ||
606 | GNUNET_YES)); | ||
607 | GNUNET_STATISTICS_set (statistics, | ||
608 | "Current zone iteration interval (in ms)", | ||
609 | put_interval.rel_value_us / 1000LL, | ||
610 | GNUNET_NO); | ||
611 | GNUNET_STATISTICS_update (statistics, | ||
612 | "Number of zone iterations", | ||
613 | 1, | ||
614 | GNUNET_NO); | ||
615 | GNUNET_STATISTICS_set (statistics, | ||
616 | "Number of public records in DHT", | ||
617 | last_num_public_records, | ||
618 | GNUNET_NO); | ||
619 | GNUNET_assert (NULL == zone_publish_task); | ||
620 | if (0 == num_public_records) | ||
621 | zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval, | ||
622 | &publish_zone_dht_start, | ||
623 | NULL); | ||
624 | else | ||
625 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, | ||
626 | NULL); | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
527 | * Function used to put all records successively into the DHT. | 631 | * Function used to put all records successively into the DHT. |
528 | * | 632 | * |
529 | * @param cls the closure (NULL) | 633 | * @param cls the closure (NULL) |
@@ -542,95 +646,22 @@ put_gns_record (void *cls, | |||
542 | struct GNUNET_GNSRECORD_Data rd_public[rd_count]; | 646 | struct GNUNET_GNSRECORD_Data rd_public[rd_count]; |
543 | unsigned int rd_public_count; | 647 | unsigned int rd_public_count; |
544 | 648 | ||
545 | if ( (NULL == key) && | ||
546 | (NULL == label) && | ||
547 | (0 == rd_count) ) | ||
548 | { | ||
549 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
550 | "Got disconnected from namestore database, retrying.\n"); | ||
551 | namestore_iter = NULL; | ||
552 | if (NULL != zone_publish_task) | ||
553 | { | ||
554 | GNUNET_SCHEDULER_cancel (zone_publish_task); | ||
555 | zone_publish_task = NULL; | ||
556 | } | ||
557 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, | ||
558 | NULL); | ||
559 | return; | ||
560 | } | ||
561 | if (NULL == label) | ||
562 | { | ||
563 | /* we're done with one iteration, calculate when to do the next one */ | ||
564 | namestore_iter = NULL; | ||
565 | last_num_public_records = num_public_records; | ||
566 | first_zone_iteration = GNUNET_NO; | ||
567 | if (0 == num_public_records) | ||
568 | { | ||
569 | /** | ||
570 | * If no records are known (startup) or none present | ||
571 | * we can safely set the interval to the value for a single | ||
572 | * record | ||
573 | */ | ||
574 | put_interval = zone_publish_time_window; | ||
575 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | ||
576 | "No records in namestore database.\n"); | ||
577 | } | ||
578 | else | ||
579 | { | ||
580 | /* If records are present, next publication is based on the minimum | ||
581 | * relative expiration time of the records published divided by 4 | ||
582 | */ | ||
583 | zone_publish_time_window = GNUNET_TIME_relative_min ( | ||
584 | GNUNET_TIME_relative_divide (min_relative_record_time, 4), | ||
585 | zone_publish_time_window_default); | ||
586 | put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, | ||
587 | num_public_records); | ||
588 | } | ||
589 | /* reset for next iteration */ | ||
590 | min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL; | ||
591 | put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL, | ||
592 | put_interval); | ||
593 | |||
594 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
595 | "Zone iteration finished. Adjusted zone iteration interval to %s\n", | ||
596 | GNUNET_STRINGS_relative_time_to_string (put_interval, | ||
597 | GNUNET_YES)); | ||
598 | GNUNET_STATISTICS_set (statistics, | ||
599 | "Current zone iteration interval (in ms)", | ||
600 | put_interval.rel_value_us / 1000LL, | ||
601 | GNUNET_NO); | ||
602 | GNUNET_STATISTICS_update (statistics, | ||
603 | "Number of zone iterations", | ||
604 | 1, | ||
605 | GNUNET_NO); | ||
606 | GNUNET_STATISTICS_set (statistics, | ||
607 | "Number of public records in DHT", | ||
608 | last_num_public_records, | ||
609 | GNUNET_NO); | ||
610 | GNUNET_assert (NULL == zone_publish_task); | ||
611 | if (0 == num_public_records) | ||
612 | zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval, | ||
613 | &publish_zone_dht_start, | ||
614 | NULL); | ||
615 | else | ||
616 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, | ||
617 | NULL); | ||
618 | return; | ||
619 | } | ||
620 | |||
621 | rd_public_count = convert_records_for_export (rd, | 649 | rd_public_count = convert_records_for_export (rd, |
622 | rd_count, | 650 | rd_count, |
623 | rd_public); | 651 | rd_public); |
624 | 652 | ||
625 | /* We got a set of records to publish */ | ||
626 | if (0 == rd_public_count) | 653 | if (0 == rd_public_count) |
627 | { | 654 | { |
628 | GNUNET_assert (NULL == zone_publish_task); | 655 | GNUNET_assert (NULL == zone_publish_task); |
656 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
657 | "Record set empty, moving to next record set\n"); | ||
629 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, | 658 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, |
630 | NULL); | 659 | NULL); |
631 | return; | 660 | return; |
632 | } | 661 | } |
633 | 662 | /* We got a set of records to publish */ | |
663 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
664 | "Starting DHT PUT\n"); | ||
634 | active_put = perform_dht_put (key, | 665 | active_put = perform_dht_put (key, |
635 | label, | 666 | label, |
636 | rd_public, | 667 | rd_public, |
@@ -662,7 +693,11 @@ publish_zone_dht_start (void *cls) | |||
662 | namestore_iter | 693 | namestore_iter |
663 | = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle, | 694 | = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle, |
664 | NULL, /* All zones */ | 695 | NULL, /* All zones */ |
696 | &zone_iteration_error, | ||
697 | NULL, | ||
665 | &put_gns_record, | 698 | &put_gns_record, |
699 | NULL, | ||
700 | &zone_iteration_finished, | ||
666 | NULL); | 701 | NULL); |
667 | } | 702 | } |
668 | 703 | ||
@@ -694,13 +729,16 @@ handle_monitor_event (void *cls, | |||
694 | label); | 729 | label); |
695 | /* filter out records that are not public, and convert to | 730 | /* filter out records that are not public, and convert to |
696 | absolute expiration time. */ | 731 | absolute expiration time. */ |
697 | rd_public_count = convert_records_for_export (rd, rd_count, | 732 | rd_public_count = convert_records_for_export (rd, |
733 | rd_count, | ||
698 | rd_public); | 734 | rd_public); |
699 | if (0 == rd_public_count) | 735 | if (0 == rd_public_count) |
700 | return; /* nothing to do */ | 736 | return; /* nothing to do */ |
701 | ma = GNUNET_new (struct MonitorActivity); | 737 | ma = GNUNET_new (struct MonitorActivity); |
702 | ma->ph = perform_dht_put (zone, label, | 738 | ma->ph = perform_dht_put (zone, |
703 | rd, rd_count, | 739 | label, |
740 | rd, | ||
741 | rd_count, | ||
704 | ma); | 742 | ma); |
705 | if (NULL == ma->ph) | 743 | if (NULL == ma->ph) |
706 | { | 744 | { |
@@ -881,6 +919,35 @@ monitor_sync_event (void *cls) | |||
881 | 919 | ||
882 | 920 | ||
883 | /** | 921 | /** |
922 | * The zone monitor is now in SYNC with the current state of the | ||
923 | * name store. Start to perform periodic iterations. | ||
924 | * | ||
925 | * @param cls NULL | ||
926 | */ | ||
927 | static void | ||
928 | handle_monitor_error (void *cls) | ||
929 | { | ||
930 | if (NULL != zone_publish_task) | ||
931 | { | ||
932 | GNUNET_SCHEDULER_cancel (zone_publish_task); | ||
933 | zone_publish_task = NULL; | ||
934 | } | ||
935 | if (NULL != namestore_iter) | ||
936 | { | ||
937 | GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter); | ||
938 | namestore_iter = NULL; | ||
939 | } | ||
940 | if (NULL != active_put) | ||
941 | { | ||
942 | GNUNET_DHT_put_cancel (active_put); | ||
943 | active_put = NULL; | ||
944 | } | ||
945 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, | ||
946 | NULL); | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
884 | * Method called to inform about the ego to be used for the master zone | 951 | * Method called to inform about the ego to be used for the master zone |
885 | * for DNS interceptions. | 952 | * for DNS interceptions. |
886 | * | 953 | * |
@@ -1032,7 +1099,10 @@ run (void *cls, | |||
1032 | zmon = GNUNET_NAMESTORE_zone_monitor_start (c, | 1099 | zmon = GNUNET_NAMESTORE_zone_monitor_start (c, |
1033 | NULL, | 1100 | NULL, |
1034 | GNUNET_NO, | 1101 | GNUNET_NO, |
1102 | &handle_monitor_error, | ||
1103 | NULL, | ||
1035 | &handle_monitor_event, | 1104 | &handle_monitor_event, |
1105 | NULL, | ||
1036 | &monitor_sync_event, | 1106 | &monitor_sync_event, |
1037 | NULL); | 1107 | NULL); |
1038 | GNUNET_break (NULL != zmon); | 1108 | GNUNET_break (NULL != zmon); |