diff options
-rw-r--r-- | src/namestore/gnunet-zoneimport.c | 160 |
1 files changed, 111 insertions, 49 deletions
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c index 763687c59..8173ad9be 100644 --- a/src/namestore/gnunet-zoneimport.c +++ b/src/namestore/gnunet-zoneimport.c | |||
@@ -114,11 +114,21 @@ struct Record | |||
114 | struct Request | 114 | struct Request |
115 | { | 115 | { |
116 | /** | 116 | /** |
117 | * Requests are kept in a heap. | 117 | * Requests are kept in a heap while waiting to be resolved. |
118 | */ | 118 | */ |
119 | struct GNUNET_CONTAINER_HeapNode *hn; | 119 | struct GNUNET_CONTAINER_HeapNode *hn; |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * Active requests are kept in a DLL. | ||
123 | */ | ||
124 | struct Request *next; | ||
125 | |||
126 | /** | ||
127 | * Active requests are kept in a DLL. | ||
128 | */ | ||
129 | struct Request *prev; | ||
130 | |||
131 | /** | ||
122 | * Head of records that should be published in GNS for | 132 | * Head of records that should be published in GNS for |
123 | * this hostname. | 133 | * this hostname. |
124 | */ | 134 | */ |
@@ -238,6 +248,16 @@ static unsigned int records; | |||
238 | static struct GNUNET_CONTAINER_Heap *req_heap; | 248 | static struct GNUNET_CONTAINER_Heap *req_heap; |
239 | 249 | ||
240 | /** | 250 | /** |
251 | * Active requests are kept in a DLL. | ||
252 | */ | ||
253 | static struct Request *req_head; | ||
254 | |||
255 | /** | ||
256 | * Active requests are kept in a DLL. | ||
257 | */ | ||
258 | static struct Request *req_tail; | ||
259 | |||
260 | /** | ||
241 | * Main task. | 261 | * Main task. |
242 | */ | 262 | */ |
243 | static struct GNUNET_SCHEDULER_Task *t; | 263 | static struct GNUNET_SCHEDULER_Task *t; |
@@ -322,6 +342,39 @@ for_all_records (const struct GNUNET_DNSPARSER_Packet *p, | |||
322 | 342 | ||
323 | 343 | ||
324 | /** | 344 | /** |
345 | * Free @a req and data structures reachable from it. | ||
346 | * | ||
347 | * @param req request to free | ||
348 | */ | ||
349 | static void | ||
350 | free_request (struct Request *req) | ||
351 | { | ||
352 | struct Record *rec; | ||
353 | |||
354 | while (NULL != (rec = req->rec_head)) | ||
355 | { | ||
356 | GNUNET_CONTAINER_DLL_remove (req->rec_head, | ||
357 | req->rec_tail, | ||
358 | rec); | ||
359 | GNUNET_free (rec); | ||
360 | } | ||
361 | GNUNET_free (req->hostname); | ||
362 | GNUNET_free (req->label); | ||
363 | GNUNET_free (req->raw); | ||
364 | GNUNET_free (req); | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Process as many requests as possible from the queue. | ||
370 | * | ||
371 | * @param cls NULL | ||
372 | */ | ||
373 | static void | ||
374 | process_queue (void *cls); | ||
375 | |||
376 | |||
377 | /** | ||
325 | * Insert @a req into DLL sorted by next fetch time. | 378 | * Insert @a req into DLL sorted by next fetch time. |
326 | * | 379 | * |
327 | * @param req request to insert into #req_heap | 380 | * @param req request to insert into #req_heap |
@@ -332,6 +385,14 @@ insert_sorted (struct Request *req) | |||
332 | req->hn = GNUNET_CONTAINER_heap_insert (req_heap, | 385 | req->hn = GNUNET_CONTAINER_heap_insert (req_heap, |
333 | req, | 386 | req, |
334 | req->expires.abs_value_us); | 387 | req->expires.abs_value_us); |
388 | if (req == GNUNET_CONTAINER_heap_peek (req_heap)) | ||
389 | { | ||
390 | if (NULL != t) | ||
391 | GNUNET_SCHEDULER_cancel (t); | ||
392 | t = GNUNET_SCHEDULER_add_at (req->expires, | ||
393 | &process_queue, | ||
394 | NULL); | ||
395 | } | ||
335 | } | 396 | } |
336 | 397 | ||
337 | 398 | ||
@@ -745,25 +806,21 @@ process_result (void *cls, | |||
745 | unsigned int rd_count; | 806 | unsigned int rd_count; |
746 | 807 | ||
747 | (void) rs; | 808 | (void) rs; |
809 | GNUNET_assert (NULL == req->hn); | ||
748 | if (NULL == dns) | 810 | if (NULL == dns) |
749 | { | 811 | { |
750 | /* stub gave up */ | 812 | /* stub gave up */ |
813 | GNUNET_CONTAINER_DLL_remove (req_head, | ||
814 | req_tail, | ||
815 | req); | ||
751 | pending--; | 816 | pending--; |
752 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 817 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
753 | "Stub gave up on DNS reply for `%s'\n", | 818 | "Stub gave up on DNS reply for `%s'\n", |
754 | req->hostname); | 819 | req->hostname); |
755 | if (NULL != req->hn) | ||
756 | { | ||
757 | GNUNET_break (0); /* should not be possible */ | ||
758 | GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_node (req->hn)); | ||
759 | req->hn = NULL; | ||
760 | } | ||
761 | if (req->issue_num > MAX_RETRIES) | 820 | if (req->issue_num > MAX_RETRIES) |
762 | { | 821 | { |
763 | failures++; | 822 | failures++; |
764 | GNUNET_free (req->hostname); | 823 | free_request (req); |
765 | GNUNET_free (req->raw); | ||
766 | GNUNET_free (req); | ||
767 | return; | 824 | return; |
768 | } | 825 | } |
769 | req->rs = NULL; | 826 | req->rs = NULL; |
@@ -772,15 +829,12 @@ process_result (void *cls, | |||
772 | } | 829 | } |
773 | if (req->id != dns->id) | 830 | if (req->id != dns->id) |
774 | return; | 831 | return; |
832 | GNUNET_CONTAINER_DLL_remove (req_head, | ||
833 | req_tail, | ||
834 | req); | ||
775 | pending--; | 835 | pending--; |
776 | GNUNET_DNSSTUB_resolve_cancel (req->rs); | 836 | GNUNET_DNSSTUB_resolve_cancel (req->rs); |
777 | req->rs = NULL; | 837 | req->rs = NULL; |
778 | if (NULL != req->hn) | ||
779 | { | ||
780 | GNUNET_break (0); /* should not be possible */ | ||
781 | GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_node (req->hn)); | ||
782 | req->hn = NULL; | ||
783 | } | ||
784 | p = GNUNET_DNSPARSER_parse ((const char *) dns, | 838 | p = GNUNET_DNSPARSER_parse ((const char *) dns, |
785 | dns_len); | 839 | dns_len); |
786 | if (NULL == p) | 840 | if (NULL == p) |
@@ -891,11 +945,17 @@ submit_req (struct Request *req) | |||
891 | struct GNUNET_TIME_Absolute now; | 945 | struct GNUNET_TIME_Absolute now; |
892 | 946 | ||
893 | if (NULL != req->rs) | 947 | if (NULL != req->rs) |
948 | { | ||
949 | GNUNET_break (0); | ||
894 | return GNUNET_NO; /* already submitted */ | 950 | return GNUNET_NO; /* already submitted */ |
951 | } | ||
895 | now = GNUNET_TIME_absolute_get (); | 952 | now = GNUNET_TIME_absolute_get (); |
896 | if ( (now.abs_value_us - last_request.abs_value_us < TIME_THRESH) || | 953 | if ( (now.abs_value_us - last_request.abs_value_us < TIME_THRESH) || |
897 | (pending >= THRESH) ) | 954 | (pending >= THRESH) ) |
898 | return GNUNET_SYSERR; | 955 | return GNUNET_SYSERR; |
956 | GNUNET_CONTAINER_DLL_insert (req_head, | ||
957 | req_tail, | ||
958 | req); | ||
899 | GNUNET_assert (NULL == req->rs); | 959 | GNUNET_assert (NULL == req->rs); |
900 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 960 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
901 | "Requesting resolution for `%s'\n", | 961 | "Requesting resolution for `%s'\n", |
@@ -947,48 +1007,47 @@ process_queue (void *cls) | |||
947 | 1007 | ||
948 | (void) cls; | 1008 | (void) cls; |
949 | t = NULL; | 1009 | t = NULL; |
950 | do | 1010 | while (1) |
951 | { | 1011 | { |
952 | req = GNUNET_CONTAINER_heap_peek (req_heap); | 1012 | req = GNUNET_CONTAINER_heap_peek (req_heap); |
953 | if (NULL == req) | 1013 | if (NULL == req) |
954 | break; | 1014 | break; |
955 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | 1015 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) |
956 | break; | 1016 | break; |
957 | GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_root (req_heap)); | 1017 | if (GNUNET_OK != submit_req (req)) |
1018 | break; | ||
1019 | GNUNET_assert (req == | ||
1020 | GNUNET_CONTAINER_heap_remove_root (req_heap)); | ||
958 | req->hn = NULL; | 1021 | req->hn = NULL; |
959 | } | 1022 | } |
960 | while (GNUNET_SYSERR != submit_req (req)); | ||
961 | 1023 | ||
962 | req = GNUNET_CONTAINER_heap_peek (req_heap); | 1024 | req = GNUNET_CONTAINER_heap_peek (req_heap); |
963 | if (NULL != req) | 1025 | if (NULL == req) |
1026 | return; | ||
1027 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | ||
964 | { | 1028 | { |
965 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | 1029 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
966 | { | 1030 | "Waiting until %s for next record (`%s') to expire\n", |
967 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1031 | GNUNET_STRINGS_absolute_time_to_string (req->expires), |
968 | "Waiting until %s for next record (`%s') to expire\n", | 1032 | req->hostname); |
969 | GNUNET_STRINGS_absolute_time_to_string (req->expires), | 1033 | finish_transaction (); |
970 | req->hostname); | 1034 | if (NULL != t) |
971 | finish_transaction (); | 1035 | GNUNET_SCHEDULER_cancel (t); |
972 | t = GNUNET_SCHEDULER_add_at (req->expires, | 1036 | t = GNUNET_SCHEDULER_add_at (req->expires, |
973 | &process_queue, | 1037 | &process_queue, |
974 | NULL); | 1038 | NULL); |
975 | } | ||
976 | else | ||
977 | { | ||
978 | if (0 == cnt++ % TRANSACTION_SYNC_FREQ) | ||
979 | finish_transaction (); | ||
980 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
981 | "Throttling for 1ms\n"); | ||
982 | t = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
983 | &process_queue, | ||
984 | NULL); | ||
985 | } | ||
986 | } | 1039 | } |
987 | else | 1040 | else |
988 | { | 1041 | { |
989 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1042 | if (0 == cnt++ % TRANSACTION_SYNC_FREQ) |
990 | "No more pending requests, terminating\n"); | 1043 | finish_transaction (); |
991 | GNUNET_SCHEDULER_shutdown (); | 1044 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1045 | "Throttling for 1ms\n"); | ||
1046 | if (NULL != t) | ||
1047 | GNUNET_SCHEDULER_cancel (t); | ||
1048 | t = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
1049 | &process_queue, | ||
1050 | NULL); | ||
992 | } | 1051 | } |
993 | } | 1052 | } |
994 | 1053 | ||
@@ -1029,12 +1088,17 @@ do_shutdown (void *cls) | |||
1029 | GNUNET_DNSSTUB_stop (ctx); | 1088 | GNUNET_DNSSTUB_stop (ctx); |
1030 | ctx = NULL; | 1089 | ctx = NULL; |
1031 | } | 1090 | } |
1091 | while (NULL != (req = req_head)) | ||
1092 | { | ||
1093 | GNUNET_CONTAINER_DLL_remove (req_head, | ||
1094 | req_tail, | ||
1095 | req); | ||
1096 | free_request (req); | ||
1097 | } | ||
1032 | while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap))) | 1098 | while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap))) |
1033 | { | 1099 | { |
1034 | req->hn = NULL; | 1100 | req->hn = NULL; |
1035 | GNUNET_free (req->hostname); | 1101 | free_request (req); |
1036 | GNUNET_free (req->label); | ||
1037 | GNUNET_free (req); | ||
1038 | } | 1102 | } |
1039 | if (NULL != req_heap) | 1103 | if (NULL != req_heap) |
1040 | { | 1104 | { |
@@ -1234,8 +1298,6 @@ process_stdin (void *cls) | |||
1234 | hn[strlen(hn)-1] = '\0'; /* eat newline */ | 1298 | hn[strlen(hn)-1] = '\0'; /* eat newline */ |
1235 | queue (hn); | 1299 | queue (hn); |
1236 | } | 1300 | } |
1237 | t = GNUNET_SCHEDULER_add_now (&process_queue, | ||
1238 | NULL); | ||
1239 | } | 1301 | } |
1240 | 1302 | ||
1241 | 1303 | ||