diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-06-18 10:30:08 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-06-18 10:30:08 +0200 |
commit | 9ae7f13f17e3d04d3ba88862299c8e42541eab47 (patch) | |
tree | 167259c402cd199bcbce49f14d6aae20f41425d8 /src/util | |
parent | 93c332be89c4c65f10b7c4c49b6ed15d91b91884 (diff) | |
download | gnunet-9ae7f13f17e3d04d3ba88862299c8e42541eab47.tar.gz gnunet-9ae7f13f17e3d04d3ba88862299c8e42541eab47.zip |
Introducing GNUNET_Uuid and matching hash map for 128 bit values.
TNG: reducing size of AcknowledgementUUIDPs from 256 bits to 128 bits.
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Makefile.am | 1 | ||||
-rw-r--r-- | src/util/common_logging.c | 393 | ||||
-rw-r--r-- | src/util/container_multiuuidmap.c | 1015 |
3 files changed, 1192 insertions, 217 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 8a99197f8..fe5cc6e72 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am | |||
@@ -78,6 +78,7 @@ libgnunetutil_la_SOURCES = \ | |||
78 | container_meta_data.c \ | 78 | container_meta_data.c \ |
79 | container_multihashmap.c \ | 79 | container_multihashmap.c \ |
80 | container_multishortmap.c \ | 80 | container_multishortmap.c \ |
81 | container_multiuuidmap.c \ | ||
81 | container_multipeermap.c \ | 82 | container_multipeermap.c \ |
82 | container_multihashmap32.c \ | 83 | container_multihashmap32.c \ |
83 | crypto_symmetric.c \ | 84 | crypto_symmetric.c \ |
diff --git a/src/util/common_logging.c b/src/util/common_logging.c index 5052134f8..b5678e5be 100644 --- a/src/util/common_logging.c +++ b/src/util/common_logging.c | |||
@@ -107,7 +107,8 @@ static __thread struct GNUNET_AsyncScopeSave current_async_scope; | |||
107 | * Note that this message maybe truncated to the first BULK_TRACK_SIZE | 107 | * Note that this message maybe truncated to the first BULK_TRACK_SIZE |
108 | * characters, in which case it is NOT 0-terminated! | 108 | * characters, in which case it is NOT 0-terminated! |
109 | */ | 109 | */ |
110 | static GNUNET_THREAD_LOCAL char last_bulk[BULK_TRACK_SIZE] __attribute__ ((nonstring)); | 110 | static GNUNET_THREAD_LOCAL char last_bulk[BULK_TRACK_SIZE] |
111 | __attribute__ ((nonstring)); | ||
111 | 112 | ||
112 | /** | 113 | /** |
113 | * Type of the last bulk message. | 114 | * Type of the last bulk message. |
@@ -211,7 +212,7 @@ struct LogDef | |||
211 | }; | 212 | }; |
212 | 213 | ||
213 | 214 | ||
214 | #if !defined(GNUNET_CULL_LOGGING) | 215 | #if ! defined(GNUNET_CULL_LOGGING) |
215 | /** | 216 | /** |
216 | * Dynamic array of logging definitions | 217 | * Dynamic array of logging definitions |
217 | */ | 218 | */ |
@@ -263,17 +264,17 @@ get_type (const char *log) | |||
263 | { | 264 | { |
264 | if (NULL == log) | 265 | if (NULL == log) |
265 | return GNUNET_ERROR_TYPE_UNSPECIFIED; | 266 | return GNUNET_ERROR_TYPE_UNSPECIFIED; |
266 | if (0 == strcasecmp (log, _("DEBUG"))) | 267 | if (0 == strcasecmp (log, _ ("DEBUG"))) |
267 | return GNUNET_ERROR_TYPE_DEBUG; | 268 | return GNUNET_ERROR_TYPE_DEBUG; |
268 | if (0 == strcasecmp (log, _("INFO"))) | 269 | if (0 == strcasecmp (log, _ ("INFO"))) |
269 | return GNUNET_ERROR_TYPE_INFO; | 270 | return GNUNET_ERROR_TYPE_INFO; |
270 | if (0 == strcasecmp (log, _("MESSAGE"))) | 271 | if (0 == strcasecmp (log, _ ("MESSAGE"))) |
271 | return GNUNET_ERROR_TYPE_MESSAGE; | 272 | return GNUNET_ERROR_TYPE_MESSAGE; |
272 | if (0 == strcasecmp (log, _("WARNING"))) | 273 | if (0 == strcasecmp (log, _ ("WARNING"))) |
273 | return GNUNET_ERROR_TYPE_WARNING; | 274 | return GNUNET_ERROR_TYPE_WARNING; |
274 | if (0 == strcasecmp (log, _("ERROR"))) | 275 | if (0 == strcasecmp (log, _ ("ERROR"))) |
275 | return GNUNET_ERROR_TYPE_ERROR; | 276 | return GNUNET_ERROR_TYPE_ERROR; |
276 | if (0 == strcasecmp (log, _("NONE"))) | 277 | if (0 == strcasecmp (log, _ ("NONE"))) |
277 | return GNUNET_ERROR_TYPE_NONE; | 278 | return GNUNET_ERROR_TYPE_NONE; |
278 | return GNUNET_ERROR_TYPE_INVALID; | 279 | return GNUNET_ERROR_TYPE_INVALID; |
279 | } | 280 | } |
@@ -292,7 +293,7 @@ GNUNET_abort_ () | |||
292 | } | 293 | } |
293 | 294 | ||
294 | 295 | ||
295 | #if !defined(GNUNET_CULL_LOGGING) | 296 | #if ! defined(GNUNET_CULL_LOGGING) |
296 | /** | 297 | /** |
297 | * Utility function - reallocates logdefs array to be twice as large. | 298 | * Utility function - reallocates logdefs array to be twice as large. |
298 | */ | 299 | */ |
@@ -353,7 +354,7 @@ setup_log_file (const struct tm *tm) | |||
353 | if (0 == strftime (fn, sizeof (fn), log_file_name, tm)) | 354 | if (0 == strftime (fn, sizeof (fn), log_file_name, tm)) |
354 | return GNUNET_SYSERR; | 355 | return GNUNET_SYSERR; |
355 | leftsquare = strrchr (fn, '['); | 356 | leftsquare = strrchr (fn, '['); |
356 | if ( (NULL != leftsquare) && (']' == leftsquare[1]) ) | 357 | if ((NULL != leftsquare) && (']' == leftsquare[1])) |
357 | { | 358 | { |
358 | char *logfile_copy = GNUNET_strdup (fn); | 359 | char *logfile_copy = GNUNET_strdup (fn); |
359 | 360 | ||
@@ -371,8 +372,7 @@ setup_log_file (const struct tm *tm) | |||
371 | return GNUNET_OK; /* no change */ | 372 | return GNUNET_OK; /* no change */ |
372 | log_rotate (last_fn); | 373 | log_rotate (last_fn); |
373 | strcpy (last_fn, fn); | 374 | strcpy (last_fn, fn); |
374 | if (GNUNET_SYSERR == | 375 | if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (fn)) |
375 | GNUNET_DISK_directory_create_for_file (fn)) | ||
376 | { | 376 | { |
377 | fprintf (stderr, | 377 | fprintf (stderr, |
378 | "Failed to create directory for `%s': %s\n", | 378 | "Failed to create directory for `%s': %s\n", |
@@ -381,14 +381,12 @@ setup_log_file (const struct tm *tm) | |||
381 | return GNUNET_SYSERR; | 381 | return GNUNET_SYSERR; |
382 | } | 382 | } |
383 | #if WINDOWS | 383 | #if WINDOWS |
384 | altlog_fd = OPEN (fn, O_APPEND | | 384 | altlog_fd = |
385 | O_BINARY | | 385 | OPEN (fn, O_APPEND | O_BINARY | O_WRONLY | O_CREAT, _S_IREAD | _S_IWRITE); |
386 | O_WRONLY | O_CREAT, | ||
387 | _S_IREAD | _S_IWRITE); | ||
388 | #else | 386 | #else |
389 | altlog_fd = OPEN (fn, O_APPEND | | 387 | altlog_fd = OPEN (fn, |
390 | O_WRONLY | O_CREAT, | 388 | O_APPEND | O_WRONLY | O_CREAT, |
391 | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | 389 | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
392 | #endif | 390 | #endif |
393 | if (-1 != altlog_fd) | 391 | if (-1 != altlog_fd) |
394 | { | 392 | { |
@@ -512,7 +510,7 @@ GNUNET_get_log_call_status (int caller_level, | |||
512 | /* We have no definitions to override globally configured log level, | 510 | /* We have no definitions to override globally configured log level, |
513 | * so just use it right away. | 511 | * so just use it right away. |
514 | */ | 512 | */ |
515 | if ( (min_level >= 0) && (GNUNET_NO == gnunet_force_log_present) ) | 513 | if ((min_level >= 0) && (GNUNET_NO == gnunet_force_log_present)) |
516 | return caller_level <= min_level; | 514 | return caller_level <= min_level; |
517 | 515 | ||
518 | /* Only look for forced definitions? */ | 516 | /* Only look for forced definitions? */ |
@@ -520,7 +518,7 @@ GNUNET_get_log_call_status (int caller_level, | |||
520 | for (i = 0; i < logdefs_len; i++) | 518 | for (i = 0; i < logdefs_len; i++) |
521 | { | 519 | { |
522 | ld = &logdefs[i]; | 520 | ld = &logdefs[i]; |
523 | if (( (!force_only) || ld->force) && | 521 | if (((! force_only) || ld->force) && |
524 | (line >= ld->from_line && line <= ld->to_line) && | 522 | (line >= ld->from_line && line <= ld->to_line) && |
525 | (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) && | 523 | (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) && |
526 | (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) && | 524 | (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) && |
@@ -591,73 +589,79 @@ parse_definitions (const char *constname, int force) | |||
591 | { | 589 | { |
592 | switch (p[0]) | 590 | switch (p[0]) |
593 | { | 591 | { |
594 | case ';': /* found a field separator */ | 592 | case ';': /* found a field separator */ |
595 | p[0] = '\0'; | 593 | p[0] = '\0'; |
596 | switch (state) | 594 | switch (state) |
597 | { | 595 | { |
598 | case 0: /* within a component name */ | 596 | case 0: /* within a component name */ |
599 | comp = start; | 597 | comp = start; |
600 | break; | 598 | break; |
601 | case 1: /* within a file name */ | 599 | case 1: /* within a file name */ |
602 | file = start; | 600 | file = start; |
603 | break; | 601 | break; |
604 | case 2: /* within a function name */ | 602 | case 2: /* within a function name */ |
605 | /* after a file name there must be a function name */ | 603 | /* after a file name there must be a function name */ |
606 | function = start; | 604 | function = start; |
607 | break; | 605 | break; |
608 | case 3: /* within a from-to line range */ | 606 | case 3: /* within a from-to line range */ |
609 | if (strlen (start) > 0) | 607 | if (strlen (start) > 0) |
610 | { | 608 | { |
611 | errno = 0; | 609 | errno = 0; |
612 | from_line = strtol (start, &t, 10); | 610 | from_line = strtol (start, &t, 10); |
613 | if ( (0 != errno) || (from_line < 0) ) | 611 | if ((0 != errno) || (from_line < 0)) |
614 | { | 612 | { |
615 | GNUNET_free (def); | 613 | GNUNET_free (def); |
616 | return counter; | 614 | return counter; |
617 | } | 615 | } |
618 | if ( (t < p) && ('-' == t[0]) ) | 616 | if ((t < p) && ('-' == t[0])) |
619 | { | 617 | { |
620 | errno = 0; | 618 | errno = 0; |
621 | start = t + 1; | 619 | start = t + 1; |
622 | to_line = strtol (start, &t, 10); | 620 | to_line = strtol (start, &t, 10); |
623 | if ( (0 != errno) || (to_line < 0) || (t != p) ) | 621 | if ((0 != errno) || (to_line < 0) || (t != p)) |
624 | { | 622 | { |
625 | GNUNET_free (def); | 623 | GNUNET_free (def); |
626 | return counter; | 624 | return counter; |
627 | } | 625 | } |
628 | } | 626 | } |
629 | else /* one number means "match this line only" */ | 627 | else /* one number means "match this line only" */ |
630 | to_line = from_line; | 628 | to_line = from_line; |
631 | } | 629 | } |
632 | else /* default to 0-max */ | 630 | else /* default to 0-max */ |
633 | { | 631 | { |
634 | from_line = 0; | 632 | from_line = 0; |
635 | to_line = INT_MAX; | 633 | to_line = INT_MAX; |
636 | } | 634 | } |
637 | break; | 635 | break; |
638 | default: | 636 | default: |
639 | fprintf(stderr, | 637 | fprintf ( |
640 | _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"), | 638 | stderr, |
641 | p); | 639 | _ ("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"), |
640 | p); | ||
642 | break; | 641 | break; |
643 | } | 642 | } |
644 | start = p + 1; | 643 | start = p + 1; |
645 | state++; | 644 | state++; |
646 | break; | 645 | break; |
647 | case '\0': /* found EOL */ | 646 | case '\0': /* found EOL */ |
648 | keep_looking = 0; | 647 | keep_looking = 0; |
649 | /* fall through to '/' */ | 648 | /* fall through to '/' */ |
650 | case '/': /* found a definition separator */ | 649 | case '/': /* found a definition separator */ |
651 | switch (state) | 650 | switch (state) |
652 | { | 651 | { |
653 | case 4: /* within a log level */ | 652 | case 4: /* within a log level */ |
654 | p[0] = '\0'; | 653 | p[0] = '\0'; |
655 | state = 0; | 654 | state = 0; |
656 | level = get_type ((const char *) start); | 655 | level = get_type ((const char *) start); |
657 | if ( (GNUNET_ERROR_TYPE_INVALID == level) || | 656 | if ((GNUNET_ERROR_TYPE_INVALID == level) || |
658 | (GNUNET_ERROR_TYPE_UNSPECIFIED == level) || | 657 | (GNUNET_ERROR_TYPE_UNSPECIFIED == level) || |
659 | (0 != add_definition (comp, file, function, from_line, to_line, | 658 | (0 != add_definition (comp, |
660 | level, force)) ) | 659 | file, |
660 | function, | ||
661 | from_line, | ||
662 | to_line, | ||
663 | level, | ||
664 | force))) | ||
661 | { | 665 | { |
662 | GNUNET_free (def); | 666 | GNUNET_free (def); |
663 | return counter; | 667 | return counter; |
@@ -666,9 +670,10 @@ parse_definitions (const char *constname, int force) | |||
666 | start = p + 1; | 670 | start = p + 1; |
667 | break; | 671 | break; |
668 | default: | 672 | default: |
669 | fprintf(stderr, | 673 | fprintf ( |
670 | _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"), | 674 | stderr, |
671 | p); | 675 | _ ("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"), |
676 | p); | ||
672 | break; | 677 | break; |
673 | } | 678 | } |
674 | default: | 679 | default: |
@@ -688,7 +693,7 @@ parse_all_definitions () | |||
688 | { | 693 | { |
689 | if (GNUNET_NO == gnunet_force_log_parsed) | 694 | if (GNUNET_NO == gnunet_force_log_parsed) |
690 | gnunet_force_log_present = | 695 | gnunet_force_log_present = |
691 | parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO; | 696 | parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO; |
692 | gnunet_force_log_parsed = GNUNET_YES; | 697 | gnunet_force_log_parsed = GNUNET_YES; |
693 | 698 | ||
694 | if (GNUNET_NO == gnunet_log_parsed) | 699 | if (GNUNET_NO == gnunet_log_parsed) |
@@ -707,14 +712,12 @@ parse_all_definitions () | |||
707 | * @return #GNUNET_OK on success | 712 | * @return #GNUNET_OK on success |
708 | */ | 713 | */ |
709 | int | 714 | int |
710 | GNUNET_log_setup (const char *comp, | 715 | GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile) |
711 | const char *loglevel, | ||
712 | const char *logfile) | ||
713 | { | 716 | { |
714 | const char *env_logfile; | 717 | const char *env_logfile; |
715 | 718 | ||
716 | min_level = get_type (loglevel); | 719 | min_level = get_type (loglevel); |
717 | #if !defined(GNUNET_CULL_LOGGING) | 720 | #if ! defined(GNUNET_CULL_LOGGING) |
718 | parse_all_definitions (); | 721 | parse_all_definitions (); |
719 | #endif | 722 | #endif |
720 | #ifdef WINDOWS | 723 | #ifdef WINDOWS |
@@ -761,8 +764,7 @@ GNUNET_log_setup (const char *comp, | |||
761 | * @param logger_cls closure for @a logger | 764 | * @param logger_cls closure for @a logger |
762 | */ | 765 | */ |
763 | void | 766 | void |
764 | GNUNET_logger_add (GNUNET_Logger logger, | 767 | GNUNET_logger_add (GNUNET_Logger logger, void *logger_cls) |
765 | void *logger_cls) | ||
766 | { | 768 | { |
767 | struct CustomLogger *entry; | 769 | struct CustomLogger *entry; |
768 | 770 | ||
@@ -781,8 +783,7 @@ GNUNET_logger_add (GNUNET_Logger logger, | |||
781 | * @param logger_cls closure for @a logger | 783 | * @param logger_cls closure for @a logger |
782 | */ | 784 | */ |
783 | void | 785 | void |
784 | GNUNET_logger_remove (GNUNET_Logger logger, | 786 | GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls) |
785 | void *logger_cls) | ||
786 | { | 787 | { |
787 | struct CustomLogger *pos; | 788 | struct CustomLogger *pos; |
788 | struct CustomLogger *prev; | 789 | struct CustomLogger *prev; |
@@ -828,8 +829,7 @@ output_message (enum GNUNET_ErrorType kind, | |||
828 | EnterCriticalSection (&output_message_cs); | 829 | EnterCriticalSection (&output_message_cs); |
829 | #endif | 830 | #endif |
830 | /* only use the standard logger if no custom loggers are present */ | 831 | /* only use the standard logger if no custom loggers are present */ |
831 | if ( (NULL != GNUNET_stderr) && | 832 | if ((NULL != GNUNET_stderr) && (NULL == loggers)) |
832 | (NULL == loggers) ) | ||
833 | { | 833 | { |
834 | if (kind == GNUNET_ERROR_TYPE_MESSAGE) | 834 | if (kind == GNUNET_ERROR_TYPE_MESSAGE) |
835 | { | 835 | { |
@@ -841,9 +841,7 @@ output_message (enum GNUNET_ErrorType kind, | |||
841 | * this way if the output is going to logfiles or robots | 841 | * this way if the output is going to logfiles or robots |
842 | * instead. | 842 | * instead. |
843 | */ | 843 | */ |
844 | FPRINTF (GNUNET_stderr, | 844 | FPRINTF (GNUNET_stderr, "* %s", msg); |
845 | "* %s", | ||
846 | msg); | ||
847 | } | 845 | } |
848 | else if (GNUNET_YES == current_async_scope.have_scope) | 846 | else if (GNUNET_YES == current_async_scope.have_scope) |
849 | { | 847 | { |
@@ -881,11 +879,7 @@ output_message (enum GNUNET_ErrorType kind, | |||
881 | pos = loggers; | 879 | pos = loggers; |
882 | while (NULL != pos) | 880 | while (NULL != pos) |
883 | { | 881 | { |
884 | pos->logger (pos->logger_cls, | 882 | pos->logger (pos->logger_cls, kind, comp, datestr, msg); |
885 | kind, | ||
886 | comp, | ||
887 | datestr, | ||
888 | msg); | ||
889 | pos = pos->next; | 883 | pos = pos->next; |
890 | } | 884 | } |
891 | #if WINDOWS | 885 | #if WINDOWS |
@@ -907,8 +901,7 @@ flush_bulk (const char *datestr) | |||
907 | char *last; | 901 | char *last; |
908 | const char *ft; | 902 | const char *ft; |
909 | 903 | ||
910 | if ( (0 == last_bulk_time.abs_value_us) || | 904 | if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat)) |
911 | (0 == last_bulk_repeat) ) | ||
912 | return; | 905 | return; |
913 | rev = 0; | 906 | rev = 0; |
914 | last = memchr (last_bulk, '\0', BULK_TRACK_SIZE); | 907 | last = memchr (last_bulk, '\0', BULK_TRACK_SIZE); |
@@ -921,11 +914,17 @@ flush_bulk (const char *datestr) | |||
921 | rev = 1; | 914 | rev = 1; |
922 | last[0] = '\0'; | 915 | last[0] = '\0'; |
923 | } | 916 | } |
924 | ft = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration | 917 | ft = |
925 | (last_bulk_time), GNUNET_YES); | 918 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration ( |
926 | snprintf (msg, sizeof (msg), | 919 | last_bulk_time), |
927 | _("Message `%.*s' repeated %u times in the last %s\n"), | 920 | GNUNET_YES); |
928 | BULK_TRACK_SIZE, last_bulk, last_bulk_repeat, ft); | 921 | snprintf (msg, |
922 | sizeof (msg), | ||
923 | _ ("Message `%.*s' repeated %u times in the last %s\n"), | ||
924 | BULK_TRACK_SIZE, | ||
925 | last_bulk, | ||
926 | last_bulk_repeat, | ||
927 | ft); | ||
929 | if (rev == 1) | 928 | if (rev == 1) |
930 | last[0] = '\n'; | 929 | last[0] = '\n'; |
931 | output_message (last_bulk_kind, last_bulk_comp, datestr, msg); | 930 | output_message (last_bulk_kind, last_bulk_comp, datestr, msg); |
@@ -941,8 +940,7 @@ flush_bulk (const char *datestr) | |||
941 | * @param check_reset #GNUNET_YES to assert that the log skip counter is currently zero | 940 | * @param check_reset #GNUNET_YES to assert that the log skip counter is currently zero |
942 | */ | 941 | */ |
943 | void | 942 | void |
944 | GNUNET_log_skip (int n, | 943 | GNUNET_log_skip (int n, int check_reset) |
945 | int check_reset) | ||
946 | { | 944 | { |
947 | int ok; | 945 | int ok; |
948 | 946 | ||
@@ -993,15 +991,10 @@ mylog (enum GNUNET_ErrorType kind, | |||
993 | va_list vacp; | 991 | va_list vacp; |
994 | 992 | ||
995 | va_copy (vacp, va); | 993 | va_copy (vacp, va); |
996 | size = VSNPRINTF (NULL, | 994 | size = VSNPRINTF (NULL, 0, message, vacp) + 1; |
997 | 0, | ||
998 | message, | ||
999 | vacp) + 1; | ||
1000 | GNUNET_assert (0 != size); | 995 | GNUNET_assert (0 != size); |
1001 | va_end (vacp); | 996 | va_end (vacp); |
1002 | memset (date, | 997 | memset (date, 0, DATE_STR_SIZE); |
1003 | 0, | ||
1004 | DATE_STR_SIZE); | ||
1005 | { | 998 | { |
1006 | char buf[size]; | 999 | char buf[size]; |
1007 | long long offset; | 1000 | long long offset; |
@@ -1022,24 +1015,19 @@ mylog (enum GNUNET_ErrorType kind, | |||
1022 | else | 1015 | else |
1023 | { | 1016 | { |
1024 | if (0 == | 1017 | if (0 == |
1025 | strftime (date2, | 1018 | strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%020llu", tmptr)) |
1026 | DATE_STR_SIZE, | 1019 | abort (); |
1027 | "%b %d %H:%M:%S-%%020llu", | 1020 | if (0 > snprintf (date, |
1028 | tmptr)) | 1021 | sizeof (date), |
1029 | abort (); | 1022 | date2, |
1030 | if (0 > | 1023 | (long long) (pc.QuadPart / |
1031 | snprintf (date, | 1024 | (performance_frequency.QuadPart / 1000)))) |
1032 | sizeof (date), | 1025 | abort (); |
1033 | date2, | ||
1034 | (long long) (pc.QuadPart / | ||
1035 | (performance_frequency.QuadPart / 1000)))) | ||
1036 | abort (); | ||
1037 | } | 1026 | } |
1038 | #else | 1027 | #else |
1039 | struct timeval timeofday; | 1028 | struct timeval timeofday; |
1040 | 1029 | ||
1041 | gettimeofday (&timeofday, | 1030 | gettimeofday (&timeofday, NULL); |
1042 | NULL); | ||
1043 | offset = GNUNET_TIME_get_offset (); | 1031 | offset = GNUNET_TIME_get_offset (); |
1044 | if (offset > 0) | 1032 | if (offset > 0) |
1045 | { | 1033 | { |
@@ -1047,80 +1035,59 @@ mylog (enum GNUNET_ErrorType kind, | |||
1047 | timeofday.tv_usec += (offset % 1000LL) * 1000LL; | 1035 | timeofday.tv_usec += (offset % 1000LL) * 1000LL; |
1048 | if (timeofday.tv_usec > 1000000LL) | 1036 | if (timeofday.tv_usec > 1000000LL) |
1049 | { | 1037 | { |
1050 | timeofday.tv_usec -= 1000000LL; | 1038 | timeofday.tv_usec -= 1000000LL; |
1051 | timeofday.tv_sec++; | 1039 | timeofday.tv_sec++; |
1052 | } | 1040 | } |
1053 | } | 1041 | } |
1054 | else | 1042 | else |
1055 | { | 1043 | { |
1056 | timeofday.tv_sec += offset / 1000LL; | 1044 | timeofday.tv_sec += offset / 1000LL; |
1057 | if (timeofday.tv_usec > - (offset % 1000LL) * 1000LL) | 1045 | if (timeofday.tv_usec > -(offset % 1000LL) * 1000LL) |
1058 | { | 1046 | { |
1059 | timeofday.tv_usec += (offset % 1000LL) * 1000LL; | 1047 | timeofday.tv_usec += (offset % 1000LL) * 1000LL; |
1060 | } | 1048 | } |
1061 | else | 1049 | else |
1062 | { | 1050 | { |
1063 | timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL; | 1051 | timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL; |
1064 | timeofday.tv_sec--; | 1052 | timeofday.tv_sec--; |
1065 | } | 1053 | } |
1066 | } | 1054 | } |
1067 | tmptr = localtime (&timeofday.tv_sec); | 1055 | tmptr = localtime (&timeofday.tv_sec); |
1068 | if (NULL == tmptr) | 1056 | if (NULL == tmptr) |
1069 | { | 1057 | { |
1070 | strcpy (date, | 1058 | strcpy (date, "localtime error"); |
1071 | "localtime error"); | ||
1072 | } | 1059 | } |
1073 | else | 1060 | else |
1074 | { | 1061 | { |
1075 | if (0 == | 1062 | if (0 == strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr)) |
1076 | strftime (date2, | 1063 | abort (); |
1077 | DATE_STR_SIZE, | 1064 | if (0 > snprintf (date, sizeof (date), date2, timeofday.tv_usec)) |
1078 | "%b %d %H:%M:%S-%%06u", | 1065 | abort (); |
1079 | tmptr)) | ||
1080 | abort (); | ||
1081 | if (0 > | ||
1082 | snprintf (date, | ||
1083 | sizeof (date), | ||
1084 | date2, | ||
1085 | timeofday.tv_usec)) | ||
1086 | abort (); | ||
1087 | } | 1066 | } |
1088 | #endif | 1067 | #endif |
1089 | VSNPRINTF (buf, | 1068 | VSNPRINTF (buf, size, message, va); |
1090 | size, | ||
1091 | message, | ||
1092 | va); | ||
1093 | #if ! (defined(GNUNET_CULL_LOGGING) || TALER_WALLET_ONLY) | 1069 | #if ! (defined(GNUNET_CULL_LOGGING) || TALER_WALLET_ONLY) |
1094 | if (NULL != tmptr) | 1070 | if (NULL != tmptr) |
1095 | (void) setup_log_file (tmptr); | 1071 | (void) setup_log_file (tmptr); |
1096 | #endif | 1072 | #endif |
1097 | if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) && | 1073 | if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) && |
1098 | (0 != last_bulk_time.abs_value_us) && | 1074 | (0 != last_bulk_time.abs_value_us) && |
1099 | (0 == strncmp (buf, | 1075 | (0 == strncmp (buf, last_bulk, sizeof (last_bulk)))) |
1100 | last_bulk, | ||
1101 | sizeof (last_bulk)))) | ||
1102 | { | 1076 | { |
1103 | last_bulk_repeat++; | 1077 | last_bulk_repeat++; |
1104 | if ( (GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value_us > | 1078 | if ((GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value_us > |
1105 | BULK_DELAY_THRESHOLD) || | 1079 | BULK_DELAY_THRESHOLD) || |
1106 | (last_bulk_repeat > BULK_REPEAT_THRESHOLD) ) | 1080 | (last_bulk_repeat > BULK_REPEAT_THRESHOLD)) |
1107 | flush_bulk (date); | 1081 | flush_bulk (date); |
1108 | return; | 1082 | return; |
1109 | } | 1083 | } |
1110 | flush_bulk (date); | 1084 | flush_bulk (date); |
1111 | strncpy (last_bulk, | 1085 | strncpy (last_bulk, buf, sizeof (last_bulk)); |
1112 | buf, | ||
1113 | sizeof (last_bulk)); | ||
1114 | last_bulk_repeat = 0; | 1086 | last_bulk_repeat = 0; |
1115 | last_bulk_kind = kind; | 1087 | last_bulk_kind = kind; |
1116 | last_bulk_time = GNUNET_TIME_absolute_get (); | 1088 | last_bulk_time = GNUNET_TIME_absolute_get (); |
1117 | strncpy (last_bulk_comp, | 1089 | strncpy (last_bulk_comp, comp, COMP_TRACK_SIZE); |
1118 | comp, | 1090 | output_message (kind, comp, date, buf); |
1119 | COMP_TRACK_SIZE); | ||
1120 | output_message (kind, | ||
1121 | comp, | ||
1122 | date, | ||
1123 | buf); | ||
1124 | } | 1091 | } |
1125 | } | 1092 | } |
1126 | 1093 | ||
@@ -1133,8 +1100,7 @@ mylog (enum GNUNET_ErrorType kind, | |||
1133 | * @param ... arguments for format string | 1100 | * @param ... arguments for format string |
1134 | */ | 1101 | */ |
1135 | void | 1102 | void |
1136 | GNUNET_log_nocheck (enum GNUNET_ErrorType kind, | 1103 | GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...) |
1137 | const char *message, ...) | ||
1138 | { | 1104 | { |
1139 | va_list va; | 1105 | va_list va; |
1140 | 1106 | ||
@@ -1154,8 +1120,10 @@ GNUNET_log_nocheck (enum GNUNET_ErrorType kind, | |||
1154 | * @param ... arguments for format string | 1120 | * @param ... arguments for format string |
1155 | */ | 1121 | */ |
1156 | void | 1122 | void |
1157 | GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp, | 1123 | GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, |
1158 | const char *message, ...) | 1124 | const char *comp, |
1125 | const char *message, | ||
1126 | ...) | ||
1159 | { | 1127 | { |
1160 | va_list va; | 1128 | va_list va; |
1161 | char comp_w_pid[128]; | 1129 | char comp_w_pid[128]; |
@@ -1180,18 +1148,18 @@ const char * | |||
1180 | GNUNET_error_type_to_string (enum GNUNET_ErrorType kind) | 1148 | GNUNET_error_type_to_string (enum GNUNET_ErrorType kind) |
1181 | { | 1149 | { |
1182 | if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0) | 1150 | if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0) |
1183 | return _("ERROR"); | 1151 | return _ ("ERROR"); |
1184 | if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0) | 1152 | if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0) |
1185 | return _("WARNING"); | 1153 | return _ ("WARNING"); |
1186 | if ((kind & GNUNET_ERROR_TYPE_MESSAGE) > 0) | 1154 | if ((kind & GNUNET_ERROR_TYPE_MESSAGE) > 0) |
1187 | return _("MESSAGE"); | 1155 | return _ ("MESSAGE"); |
1188 | if ((kind & GNUNET_ERROR_TYPE_INFO) > 0) | 1156 | if ((kind & GNUNET_ERROR_TYPE_INFO) > 0) |
1189 | return _("INFO"); | 1157 | return _ ("INFO"); |
1190 | if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0) | 1158 | if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0) |
1191 | return _("DEBUG"); | 1159 | return _ ("DEBUG"); |
1192 | if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0) | 1160 | if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0) |
1193 | return _("NONE"); | 1161 | return _ ("NONE"); |
1194 | return _("INVALID"); | 1162 | return _ ("INVALID"); |
1195 | } | 1163 | } |
1196 | 1164 | ||
1197 | 1165 | ||
@@ -1202,7 +1170,7 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind) | |||
1202 | * @return string form; will be overwritten by next call to GNUNET_h2s. | 1170 | * @return string form; will be overwritten by next call to GNUNET_h2s. |
1203 | */ | 1171 | */ |
1204 | const char * | 1172 | const char * |
1205 | GNUNET_h2s (const struct GNUNET_HashCode * hc) | 1173 | GNUNET_h2s (const struct GNUNET_HashCode *hc) |
1206 | { | 1174 | { |
1207 | static GNUNET_THREAD_LOCAL struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1175 | static GNUNET_THREAD_LOCAL struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1208 | 1176 | ||
@@ -1223,7 +1191,7 @@ GNUNET_h2s (const struct GNUNET_HashCode * hc) | |||
1223 | * @return string form; will be overwritten by next call to GNUNET_h2s. | 1191 | * @return string form; will be overwritten by next call to GNUNET_h2s. |
1224 | */ | 1192 | */ |
1225 | const char * | 1193 | const char * |
1226 | GNUNET_h2s2 (const struct GNUNET_HashCode * hc) | 1194 | GNUNET_h2s2 (const struct GNUNET_HashCode *hc) |
1227 | { | 1195 | { |
1228 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1196 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1229 | 1197 | ||
@@ -1248,11 +1216,8 @@ GNUNET_p2s (const struct GNUNET_CRYPTO_EddsaPublicKey *p) | |||
1248 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1216 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1249 | struct GNUNET_HashCode hc; | 1217 | struct GNUNET_HashCode hc; |
1250 | 1218 | ||
1251 | GNUNET_CRYPTO_hash (p, | 1219 | GNUNET_CRYPTO_hash (p, sizeof (*p), &hc); |
1252 | sizeof (*p), | 1220 | GNUNET_CRYPTO_hash_to_enc (&hc, &ret); |
1253 | &hc); | ||
1254 | GNUNET_CRYPTO_hash_to_enc (&hc, | ||
1255 | &ret); | ||
1256 | ret.encoding[6] = '\0'; | 1221 | ret.encoding[6] = '\0'; |
1257 | return (const char *) ret.encoding; | 1222 | return (const char *) ret.encoding; |
1258 | } | 1223 | } |
@@ -1273,11 +1238,8 @@ GNUNET_p2s2 (const struct GNUNET_CRYPTO_EddsaPublicKey *p) | |||
1273 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1238 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1274 | struct GNUNET_HashCode hc; | 1239 | struct GNUNET_HashCode hc; |
1275 | 1240 | ||
1276 | GNUNET_CRYPTO_hash (p, | 1241 | GNUNET_CRYPTO_hash (p, sizeof (*p), &hc); |
1277 | sizeof (*p), | 1242 | GNUNET_CRYPTO_hash_to_enc (&hc, &ret); |
1278 | &hc); | ||
1279 | GNUNET_CRYPTO_hash_to_enc (&hc, | ||
1280 | &ret); | ||
1281 | ret.encoding[6] = '\0'; | 1243 | ret.encoding[6] = '\0'; |
1282 | return (const char *) ret.encoding; | 1244 | return (const char *) ret.encoding; |
1283 | } | 1245 | } |
@@ -1298,11 +1260,8 @@ GNUNET_e2s (const struct GNUNET_CRYPTO_EcdhePublicKey *p) | |||
1298 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1260 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1299 | struct GNUNET_HashCode hc; | 1261 | struct GNUNET_HashCode hc; |
1300 | 1262 | ||
1301 | GNUNET_CRYPTO_hash (p, | 1263 | GNUNET_CRYPTO_hash (p, sizeof (*p), &hc); |
1302 | sizeof (*p), | 1264 | GNUNET_CRYPTO_hash_to_enc (&hc, &ret); |
1303 | &hc); | ||
1304 | GNUNET_CRYPTO_hash_to_enc (&hc, | ||
1305 | &ret); | ||
1306 | ret.encoding[6] = '\0'; | 1265 | ret.encoding[6] = '\0'; |
1307 | return (const char *) ret.encoding; | 1266 | return (const char *) ret.encoding; |
1308 | } | 1267 | } |
@@ -1323,11 +1282,8 @@ GNUNET_e2s2 (const struct GNUNET_CRYPTO_EcdhePublicKey *p) | |||
1323 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1282 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1324 | struct GNUNET_HashCode hc; | 1283 | struct GNUNET_HashCode hc; |
1325 | 1284 | ||
1326 | GNUNET_CRYPTO_hash (p, | 1285 | GNUNET_CRYPTO_hash (p, sizeof (*p), &hc); |
1327 | sizeof (*p), | 1286 | GNUNET_CRYPTO_hash_to_enc (&hc, &ret); |
1328 | &hc); | ||
1329 | GNUNET_CRYPTO_hash_to_enc (&hc, | ||
1330 | &ret); | ||
1331 | ret.encoding[6] = '\0'; | 1287 | ret.encoding[6] = '\0'; |
1332 | return (const char *) ret.encoding; | 1288 | return (const char *) ret.encoding; |
1333 | } | 1289 | } |
@@ -1347,10 +1303,27 @@ GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc) | |||
1347 | { | 1303 | { |
1348 | static char buf[64]; | 1304 | static char buf[64]; |
1349 | 1305 | ||
1350 | GNUNET_STRINGS_data_to_string (shc, | 1306 | GNUNET_STRINGS_data_to_string (shc, sizeof (*shc), buf, sizeof (buf)); |
1351 | sizeof (*shc), | 1307 | buf[6] = '\0'; |
1352 | buf, | 1308 | return (const char *) buf; |
1353 | sizeof (buf)); | 1309 | } |
1310 | |||
1311 | |||
1312 | /** | ||
1313 | * @ingroup logging | ||
1314 | * Convert a UUID to a string (for printing debug messages). | ||
1315 | * This is one of the very few calls in the entire API that is | ||
1316 | * NOT reentrant! | ||
1317 | * | ||
1318 | * @param uuid the UUID | ||
1319 | * @return string | ||
1320 | */ | ||
1321 | const char * | ||
1322 | GNUNET_uuid2s (const struct GNUNET_Uuid *uuid) | ||
1323 | { | ||
1324 | static char buf[32]; | ||
1325 | |||
1326 | GNUNET_STRINGS_data_to_string (uuid, sizeof (*uuid), buf, sizeof (buf)); | ||
1354 | buf[6] = '\0'; | 1327 | buf[6] = '\0'; |
1355 | return (const char *) buf; | 1328 | return (const char *) buf; |
1356 | } | 1329 | } |
@@ -1365,7 +1338,7 @@ GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc) | |||
1365 | * @return string form; will be overwritten by next call to GNUNET_h2s_full. | 1338 | * @return string form; will be overwritten by next call to GNUNET_h2s_full. |
1366 | */ | 1339 | */ |
1367 | const char * | 1340 | const char * |
1368 | GNUNET_h2s_full (const struct GNUNET_HashCode * hc) | 1341 | GNUNET_h2s_full (const struct GNUNET_HashCode *hc) |
1369 | { | 1342 | { |
1370 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; | 1343 | static struct GNUNET_CRYPTO_HashAsciiEncoded ret; |
1371 | 1344 | ||
@@ -1391,9 +1364,7 @@ GNUNET_i2s (const struct GNUNET_PeerIdentity *pid) | |||
1391 | if (NULL == pid) | 1364 | if (NULL == pid) |
1392 | return "NULL"; | 1365 | return "NULL"; |
1393 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key); | 1366 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key); |
1394 | strncpy (buf, | 1367 | strncpy (buf, ret, sizeof (buf) - 1); |
1395 | ret, | ||
1396 | sizeof (buf) - 1); | ||
1397 | GNUNET_free (ret); | 1368 | GNUNET_free (ret); |
1398 | buf[4] = '\0'; | 1369 | buf[4] = '\0'; |
1399 | return buf; | 1370 | return buf; |
@@ -1419,9 +1390,7 @@ GNUNET_i2s2 (const struct GNUNET_PeerIdentity *pid) | |||
1419 | if (NULL == pid) | 1390 | if (NULL == pid) |
1420 | return "NULL"; | 1391 | return "NULL"; |
1421 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key); | 1392 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key); |
1422 | strncpy (buf, | 1393 | strncpy (buf, ret, sizeof (buf) - 1); |
1423 | ret, | ||
1424 | sizeof (buf) - 1); | ||
1425 | GNUNET_free (ret); | 1394 | GNUNET_free (ret); |
1426 | buf[4] = '\0'; | 1395 | buf[4] = '\0'; |
1427 | return buf; | 1396 | return buf; |
@@ -1459,12 +1428,12 @@ GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid) | |||
1459 | * will be overwritten by next call to #GNUNET_a2s. | 1428 | * will be overwritten by next call to #GNUNET_a2s. |
1460 | */ | 1429 | */ |
1461 | const char * | 1430 | const char * |
1462 | GNUNET_a2s (const struct sockaddr *addr, | 1431 | GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen) |
1463 | socklen_t addrlen) | ||
1464 | { | 1432 | { |
1465 | #ifndef WINDOWS | 1433 | #ifndef WINDOWS |
1466 | #define LEN GNUNET_MAX ((INET6_ADDRSTRLEN + 8), \ | 1434 | #define LEN \ |
1467 | (1 + sizeof (struct sockaddr_un) - sizeof (sa_family_t))) | 1435 | GNUNET_MAX ((INET6_ADDRSTRLEN + 8), \ |
1436 | (1 + sizeof (struct sockaddr_un) - sizeof (sa_family_t))) | ||
1468 | #else | 1437 | #else |
1469 | #define LEN (INET6_ADDRSTRLEN + 8) | 1438 | #define LEN (INET6_ADDRSTRLEN + 8) |
1470 | #endif | 1439 | #endif |
@@ -1477,24 +1446,18 @@ GNUNET_a2s (const struct sockaddr *addr, | |||
1477 | unsigned int off; | 1446 | unsigned int off; |
1478 | 1447 | ||
1479 | if (addr == NULL) | 1448 | if (addr == NULL) |
1480 | return _("unknown address"); | 1449 | return _ ("unknown address"); |
1481 | switch (addr->sa_family) | 1450 | switch (addr->sa_family) |
1482 | { | 1451 | { |
1483 | case AF_INET: | 1452 | case AF_INET: |
1484 | if (addrlen != sizeof (struct sockaddr_in)) | 1453 | if (addrlen != sizeof (struct sockaddr_in)) |
1485 | return "<invalid v4 address>"; | 1454 | return "<invalid v4 address>"; |
1486 | v4 = (const struct sockaddr_in *) addr; | 1455 | v4 = (const struct sockaddr_in *) addr; |
1487 | inet_ntop (AF_INET, | 1456 | inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN); |
1488 | &v4->sin_addr, | ||
1489 | buf, | ||
1490 | INET_ADDRSTRLEN); | ||
1491 | if (0 == ntohs (v4->sin_port)) | 1457 | if (0 == ntohs (v4->sin_port)) |
1492 | return buf; | 1458 | return buf; |
1493 | strcat (buf, ":"); | 1459 | strcat (buf, ":"); |
1494 | GNUNET_snprintf (b2, | 1460 | GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v4->sin_port)); |
1495 | sizeof (b2), | ||
1496 | "%u", | ||
1497 | ntohs (v4->sin_port)); | ||
1498 | strcat (buf, b2); | 1461 | strcat (buf, b2); |
1499 | return buf; | 1462 | return buf; |
1500 | case AF_INET6: | 1463 | case AF_INET6: |
@@ -1502,19 +1465,12 @@ GNUNET_a2s (const struct sockaddr *addr, | |||
1502 | return "<invalid v4 address>"; | 1465 | return "<invalid v4 address>"; |
1503 | v6 = (const struct sockaddr_in6 *) addr; | 1466 | v6 = (const struct sockaddr_in6 *) addr; |
1504 | buf[0] = '['; | 1467 | buf[0] = '['; |
1505 | inet_ntop (AF_INET6, | 1468 | inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN); |
1506 | &v6->sin6_addr, | ||
1507 | &buf[1], | ||
1508 | INET6_ADDRSTRLEN); | ||
1509 | if (0 == ntohs (v6->sin6_port)) | 1469 | if (0 == ntohs (v6->sin6_port)) |
1510 | return &buf[1]; | 1470 | return &buf[1]; |
1511 | strcat (buf, "]:"); | 1471 | strcat (buf, "]:"); |
1512 | GNUNET_snprintf (b2, | 1472 | GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v6->sin6_port)); |
1513 | sizeof (b2), | 1473 | strcat (buf, b2); |
1514 | "%u", | ||
1515 | ntohs (v6->sin6_port)); | ||
1516 | strcat (buf, | ||
1517 | b2); | ||
1518 | return buf; | 1474 | return buf; |
1519 | case AF_UNIX: | 1475 | case AF_UNIX: |
1520 | if (addrlen <= sizeof (sa_family_t)) | 1476 | if (addrlen <= sizeof (sa_family_t)) |
@@ -1532,7 +1488,7 @@ GNUNET_a2s (const struct sockaddr *addr, | |||
1532 | &un->sun_path[off]); | 1488 | &un->sun_path[off]); |
1533 | return buf; | 1489 | return buf; |
1534 | default: | 1490 | default: |
1535 | return _("invalid address"); | 1491 | return _ ("invalid address"); |
1536 | } | 1492 | } |
1537 | } | 1493 | } |
1538 | 1494 | ||
@@ -1546,13 +1502,14 @@ GNUNET_a2s (const struct sockaddr *addr, | |||
1546 | */ | 1502 | */ |
1547 | void | 1503 | void |
1548 | GNUNET_log_config_missing (enum GNUNET_ErrorType kind, | 1504 | GNUNET_log_config_missing (enum GNUNET_ErrorType kind, |
1549 | const char *section, | 1505 | const char *section, |
1550 | const char *option) | 1506 | const char *option) |
1551 | { | 1507 | { |
1552 | GNUNET_log (kind, | 1508 | GNUNET_log (kind, |
1553 | _("Configuration fails to specify option `%s' in section `%s'!\n"), | 1509 | _ ( |
1554 | option, | 1510 | "Configuration fails to specify option `%s' in section `%s'!\n"), |
1555 | section); | 1511 | option, |
1512 | section); | ||
1556 | } | 1513 | } |
1557 | 1514 | ||
1558 | 1515 | ||
@@ -1566,13 +1523,17 @@ GNUNET_log_config_missing (enum GNUNET_ErrorType kind, | |||
1566 | */ | 1523 | */ |
1567 | void | 1524 | void |
1568 | GNUNET_log_config_invalid (enum GNUNET_ErrorType kind, | 1525 | GNUNET_log_config_invalid (enum GNUNET_ErrorType kind, |
1569 | const char *section, | 1526 | const char *section, |
1570 | const char *option, | 1527 | const char *option, |
1571 | const char *required) | 1528 | const char *required) |
1572 | { | 1529 | { |
1573 | GNUNET_log (kind, | 1530 | GNUNET_log ( |
1574 | _("Configuration specifies invalid value for option `%s' in section `%s': %s\n"), | 1531 | kind, |
1575 | option, section, required); | 1532 | _ ( |
1533 | "Configuration specifies invalid value for option `%s' in section `%s': %s\n"), | ||
1534 | option, | ||
1535 | section, | ||
1536 | required); | ||
1576 | } | 1537 | } |
1577 | 1538 | ||
1578 | 1539 | ||
@@ -1633,15 +1594,14 @@ GNUNET_async_scope_get (struct GNUNET_AsyncScopeSave *scope_ret) | |||
1633 | /** | 1594 | /** |
1634 | * Initializer | 1595 | * Initializer |
1635 | */ | 1596 | */ |
1636 | void __attribute__ ((constructor)) | 1597 | void __attribute__ ((constructor)) GNUNET_util_cl_init () |
1637 | GNUNET_util_cl_init () | ||
1638 | { | 1598 | { |
1639 | GNUNET_stderr = stderr; | 1599 | GNUNET_stderr = stderr; |
1640 | #ifdef MINGW | 1600 | #ifdef MINGW |
1641 | GNInitWinEnv (NULL); | 1601 | GNInitWinEnv (NULL); |
1642 | #endif | 1602 | #endif |
1643 | #if WINDOWS | 1603 | #if WINDOWS |
1644 | if (!InitializeCriticalSectionAndSpinCount (&output_message_cs, 0x00000400)) | 1604 | if (! InitializeCriticalSectionAndSpinCount (&output_message_cs, 0x00000400)) |
1645 | GNUNET_abort_ (); | 1605 | GNUNET_abort_ (); |
1646 | #endif | 1606 | #endif |
1647 | } | 1607 | } |
@@ -1650,8 +1610,7 @@ GNUNET_util_cl_init () | |||
1650 | /** | 1610 | /** |
1651 | * Destructor | 1611 | * Destructor |
1652 | */ | 1612 | */ |
1653 | void __attribute__ ((destructor)) | 1613 | void __attribute__ ((destructor)) GNUNET_util_cl_fini () |
1654 | GNUNET_util_cl_fini () | ||
1655 | { | 1614 | { |
1656 | #if WINDOWS | 1615 | #if WINDOWS |
1657 | DeleteCriticalSection (&output_message_cs); | 1616 | DeleteCriticalSection (&output_message_cs); |
diff --git a/src/util/container_multiuuidmap.c b/src/util/container_multiuuidmap.c new file mode 100644 index 000000000..49eb64cfe --- /dev/null +++ b/src/util/container_multiuuidmap.c | |||
@@ -0,0 +1,1015 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008, 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file util/container_multiuuidmap.c | ||
22 | * @brief hash map for UUIDs where the same key may be present multiple times | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | |||
29 | #define LOG(kind, ...) \ | ||
30 | GNUNET_log_from (kind, "util-container-multiuuidmap", __VA_ARGS__) | ||
31 | |||
32 | /** | ||
33 | * Maximum recursion depth for callbacks of | ||
34 | * #GNUNET_CONTAINER_multihashmap_get_multiple() themselve s | ||
35 | * again calling #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
36 | * Should be totally excessive, but if violated we die. | ||
37 | */ | ||
38 | #define NEXT_CACHE_SIZE 16 | ||
39 | |||
40 | |||
41 | /** | ||
42 | * An entry in the hash map with the full key. | ||
43 | */ | ||
44 | struct BigMapEntry | ||
45 | { | ||
46 | |||
47 | /** | ||
48 | * Value of the entry. | ||
49 | */ | ||
50 | void *value; | ||
51 | |||
52 | /** | ||
53 | * If there is a hash collision, we create a linked list. | ||
54 | */ | ||
55 | struct BigMapEntry *next; | ||
56 | |||
57 | /** | ||
58 | * Key for the entry. | ||
59 | */ | ||
60 | struct GNUNET_Uuid key; | ||
61 | }; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * An entry in the hash map with just a pointer to the key. | ||
66 | */ | ||
67 | struct SmallMapEntry | ||
68 | { | ||
69 | |||
70 | /** | ||
71 | * Value of the entry. | ||
72 | */ | ||
73 | void *value; | ||
74 | |||
75 | /** | ||
76 | * If there is a hash collision, we create a linked list. | ||
77 | */ | ||
78 | struct SmallMapEntry *next; | ||
79 | |||
80 | /** | ||
81 | * Key for the entry. | ||
82 | */ | ||
83 | const struct GNUNET_Uuid *key; | ||
84 | }; | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Entry in the map. | ||
89 | */ | ||
90 | union MapEntry | ||
91 | { | ||
92 | /** | ||
93 | * Variant used if map entries only contain a pointer to the key. | ||
94 | */ | ||
95 | struct SmallMapEntry *sme; | ||
96 | |||
97 | /** | ||
98 | * Variant used if map entries contain the full key. | ||
99 | */ | ||
100 | struct BigMapEntry *bme; | ||
101 | }; | ||
102 | |||
103 | |||
104 | /** | ||
105 | * Internal representation of the hash map. | ||
106 | */ | ||
107 | struct GNUNET_CONTAINER_MultiUuidmap | ||
108 | { | ||
109 | /** | ||
110 | * All of our buckets. | ||
111 | */ | ||
112 | union MapEntry *map; | ||
113 | |||
114 | /** | ||
115 | * Number of entries in the map. | ||
116 | */ | ||
117 | unsigned int size; | ||
118 | |||
119 | /** | ||
120 | * Length of the "map" array. | ||
121 | */ | ||
122 | unsigned int map_length; | ||
123 | |||
124 | /** | ||
125 | * #GNUNET_NO if the map entries are of type 'struct BigMapEntry', | ||
126 | * #GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. | ||
127 | */ | ||
128 | int use_small_entries; | ||
129 | |||
130 | /** | ||
131 | * Counts the destructive modifications (grow, remove) | ||
132 | * to the map, so that iterators can check if they are still valid. | ||
133 | */ | ||
134 | unsigned int modification_counter; | ||
135 | |||
136 | /** | ||
137 | * Map entries indicating iteration positions currently | ||
138 | * in use by #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
139 | * Only used up to @e next_cache_off. | ||
140 | */ | ||
141 | union MapEntry next_cache[NEXT_CACHE_SIZE]; | ||
142 | |||
143 | /** | ||
144 | * Offset of @e next_cache entries in use, must be smaller | ||
145 | * than #NEXT_CACHE_SIZE. | ||
146 | */ | ||
147 | unsigned int next_cache_off; | ||
148 | }; | ||
149 | |||
150 | |||
151 | /** | ||
152 | * Cursor into a multiuuidmap. | ||
153 | * Allows to enumerate elements asynchronously. | ||
154 | */ | ||
155 | struct GNUNET_CONTAINER_MultiUuidmapIterator | ||
156 | { | ||
157 | /** | ||
158 | * Position in the bucket 'idx' | ||
159 | */ | ||
160 | union MapEntry me; | ||
161 | |||
162 | /** | ||
163 | * Current bucket index. | ||
164 | */ | ||
165 | unsigned int idx; | ||
166 | |||
167 | /** | ||
168 | * Modification counter as observed on the map when the iterator | ||
169 | * was created. | ||
170 | */ | ||
171 | unsigned int modification_counter; | ||
172 | |||
173 | /** | ||
174 | * Map that we are iterating over. | ||
175 | */ | ||
176 | const struct GNUNET_CONTAINER_MultiUuidmap *map; | ||
177 | }; | ||
178 | |||
179 | |||
180 | /** | ||
181 | * Create a multi hash map. | ||
182 | * | ||
183 | * @param len initial size (map will grow as needed) | ||
184 | * @param do_not_copy_keys #GNUNET_NO is always safe and should be used by default; | ||
185 | * #GNUNET_YES means that on 'put', the 'key' does not have | ||
186 | * to be copied as the destination of the pointer is | ||
187 | * guaranteed to be life as long as the value is stored in | ||
188 | * the hashmap. This can significantly reduce memory | ||
189 | * consumption, but of course is also a recipie for | ||
190 | * heap corruption if the assumption is not true. Only | ||
191 | * use this if (1) memory use is important in this case and | ||
192 | * (2) you have triple-checked that the invariant holds | ||
193 | * @return NULL on error | ||
194 | */ | ||
195 | struct GNUNET_CONTAINER_MultiUuidmap * | ||
196 | GNUNET_CONTAINER_multiuuidmap_create (unsigned int len, int do_not_copy_keys) | ||
197 | { | ||
198 | struct GNUNET_CONTAINER_MultiUuidmap *map; | ||
199 | |||
200 | GNUNET_assert (len > 0); | ||
201 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiUuidmap); | ||
202 | map->map = GNUNET_malloc_large (len * sizeof (union MapEntry)); | ||
203 | if (NULL == map->map) | ||
204 | { | ||
205 | GNUNET_free (map); | ||
206 | return NULL; | ||
207 | } | ||
208 | map->map_length = len; | ||
209 | map->use_small_entries = do_not_copy_keys; | ||
210 | return map; | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Destroy a hash map. Will not free any values | ||
216 | * stored in the hash map! | ||
217 | * | ||
218 | * @param map the map | ||
219 | */ | ||
220 | void | ||
221 | GNUNET_CONTAINER_multiuuidmap_destroy ( | ||
222 | struct GNUNET_CONTAINER_MultiUuidmap *map) | ||
223 | { | ||
224 | GNUNET_assert (0 == map->next_cache_off); | ||
225 | for (unsigned int i = 0; i < map->map_length; i++) | ||
226 | { | ||
227 | union MapEntry me; | ||
228 | |||
229 | me = map->map[i]; | ||
230 | if (map->use_small_entries) | ||
231 | { | ||
232 | struct SmallMapEntry *sme; | ||
233 | struct SmallMapEntry *nxt; | ||
234 | |||
235 | nxt = me.sme; | ||
236 | while (NULL != (sme = nxt)) | ||
237 | { | ||
238 | nxt = sme->next; | ||
239 | GNUNET_free (sme); | ||
240 | } | ||
241 | me.sme = NULL; | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | struct BigMapEntry *bme; | ||
246 | struct BigMapEntry *nxt; | ||
247 | |||
248 | nxt = me.bme; | ||
249 | while (NULL != (bme = nxt)) | ||
250 | { | ||
251 | nxt = bme->next; | ||
252 | GNUNET_free (bme); | ||
253 | } | ||
254 | me.bme = NULL; | ||
255 | } | ||
256 | } | ||
257 | GNUNET_free (map->map); | ||
258 | GNUNET_free (map); | ||
259 | } | ||
260 | |||
261 | |||
262 | /** | ||
263 | * Compute the index of the bucket for the given key. | ||
264 | * | ||
265 | * @param map hash map for which to compute the index | ||
266 | * @param key what key should the index be computed for | ||
267 | * @return offset into the "map" array of "map" | ||
268 | */ | ||
269 | static unsigned int | ||
270 | idx_of (const struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
271 | const struct GNUNET_Uuid *key) | ||
272 | { | ||
273 | unsigned int kx; | ||
274 | |||
275 | GNUNET_assert (NULL != map); | ||
276 | GNUNET_memcpy (&kx, key, sizeof (kx)); | ||
277 | return kx % map->map_length; | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Get the number of key-value pairs in the map. | ||
283 | * | ||
284 | * @param map the map | ||
285 | * @return the number of key value pairs | ||
286 | */ | ||
287 | unsigned int | ||
288 | GNUNET_CONTAINER_multiuuidmap_size ( | ||
289 | const struct GNUNET_CONTAINER_MultiUuidmap *map) | ||
290 | { | ||
291 | return map->size; | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Given a key find a value in the map matching the key. | ||
297 | * | ||
298 | * @param map the map | ||
299 | * @param key what to look for | ||
300 | * @return NULL if no value was found; note that | ||
301 | * this is indistinguishable from values that just | ||
302 | * happen to be NULL; use "contains" to test for | ||
303 | * key-value pairs with value NULL | ||
304 | */ | ||
305 | void * | ||
306 | GNUNET_CONTAINER_multiuuidmap_get ( | ||
307 | const struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
308 | const struct GNUNET_Uuid *key) | ||
309 | { | ||
310 | union MapEntry me; | ||
311 | |||
312 | me = map->map[idx_of (map, key)]; | ||
313 | if (map->use_small_entries) | ||
314 | { | ||
315 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | ||
316 | if (0 == GNUNET_memcmp (key, sme->key)) | ||
317 | return sme->value; | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | ||
322 | if (0 == GNUNET_memcmp (key, &bme->key)) | ||
323 | return bme->value; | ||
324 | } | ||
325 | return NULL; | ||
326 | } | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Iterate over all entries in the map. | ||
331 | * | ||
332 | * @param map the map | ||
333 | * @param it function to call on each entry | ||
334 | * @param it_cls extra argument to @a it | ||
335 | * @return the number of key value pairs processed, | ||
336 | * #GNUNET_SYSERR if it aborted iteration | ||
337 | */ | ||
338 | int | ||
339 | GNUNET_CONTAINER_multiuuidmap_iterate ( | ||
340 | struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
341 | GNUNET_CONTAINER_MultiUuidmapIterator it, | ||
342 | void *it_cls) | ||
343 | { | ||
344 | int count; | ||
345 | union MapEntry me; | ||
346 | union MapEntry *ce; | ||
347 | struct GNUNET_Uuid kc; | ||
348 | |||
349 | count = 0; | ||
350 | GNUNET_assert (NULL != map); | ||
351 | ce = &map->next_cache[map->next_cache_off]; | ||
352 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
353 | for (unsigned int i = 0; i < map->map_length; i++) | ||
354 | { | ||
355 | me = map->map[i]; | ||
356 | if (map->use_small_entries) | ||
357 | { | ||
358 | struct SmallMapEntry *sme; | ||
359 | |||
360 | ce->sme = me.sme; | ||
361 | while (NULL != (sme = ce->sme)) | ||
362 | { | ||
363 | ce->sme = sme->next; | ||
364 | if ((NULL != it) && (GNUNET_OK != it (it_cls, sme->key, sme->value))) | ||
365 | { | ||
366 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
367 | return GNUNET_SYSERR; | ||
368 | } | ||
369 | count++; | ||
370 | } | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | struct BigMapEntry *bme; | ||
375 | |||
376 | ce->bme = me.bme; | ||
377 | while (NULL != (bme = ce->bme)) | ||
378 | { | ||
379 | ce->bme = bme->next; | ||
380 | if (NULL != it) | ||
381 | { | ||
382 | kc = bme->key; | ||
383 | if (GNUNET_OK != it (it_cls, &kc, bme->value)) | ||
384 | { | ||
385 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
386 | return GNUNET_SYSERR; | ||
387 | } | ||
388 | } | ||
389 | count++; | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
394 | return count; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * We are about to free() the @a bme, make sure it is not in | ||
400 | * the list of next values for any iterator in the @a map's next_cache. | ||
401 | * | ||
402 | * @param map the map to check | ||
403 | * @param bme the entry that is about to be free'd | ||
404 | */ | ||
405 | static void | ||
406 | update_next_cache_bme (struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
407 | const struct BigMapEntry *bme) | ||
408 | { | ||
409 | for (unsigned int i = 0; i < map->next_cache_off; i++) | ||
410 | if (map->next_cache[i].bme == bme) | ||
411 | map->next_cache[i].bme = bme->next; | ||
412 | } | ||
413 | |||
414 | |||
415 | /** | ||
416 | * We are about to free() the @a sme, make sure it is not in | ||
417 | * the list of next values for any iterator in the @a map's next_cache. | ||
418 | * | ||
419 | * @param map the map to check | ||
420 | * @param sme the entry that is about to be free'd | ||
421 | */ | ||
422 | static void | ||
423 | update_next_cache_sme (struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
424 | const struct SmallMapEntry *sme) | ||
425 | { | ||
426 | for (unsigned int i = 0; i < map->next_cache_off; i++) | ||
427 | if (map->next_cache[i].sme == sme) | ||
428 | map->next_cache[i].sme = sme->next; | ||
429 | } | ||
430 | |||
431 | |||
432 | /** | ||
433 | * Remove the given key-value pair from the map. Note that if the | ||
434 | * key-value pair is in the map multiple times, only one of the pairs | ||
435 | * will be removed. | ||
436 | * | ||
437 | * @param map the map | ||
438 | * @param key key of the key-value pair | ||
439 | * @param value value of the key-value pair | ||
440 | * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair | ||
441 | * is not in the map | ||
442 | */ | ||
443 | int | ||
444 | GNUNET_CONTAINER_multiuuidmap_remove (struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
445 | const struct GNUNET_Uuid *key, | ||
446 | const void *value) | ||
447 | { | ||
448 | union MapEntry me; | ||
449 | unsigned int i; | ||
450 | |||
451 | map->modification_counter++; | ||
452 | i = idx_of (map, key); | ||
453 | me = map->map[i]; | ||
454 | if (map->use_small_entries) | ||
455 | { | ||
456 | struct SmallMapEntry *p = NULL; | ||
457 | |||
458 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | ||
459 | { | ||
460 | if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value)) | ||
461 | { | ||
462 | if (NULL == p) | ||
463 | map->map[i].sme = sme->next; | ||
464 | else | ||
465 | p->next = sme->next; | ||
466 | update_next_cache_sme (map, sme); | ||
467 | GNUNET_free (sme); | ||
468 | map->size--; | ||
469 | return GNUNET_YES; | ||
470 | } | ||
471 | p = sme; | ||
472 | } | ||
473 | } | ||
474 | else | ||
475 | { | ||
476 | struct BigMapEntry *p = NULL; | ||
477 | |||
478 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | ||
479 | { | ||
480 | if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value)) | ||
481 | { | ||
482 | if (NULL == p) | ||
483 | map->map[i].bme = bme->next; | ||
484 | else | ||
485 | p->next = bme->next; | ||
486 | update_next_cache_bme (map, bme); | ||
487 | GNUNET_free (bme); | ||
488 | map->size--; | ||
489 | return GNUNET_YES; | ||
490 | } | ||
491 | p = bme; | ||
492 | } | ||
493 | } | ||
494 | return GNUNET_NO; | ||
495 | } | ||
496 | |||
497 | |||
498 | /** | ||
499 | * Remove all entries for the given key from the map. | ||
500 | * Note that the values would not be "freed". | ||
501 | * | ||
502 | * @param map the map | ||
503 | * @param key identifies values to be removed | ||
504 | * @return number of values removed | ||
505 | */ | ||
506 | int | ||
507 | GNUNET_CONTAINER_multiuuidmap_remove_all ( | ||
508 | struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
509 | const struct GNUNET_Uuid *key) | ||
510 | { | ||
511 | union MapEntry me; | ||
512 | unsigned int i; | ||
513 | int ret; | ||
514 | |||
515 | map->modification_counter++; | ||
516 | |||
517 | ret = 0; | ||
518 | i = idx_of (map, key); | ||
519 | me = map->map[i]; | ||
520 | if (map->use_small_entries) | ||
521 | { | ||
522 | struct SmallMapEntry *sme; | ||
523 | struct SmallMapEntry *p; | ||
524 | |||
525 | p = NULL; | ||
526 | sme = me.sme; | ||
527 | while (NULL != sme) | ||
528 | { | ||
529 | if (0 == GNUNET_memcmp (key, sme->key)) | ||
530 | { | ||
531 | if (NULL == p) | ||
532 | map->map[i].sme = sme->next; | ||
533 | else | ||
534 | p->next = sme->next; | ||
535 | update_next_cache_sme (map, sme); | ||
536 | GNUNET_free (sme); | ||
537 | map->size--; | ||
538 | if (NULL == p) | ||
539 | sme = map->map[i].sme; | ||
540 | else | ||
541 | sme = p->next; | ||
542 | ret++; | ||
543 | } | ||
544 | else | ||
545 | { | ||
546 | p = sme; | ||
547 | sme = sme->next; | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | else | ||
552 | { | ||
553 | struct BigMapEntry *bme; | ||
554 | struct BigMapEntry *p; | ||
555 | |||
556 | p = NULL; | ||
557 | bme = me.bme; | ||
558 | while (NULL != bme) | ||
559 | { | ||
560 | if (0 == GNUNET_memcmp (key, &bme->key)) | ||
561 | { | ||
562 | if (NULL == p) | ||
563 | map->map[i].bme = bme->next; | ||
564 | else | ||
565 | p->next = bme->next; | ||
566 | update_next_cache_bme (map, bme); | ||
567 | GNUNET_free (bme); | ||
568 | map->size--; | ||
569 | if (NULL == p) | ||
570 | bme = map->map[i].bme; | ||
571 | else | ||
572 | bme = p->next; | ||
573 | ret++; | ||
574 | } | ||
575 | else | ||
576 | { | ||
577 | p = bme; | ||
578 | bme = bme->next; | ||
579 | } | ||
580 | } | ||
581 | } | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Check if the map contains any value under the given | ||
588 | * key (including values that are NULL). | ||
589 | * | ||
590 | * @param map the map | ||
591 | * @param key the key to test if a value exists for it | ||
592 | * @return #GNUNET_YES if such a value exists, | ||
593 | * #GNUNET_NO if not | ||
594 | */ | ||
595 | int | ||
596 | GNUNET_CONTAINER_multiuuidmap_contains ( | ||
597 | const struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
598 | const struct GNUNET_Uuid *key) | ||
599 | { | ||
600 | union MapEntry me; | ||
601 | |||
602 | me = map->map[idx_of (map, key)]; | ||
603 | if (map->use_small_entries) | ||
604 | { | ||
605 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | ||
606 | if (0 == GNUNET_memcmp (key, sme->key)) | ||
607 | return GNUNET_YES; | ||
608 | } | ||
609 | else | ||
610 | { | ||
611 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | ||
612 | if (0 == GNUNET_memcmp (key, &bme->key)) | ||
613 | return GNUNET_YES; | ||
614 | } | ||
615 | return GNUNET_NO; | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Check if the map contains the given value under the given | ||
621 | * key. | ||
622 | * | ||
623 | * @param map the map | ||
624 | * @param key the key to test if a value exists for it | ||
625 | * @param value value to test for | ||
626 | * @return #GNUNET_YES if such a value exists, | ||
627 | * #GNUNET_NO if not | ||
628 | */ | ||
629 | int | ||
630 | GNUNET_CONTAINER_multiuuidmap_contains_value ( | ||
631 | const struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
632 | const struct GNUNET_Uuid *key, | ||
633 | const void *value) | ||
634 | { | ||
635 | union MapEntry me; | ||
636 | |||
637 | me = map->map[idx_of (map, key)]; | ||
638 | if (map->use_small_entries) | ||
639 | { | ||
640 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | ||
641 | if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value)) | ||
642 | return GNUNET_YES; | ||
643 | } | ||
644 | else | ||
645 | { | ||
646 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | ||
647 | if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value)) | ||
648 | return GNUNET_YES; | ||
649 | } | ||
650 | return GNUNET_NO; | ||
651 | } | ||
652 | |||
653 | |||
654 | /** | ||
655 | * Grow the given map to a more appropriate size. | ||
656 | * | ||
657 | * @param map the hash map to grow | ||
658 | */ | ||
659 | static void | ||
660 | grow (struct GNUNET_CONTAINER_MultiUuidmap *map) | ||
661 | { | ||
662 | union MapEntry *old_map; | ||
663 | union MapEntry *new_map; | ||
664 | unsigned int old_len; | ||
665 | unsigned int new_len; | ||
666 | unsigned int idx; | ||
667 | |||
668 | old_map = map->map; | ||
669 | old_len = map->map_length; | ||
670 | new_len = old_len * 2; | ||
671 | if (0 == new_len) /* 2^31 * 2 == 0 */ | ||
672 | new_len = old_len; /* never use 0 */ | ||
673 | if (new_len == old_len) | ||
674 | return; /* nothing changed */ | ||
675 | new_map = GNUNET_malloc_large (new_len * sizeof (union MapEntry)); | ||
676 | if (NULL == new_map) | ||
677 | return; /* grow not possible */ | ||
678 | map->modification_counter++; | ||
679 | map->map_length = new_len; | ||
680 | map->map = new_map; | ||
681 | for (unsigned int i = 0; i < old_len; i++) | ||
682 | { | ||
683 | if (map->use_small_entries) | ||
684 | { | ||
685 | struct SmallMapEntry *sme; | ||
686 | |||
687 | while (NULL != (sme = old_map[i].sme)) | ||
688 | { | ||
689 | old_map[i].sme = sme->next; | ||
690 | idx = idx_of (map, sme->key); | ||
691 | sme->next = new_map[idx].sme; | ||
692 | new_map[idx].sme = sme; | ||
693 | } | ||
694 | } | ||
695 | else | ||
696 | { | ||
697 | struct BigMapEntry *bme; | ||
698 | |||
699 | while (NULL != (bme = old_map[i].bme)) | ||
700 | { | ||
701 | old_map[i].bme = bme->next; | ||
702 | idx = idx_of (map, &bme->key); | ||
703 | bme->next = new_map[idx].bme; | ||
704 | new_map[idx].bme = bme; | ||
705 | } | ||
706 | } | ||
707 | } | ||
708 | GNUNET_free (old_map); | ||
709 | } | ||
710 | |||
711 | |||
712 | /** | ||
713 | * Store a key-value pair in the map. | ||
714 | * | ||
715 | * @param map the map | ||
716 | * @param key key to use | ||
717 | * @param value value to use | ||
718 | * @param opt options for put | ||
719 | * @return #GNUNET_OK on success, | ||
720 | * #GNUNET_NO if a value was replaced (with REPLACE) | ||
721 | * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the | ||
722 | * value already exists | ||
723 | */ | ||
724 | int | ||
725 | GNUNET_CONTAINER_multiuuidmap_put (struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
726 | const struct GNUNET_Uuid *key, | ||
727 | void *value, | ||
728 | enum GNUNET_CONTAINER_MultiHashMapOption opt) | ||
729 | { | ||
730 | union MapEntry me; | ||
731 | unsigned int i; | ||
732 | |||
733 | i = idx_of (map, key); | ||
734 | if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) && | ||
735 | (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
736 | { | ||
737 | me = map->map[i]; | ||
738 | if (map->use_small_entries) | ||
739 | { | ||
740 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | ||
741 | if (0 == GNUNET_memcmp (key, sme->key)) | ||
742 | { | ||
743 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) | ||
744 | return GNUNET_SYSERR; | ||
745 | sme->value = value; | ||
746 | return GNUNET_NO; | ||
747 | } | ||
748 | } | ||
749 | else | ||
750 | { | ||
751 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | ||
752 | if (0 == GNUNET_memcmp (key, &bme->key)) | ||
753 | { | ||
754 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) | ||
755 | return GNUNET_SYSERR; | ||
756 | bme->value = value; | ||
757 | return GNUNET_NO; | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | if (map->size / 3 >= map->map_length / 4) | ||
762 | { | ||
763 | grow (map); | ||
764 | i = idx_of (map, key); | ||
765 | } | ||
766 | if (map->use_small_entries) | ||
767 | { | ||
768 | struct SmallMapEntry *sme; | ||
769 | |||
770 | sme = GNUNET_new (struct SmallMapEntry); | ||
771 | sme->key = key; | ||
772 | sme->value = value; | ||
773 | sme->next = map->map[i].sme; | ||
774 | map->map[i].sme = sme; | ||
775 | } | ||
776 | else | ||
777 | { | ||
778 | struct BigMapEntry *bme; | ||
779 | |||
780 | bme = GNUNET_new (struct BigMapEntry); | ||
781 | bme->key = *key; | ||
782 | bme->value = value; | ||
783 | bme->next = map->map[i].bme; | ||
784 | map->map[i].bme = bme; | ||
785 | } | ||
786 | map->size++; | ||
787 | return GNUNET_OK; | ||
788 | } | ||
789 | |||
790 | |||
791 | /** | ||
792 | * Iterate over all entries in the map that match a particular key. | ||
793 | * | ||
794 | * @param map the map | ||
795 | * @param key key that the entries must correspond to | ||
796 | * @param it function to call on each entry | ||
797 | * @param it_cls extra argument to @a it | ||
798 | * @return the number of key value pairs processed, | ||
799 | * #GNUNET_SYSERR if it aborted iteration | ||
800 | */ | ||
801 | int | ||
802 | GNUNET_CONTAINER_multiuuidmap_get_multiple ( | ||
803 | struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
804 | const struct GNUNET_Uuid *key, | ||
805 | GNUNET_CONTAINER_MultiUuidmapIterator it, | ||
806 | void *it_cls) | ||
807 | { | ||
808 | int count; | ||
809 | union MapEntry me; | ||
810 | union MapEntry *ce; | ||
811 | |||
812 | ce = &map->next_cache[map->next_cache_off]; | ||
813 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
814 | count = 0; | ||
815 | me = map->map[idx_of (map, key)]; | ||
816 | if (map->use_small_entries) | ||
817 | { | ||
818 | struct SmallMapEntry *sme; | ||
819 | |||
820 | ce->sme = me.sme; | ||
821 | while (NULL != (sme = ce->sme)) | ||
822 | { | ||
823 | ce->sme = sme->next; | ||
824 | if (0 != GNUNET_memcmp (key, sme->key)) | ||
825 | continue; | ||
826 | if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value))) | ||
827 | { | ||
828 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
829 | return GNUNET_SYSERR; | ||
830 | } | ||
831 | count++; | ||
832 | } | ||
833 | } | ||
834 | else | ||
835 | { | ||
836 | struct BigMapEntry *bme; | ||
837 | |||
838 | ce->bme = me.bme; | ||
839 | while (NULL != (bme = ce->bme)) | ||
840 | { | ||
841 | ce->bme = bme->next; | ||
842 | if (0 != GNUNET_memcmp (key, &bme->key)) | ||
843 | continue; | ||
844 | if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value))) | ||
845 | { | ||
846 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
847 | return GNUNET_SYSERR; | ||
848 | } | ||
849 | count++; | ||
850 | } | ||
851 | } | ||
852 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
853 | return count; | ||
854 | } | ||
855 | |||
856 | |||
857 | /** | ||
858 | * @ingroup hashmap | ||
859 | * Call @a it on a random value from the map, or not at all | ||
860 | * if the map is empty. Note that this function has linear | ||
861 | * complexity (in the size of the map). | ||
862 | * | ||
863 | * @param map the map | ||
864 | * @param it function to call on a random entry | ||
865 | * @param it_cls extra argument to @a it | ||
866 | * @return the number of key value pairs processed, zero or one. | ||
867 | */ | ||
868 | unsigned int | ||
869 | GNUNET_CONTAINER_multiuuidmap_get_random ( | ||
870 | const struct GNUNET_CONTAINER_MultiUuidmap *map, | ||
871 | GNUNET_CONTAINER_MultiUuidmapIterator it, | ||
872 | void *it_cls) | ||
873 | { | ||
874 | unsigned int off; | ||
875 | union MapEntry me; | ||
876 | |||
877 | if (0 == map->size) | ||
878 | return 0; | ||
879 | if (NULL == it) | ||
880 | return 1; | ||
881 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, map->size); | ||
882 | for (unsigned int idx = 0; idx < map->map_length; idx++) | ||
883 | { | ||
884 | me = map->map[idx]; | ||
885 | if (map->use_small_entries) | ||
886 | { | ||
887 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | ||
888 | { | ||
889 | if (0 == off) | ||
890 | { | ||
891 | if (GNUNET_OK != it (it_cls, sme->key, sme->value)) | ||
892 | return GNUNET_SYSERR; | ||
893 | return 1; | ||
894 | } | ||
895 | off--; | ||
896 | } | ||
897 | } | ||
898 | else | ||
899 | { | ||
900 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | ||
901 | { | ||
902 | if (0 == off) | ||
903 | { | ||
904 | if (GNUNET_OK != it (it_cls, &bme->key, bme->value)) | ||
905 | return GNUNET_SYSERR; | ||
906 | return 1; | ||
907 | } | ||
908 | off--; | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | GNUNET_break (0); | ||
913 | return GNUNET_SYSERR; | ||
914 | } | ||
915 | |||
916 | |||
917 | /** | ||
918 | * Create an iterator for a multiuuidmap. | ||
919 | * The iterator can be used to retrieve all the elements in the multiuuidmap | ||
920 | * one by one, without having to handle all elements at once (in contrast to | ||
921 | * #GNUNET_CONTAINER_multiuuidmap_iterate). Note that the iterator can not be | ||
922 | * used anymore if elements have been removed from 'map' after the creation of | ||
923 | * the iterator, or 'map' has been destroyed. Adding elements to 'map' may | ||
924 | * result in skipped or repeated elements. | ||
925 | * | ||
926 | * @param map the map to create an iterator for | ||
927 | * @return an iterator over the given multiuuidmap 'map' | ||
928 | */ | ||
929 | struct GNUNET_CONTAINER_MultiUuidmapIterator * | ||
930 | GNUNET_CONTAINER_multiuuidmap_iterator_create ( | ||
931 | const struct GNUNET_CONTAINER_MultiUuidmap *map) | ||
932 | { | ||
933 | struct GNUNET_CONTAINER_MultiUuidmapIterator *iter; | ||
934 | |||
935 | iter = GNUNET_new (struct GNUNET_CONTAINER_MultiUuidmapIterator); | ||
936 | iter->map = map; | ||
937 | iter->modification_counter = map->modification_counter; | ||
938 | iter->me = map->map[0]; | ||
939 | return iter; | ||
940 | } | ||
941 | |||
942 | |||
943 | /** | ||
944 | * Retrieve the next element from the hash map at the iterator's position. | ||
945 | * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value' | ||
946 | * are not modified. | ||
947 | * This operation is only allowed if no elements have been removed from the | ||
948 | * multiuuidmap since the creation of 'iter', and the map has not been destroyed. | ||
949 | * Adding elements may result in repeating or skipping elements. | ||
950 | * | ||
951 | * @param iter the iterator to get the next element from | ||
952 | * @param key pointer to store the key in, can be NULL | ||
953 | * @param value pointer to store the value in, can be NULL | ||
954 | * @return #GNUNET_YES we returned an element, | ||
955 | * #GNUNET_NO if we are out of elements | ||
956 | */ | ||
957 | int | ||
958 | GNUNET_CONTAINER_multiuuidmap_iterator_next ( | ||
959 | struct GNUNET_CONTAINER_MultiUuidmapIterator *iter, | ||
960 | struct GNUNET_Uuid *key, | ||
961 | const void **value) | ||
962 | { | ||
963 | /* make sure the map has not been modified */ | ||
964 | GNUNET_assert (iter->modification_counter == iter->map->modification_counter); | ||
965 | |||
966 | /* look for the next entry, skipping empty buckets */ | ||
967 | while (1) | ||
968 | { | ||
969 | if (iter->idx >= iter->map->map_length) | ||
970 | return GNUNET_NO; | ||
971 | if (GNUNET_YES == iter->map->use_small_entries) | ||
972 | { | ||
973 | if (NULL != iter->me.sme) | ||
974 | { | ||
975 | if (NULL != key) | ||
976 | *key = *iter->me.sme->key; | ||
977 | if (NULL != value) | ||
978 | *value = iter->me.sme->value; | ||
979 | iter->me.sme = iter->me.sme->next; | ||
980 | return GNUNET_YES; | ||
981 | } | ||
982 | } | ||
983 | else | ||
984 | { | ||
985 | if (NULL != iter->me.bme) | ||
986 | { | ||
987 | if (NULL != key) | ||
988 | *key = iter->me.bme->key; | ||
989 | if (NULL != value) | ||
990 | *value = iter->me.bme->value; | ||
991 | iter->me.bme = iter->me.bme->next; | ||
992 | return GNUNET_YES; | ||
993 | } | ||
994 | } | ||
995 | iter->idx += 1; | ||
996 | if (iter->idx < iter->map->map_length) | ||
997 | iter->me = iter->map->map[iter->idx]; | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | |||
1002 | /** | ||
1003 | * Destroy a multiuuidmap iterator. | ||
1004 | * | ||
1005 | * @param iter the iterator to destroy | ||
1006 | */ | ||
1007 | void | ||
1008 | GNUNET_CONTAINER_multiuuidmap_iterator_destroy ( | ||
1009 | struct GNUNET_CONTAINER_MultiUuidmapIterator *iter) | ||
1010 | { | ||
1011 | GNUNET_free (iter); | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | /* end of container_multiuuidmap.c */ | ||