diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-04-28 12:10:06 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-04-28 12:10:06 +0000 |
commit | ae300a58c5bdfcadca8837a1e23abe3e34032209 (patch) | |
tree | c90e62d0c32575dce3ac763fa1f67ca858823a5e /src | |
parent | 684476aafc7c225d565295fdac4a00ee8bfc207f (diff) | |
download | gnunet-ae300a58c5bdfcadca8837a1e23abe3e34032209.tar.gz gnunet-ae300a58c5bdfcadca8837a1e23abe3e34032209.zip |
adding availability probes for search results
Diffstat (limited to 'src')
-rw-r--r-- | src/fs/fs.h | 134 | ||||
-rw-r--r-- | src/fs/fs_download.c | 41 | ||||
-rw-r--r-- | src/fs/fs_search.c | 240 | ||||
-rw-r--r-- | src/include/gnunet_fs_service.h | 20 | ||||
-rw-r--r-- | src/include/gnunet_time_lib.h | 11 | ||||
-rw-r--r-- | src/util/time.c | 36 |
6 files changed, 375 insertions, 107 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h index e11b0aa74..0a656e1e9 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -84,6 +84,11 @@ | |||
84 | #define BLOOMFILTER_K 16 | 84 | #define BLOOMFILTER_K 16 |
85 | 85 | ||
86 | /** | 86 | /** |
87 | * Number of availability trials we perform per search result. | ||
88 | */ | ||
89 | #define AVAILABILITY_TRIALS_MAX 8 | ||
90 | |||
91 | /** | ||
87 | * By how much (in ms) do we decrement the TTL | 92 | * By how much (in ms) do we decrement the TTL |
88 | * at each hop? | 93 | * at each hop? |
89 | */ | 94 | */ |
@@ -560,6 +565,28 @@ void | |||
560 | GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh); | 565 | GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh); |
561 | 566 | ||
562 | 567 | ||
568 | |||
569 | /** | ||
570 | * Notification of FS that a search probe has made progress. | ||
571 | * This function is used INSTEAD of the client's event handler | ||
572 | * for downloads where the GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. | ||
573 | * | ||
574 | * @param cls closure, always NULL (!), actual closure | ||
575 | * is in the client-context of the info struct | ||
576 | * @param info details about the event, specifying the event type | ||
577 | * and various bits about the event | ||
578 | * @return client-context (for the next progress call | ||
579 | * for this operation; should be set to NULL for | ||
580 | * SUSPEND and STOPPED events). The value returned | ||
581 | * will be passed to future callbacks in the respective | ||
582 | * field in the GNUNET_FS_ProgressInfo struct. | ||
583 | */ | ||
584 | void* | ||
585 | GNUNET_FS_search_probe_progress_ (void *cls, | ||
586 | const struct GNUNET_FS_ProgressInfo *info); | ||
587 | |||
588 | |||
589 | |||
563 | /** | 590 | /** |
564 | * Master context for most FS operations. | 591 | * Master context for most FS operations. |
565 | */ | 592 | */ |
@@ -799,16 +826,14 @@ struct GNUNET_FS_UnindexContext | |||
799 | char *filename; | 826 | char *filename; |
800 | 827 | ||
801 | /** | 828 | /** |
802 | * Connection to the FS service, | 829 | * Connection to the FS service, only valid during the |
803 | * only valid during the UNINDEX_STATE_FS_NOTIFY | 830 | * UNINDEX_STATE_FS_NOTIFY phase. |
804 | * phase. | ||
805 | */ | 831 | */ |
806 | struct GNUNET_CLIENT_Connection *client; | 832 | struct GNUNET_CLIENT_Connection *client; |
807 | 833 | ||
808 | /** | 834 | /** |
809 | * Connection to the datastore service, | 835 | * Connection to the datastore service, only valid during the |
810 | * only valid during the UNINDEX_STATE_DS_NOTIFY | 836 | * UNINDEX_STATE_DS_NOTIFY phase. |
811 | * phase. | ||
812 | */ | 837 | */ |
813 | struct GNUNET_DATASTORE_Handle *dsh; | 838 | struct GNUNET_DATASTORE_Handle *dsh; |
814 | 839 | ||
@@ -838,8 +863,7 @@ struct GNUNET_FS_UnindexContext | |||
838 | struct GNUNET_TIME_Absolute start_time; | 863 | struct GNUNET_TIME_Absolute start_time; |
839 | 864 | ||
840 | /** | 865 | /** |
841 | * Hash of the file's contents (once | 866 | * Hash of the file's contents (once computed). |
842 | * computed). | ||
843 | */ | 867 | */ |
844 | GNUNET_HashCode file_id; | 868 | GNUNET_HashCode file_id; |
845 | 869 | ||
@@ -858,8 +882,12 @@ struct SearchResult | |||
858 | { | 882 | { |
859 | 883 | ||
860 | /** | 884 | /** |
861 | * URI to which this search result | 885 | * Search context this result belongs to. |
862 | * refers to. | 886 | */ |
887 | struct GNUNET_FS_SearchContext *sc; | ||
888 | |||
889 | /** | ||
890 | * URI to which this search result refers to. | ||
863 | */ | 891 | */ |
864 | struct GNUNET_FS_Uri *uri; | 892 | struct GNUNET_FS_Uri *uri; |
865 | 893 | ||
@@ -874,43 +902,49 @@ struct SearchResult | |||
874 | void *client_info; | 902 | void *client_info; |
875 | 903 | ||
876 | /** | 904 | /** |
877 | * ID of a job that is currently probing | 905 | * ID of a job that is currently probing this results' availability |
878 | * this results' availability (NULL if we | 906 | * (NULL if we are not currently probing). |
879 | * are not currently probing). | ||
880 | */ | 907 | */ |
881 | struct GNUNET_FS_DownloadContext *probe_ctx; | 908 | struct GNUNET_FS_DownloadContext *probe_ctx; |
882 | 909 | ||
883 | /** | 910 | /** |
884 | * ID of the task that will clean up the probe_ctx | 911 | * ID of the task that will clean up the probe_ctx should it not |
885 | * should it not complete on time (and that will | 912 | * complete on time (and that will need to be cancelled if we clean |
886 | * need to be cancelled if we clean up the search | 913 | * up the search result before then). |
887 | * result before then). | ||
888 | */ | 914 | */ |
889 | GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; | 915 | GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; |
890 | 916 | ||
891 | /** | 917 | /** |
892 | * Number of mandatory keywords for which | 918 | * When did the current probe become active? |
893 | * we have NOT yet found the search result; | 919 | */ |
894 | * when this value hits zero, the search | 920 | struct GNUNET_TIME_Absolute probe_active_time; |
895 | * result is given to the callback. | 921 | |
922 | /** | ||
923 | * How much longer should we run the current probe before giving up? | ||
924 | */ | ||
925 | struct GNUNET_TIME_Relative remaining_probe_time; | ||
926 | |||
927 | /** | ||
928 | * Number of mandatory keywords for which we have NOT yet found the | ||
929 | * search result; when this value hits zero, the search result is | ||
930 | * given to the callback. | ||
896 | */ | 931 | */ |
897 | uint32_t mandatory_missing; | 932 | uint32_t mandatory_missing; |
898 | 933 | ||
899 | /** | 934 | /** |
900 | * Number of optional keywords under which | 935 | * Number of optional keywords under which this result was also |
901 | * this result was also found. | 936 | * found. |
902 | */ | 937 | */ |
903 | uint32_t optional_support; | 938 | uint32_t optional_support; |
904 | 939 | ||
905 | /** | 940 | /** |
906 | * Number of availability tests that | 941 | * Number of availability tests that have succeeded for this result. |
907 | * have succeeded for this result. | ||
908 | */ | 942 | */ |
909 | uint32_t availability_success; | 943 | uint32_t availability_success; |
910 | 944 | ||
911 | /** | 945 | /** |
912 | * Number of availability trials that we | 946 | * Number of availability trials that we have performed for this |
913 | * have performed for this search result. | 947 | * search result. |
914 | */ | 948 | */ |
915 | uint32_t availability_trials; | 949 | uint32_t availability_trials; |
916 | 950 | ||
@@ -969,36 +1003,32 @@ struct GNUNET_FS_SearchContext | |||
969 | struct GNUNET_FS_Uri *uri; | 1003 | struct GNUNET_FS_Uri *uri; |
970 | 1004 | ||
971 | /** | 1005 | /** |
972 | * For update-searches, link to the | 1006 | * For update-searches, link to the base-SKS search that triggered |
973 | * base-SKS search that triggered the | 1007 | * the update search; otherwise NULL. |
974 | * update search; otherwise NULL. | ||
975 | */ | 1008 | */ |
976 | struct GNUNET_FS_SearchContext *parent; | 1009 | struct GNUNET_FS_SearchContext *parent; |
977 | 1010 | ||
978 | /** | 1011 | /** |
979 | * For update-searches, link to the | 1012 | * For update-searches, link to the first child search that |
980 | * first child search that triggered the | 1013 | * triggered the update search; otherwise NULL. |
981 | * update search; otherwise NULL. | ||
982 | */ | 1014 | */ |
983 | struct GNUNET_FS_SearchContext *child_head; | 1015 | struct GNUNET_FS_SearchContext *child_head; |
984 | 1016 | ||
985 | /** | 1017 | /** |
986 | * For update-searches, link to the | 1018 | * For update-searches, link to the last child search that triggered |
987 | * last child search that triggered the | 1019 | * the update search; otherwise NULL. |
988 | * update search; otherwise NULL. | ||
989 | */ | 1020 | */ |
990 | struct GNUNET_FS_SearchContext *child_tail; | 1021 | struct GNUNET_FS_SearchContext *child_tail; |
991 | 1022 | ||
992 | /** | 1023 | /** |
993 | * For update-searches, link to the | 1024 | * For update-searches, link to the next child belonging to the same |
994 | * next child belonging to the same parent. | 1025 | * parent. |
995 | */ | 1026 | */ |
996 | struct GNUNET_FS_SearchContext *next; | 1027 | struct GNUNET_FS_SearchContext *next; |
997 | 1028 | ||
998 | /** | 1029 | /** |
999 | * For update-searches, link to the | 1030 | * For update-searches, link to the previous child belonging to the |
1000 | * previous child belonging to the same | 1031 | * same parent. |
1001 | * parent. | ||
1002 | */ | 1032 | */ |
1003 | struct GNUNET_FS_SearchContext *prev; | 1033 | struct GNUNET_FS_SearchContext *prev; |
1004 | 1034 | ||
@@ -1021,9 +1051,8 @@ struct GNUNET_FS_SearchContext | |||
1021 | struct GNUNET_CONTAINER_MultiHashMap *master_result_map; | 1051 | struct GNUNET_CONTAINER_MultiHashMap *master_result_map; |
1022 | 1052 | ||
1023 | /** | 1053 | /** |
1024 | * Per-keyword information for a keyword search. | 1054 | * Per-keyword information for a keyword search. This array will |
1025 | * This array will have exactly as many entries | 1055 | * have exactly as many entries as there were keywords. |
1026 | * as there were keywords. | ||
1027 | */ | 1056 | */ |
1028 | struct SearchRequestEntry *requests; | 1057 | struct SearchRequestEntry *requests; |
1029 | 1058 | ||
@@ -1033,12 +1062,10 @@ struct GNUNET_FS_SearchContext | |||
1033 | struct GNUNET_TIME_Absolute start_time; | 1062 | struct GNUNET_TIME_Absolute start_time; |
1034 | 1063 | ||
1035 | /** | 1064 | /** |
1036 | * ID of a task that is using this struct | 1065 | * ID of a task that is using this struct and that must be cancelled |
1037 | * and that must be cancelled when the search | 1066 | * when the search is being stopped (if not |
1038 | * is being stopped (if not GNUNET_SCHEDULER_NO_TASK). | 1067 | * GNUNET_SCHEDULER_NO_TASK). Used for the task that adds some |
1039 | * Used for the task that adds some artificial | 1068 | * artificial delay when trying to reconnect to the FS service. |
1040 | * delay when trying to reconnect to the FS | ||
1041 | * service. | ||
1042 | */ | 1069 | */ |
1043 | GNUNET_SCHEDULER_TaskIdentifier task; | 1070 | GNUNET_SCHEDULER_TaskIdentifier task; |
1044 | 1071 | ||
@@ -1051,6 +1078,8 @@ struct GNUNET_FS_SearchContext | |||
1051 | * Number of mandatory keywords in this query. | 1078 | * Number of mandatory keywords in this query. |
1052 | */ | 1079 | */ |
1053 | uint32_t mandatory_count; | 1080 | uint32_t mandatory_count; |
1081 | |||
1082 | |||
1054 | }; | 1083 | }; |
1055 | 1084 | ||
1056 | 1085 | ||
@@ -1060,8 +1089,7 @@ struct GNUNET_FS_SearchContext | |||
1060 | struct DownloadRequest | 1089 | struct DownloadRequest |
1061 | { | 1090 | { |
1062 | /** | 1091 | /** |
1063 | * While pending, we keep all download requests | 1092 | * While pending, we keep all download requests in a linked list. |
1064 | * in a linked list. | ||
1065 | */ | 1093 | */ |
1066 | struct DownloadRequest *next; | 1094 | struct DownloadRequest *next; |
1067 | 1095 | ||
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index 424aaf5d4..14e6266f8 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c | |||
@@ -23,8 +23,9 @@ | |||
23 | * @author Christian Grothoff | 23 | * @author Christian Grothoff |
24 | * | 24 | * |
25 | * TODO: | 25 | * TODO: |
26 | * - location URI suppport (can wait, easy) | ||
27 | * - persistence (can wait) | 26 | * - persistence (can wait) |
27 | * - location URI suppport (can wait, easy) | ||
28 | * - different priority for scheduling probe downloads? | ||
28 | * - check if iblocks can be computed from existing blocks (can wait, hard) | 29 | * - check if iblocks can be computed from existing blocks (can wait, hard) |
29 | */ | 30 | */ |
30 | #include "platform.h" | 31 | #include "platform.h" |
@@ -137,8 +138,8 @@ compute_dblock_offset (uint64_t offset, | |||
137 | 138 | ||
138 | 139 | ||
139 | /** | 140 | /** |
140 | * Fill in all of the generic fields for | 141 | * Fill in all of the generic fields for a download event and call the |
141 | * a download event. | 142 | * callback. |
142 | * | 143 | * |
143 | * @param pi structure to fill in | 144 | * @param pi structure to fill in |
144 | * @param dc overall download context | 145 | * @param dc overall download context |
@@ -168,6 +169,12 @@ make_download_status (struct GNUNET_FS_ProgressInfo *pi, | |||
168 | = GNUNET_TIME_calculate_eta (dc->start_time, | 169 | = GNUNET_TIME_calculate_eta (dc->start_time, |
169 | dc->completed, | 170 | dc->completed, |
170 | dc->length); | 171 | dc->length); |
172 | if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) | ||
173 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | ||
174 | pi); | ||
175 | else | ||
176 | dc->client_info = GNUNET_FS_search_probe_progress_ (NULL, | ||
177 | pi); | ||
171 | } | 178 | } |
172 | 179 | ||
173 | /** | 180 | /** |
@@ -624,8 +631,6 @@ check_completed (struct GNUNET_FS_DownloadContext *dc) | |||
624 | /* signal completion */ | 631 | /* signal completion */ |
625 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; | 632 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; |
626 | make_download_status (&pi, dc); | 633 | make_download_status (&pi, dc); |
627 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | ||
628 | &pi); | ||
629 | if (dc->parent != NULL) | 634 | if (dc->parent != NULL) |
630 | check_completed (dc->parent); | 635 | check_completed (dc->parent); |
631 | } | 636 | } |
@@ -847,10 +852,8 @@ process_result_with_request (void *cls, | |||
847 | dc->emsg = GNUNET_strdup ("Internal error or bogus download URI"); | 852 | dc->emsg = GNUNET_strdup ("Internal error or bogus download URI"); |
848 | /* signal error */ | 853 | /* signal error */ |
849 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; | 854 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; |
850 | make_download_status (&pi, dc); | ||
851 | pi.value.download.specifics.error.message = dc->emsg; | 855 | pi.value.download.specifics.error.message = dc->emsg; |
852 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | 856 | make_download_status (&pi, dc); |
853 | &pi); | ||
854 | /* abort all pending requests */ | 857 | /* abort all pending requests */ |
855 | if (NULL != dc->th) | 858 | if (NULL != dc->th) |
856 | { | 859 | { |
@@ -913,11 +916,8 @@ process_result_with_request (void *cls, | |||
913 | 916 | ||
914 | /* signal error */ | 917 | /* signal error */ |
915 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; | 918 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; |
916 | make_download_status (&pi, dc); | ||
917 | pi.value.download.specifics.error.message = emsg; | 919 | pi.value.download.specifics.error.message = emsg; |
918 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | 920 | make_download_status (&pi, dc); |
919 | &pi); | ||
920 | |||
921 | /* abort all pending requests */ | 921 | /* abort all pending requests */ |
922 | if (NULL != dc->th) | 922 | if (NULL != dc->th) |
923 | { | 923 | { |
@@ -961,13 +961,11 @@ process_result_with_request (void *cls, | |||
961 | 961 | ||
962 | } | 962 | } |
963 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS; | 963 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS; |
964 | make_download_status (&pi, dc); | ||
965 | pi.value.download.specifics.progress.data = pt; | 964 | pi.value.download.specifics.progress.data = pt; |
966 | pi.value.download.specifics.progress.offset = sm->offset; | 965 | pi.value.download.specifics.progress.offset = sm->offset; |
967 | pi.value.download.specifics.progress.data_len = prc->size; | 966 | pi.value.download.specifics.progress.data_len = prc->size; |
968 | pi.value.download.specifics.progress.depth = sm->depth; | 967 | pi.value.download.specifics.progress.depth = sm->depth; |
969 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | 968 | make_download_status (&pi, dc); |
970 | &pi); | ||
971 | GNUNET_assert (dc->completed <= dc->length); | 969 | GNUNET_assert (dc->completed <= dc->length); |
972 | if (dc->completed == dc->length) | 970 | if (dc->completed == dc->length) |
973 | { | 971 | { |
@@ -999,8 +997,6 @@ process_result_with_request (void *cls, | |||
999 | /* signal completion */ | 997 | /* signal completion */ |
1000 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; | 998 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; |
1001 | make_download_status (&pi, dc); | 999 | make_download_status (&pi, dc); |
1002 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | ||
1003 | &pi); | ||
1004 | if (dc->parent != NULL) | 1000 | if (dc->parent != NULL) |
1005 | check_completed (dc->parent); | 1001 | check_completed (dc->parent); |
1006 | } | 1002 | } |
@@ -1296,8 +1292,6 @@ activate_fs_download (void *cls, | |||
1296 | GNUNET_TIME_UNIT_FOREVER_REL); | 1292 | GNUNET_TIME_UNIT_FOREVER_REL); |
1297 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; | 1293 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; |
1298 | make_download_status (&pi, dc); | 1294 | make_download_status (&pi, dc); |
1299 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | ||
1300 | &pi); | ||
1301 | GNUNET_CONTAINER_multihashmap_iterate (dc->active, | 1295 | GNUNET_CONTAINER_multihashmap_iterate (dc->active, |
1302 | &retry_entry, | 1296 | &retry_entry, |
1303 | dc); | 1297 | dc); |
@@ -1336,8 +1330,6 @@ deactivate_fs_download (void *cls) | |||
1336 | } | 1330 | } |
1337 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE; | 1331 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE; |
1338 | make_download_status (&pi, dc); | 1332 | make_download_status (&pi, dc); |
1339 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | ||
1340 | &pi); | ||
1341 | } | 1333 | } |
1342 | 1334 | ||
1343 | 1335 | ||
@@ -1464,10 +1456,8 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, | |||
1464 | #endif | 1456 | #endif |
1465 | // FIXME: make persistent | 1457 | // FIXME: make persistent |
1466 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_START; | 1458 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_START; |
1467 | make_download_status (&pi, dc); | ||
1468 | pi.value.download.specifics.start.meta = meta; | 1459 | pi.value.download.specifics.start.meta = meta; |
1469 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | 1460 | make_download_status (&pi, dc); |
1470 | &pi); | ||
1471 | schedule_block_download (dc, | 1461 | schedule_block_download (dc, |
1472 | &dc->uri->data.chk.chk, | 1462 | &dc->uri->data.chk.chk, |
1473 | 0, | 1463 | 0, |
@@ -1527,9 +1517,6 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, | |||
1527 | 1517 | ||
1528 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED; | 1518 | pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED; |
1529 | make_download_status (&pi, dc); | 1519 | make_download_status (&pi, dc); |
1530 | dc->client_info = dc->h->upcb (dc->h->upcb_cls, | ||
1531 | &pi); | ||
1532 | |||
1533 | if (GNUNET_SCHEDULER_NO_TASK != dc->task) | 1520 | if (GNUNET_SCHEDULER_NO_TASK != dc->task) |
1534 | GNUNET_SCHEDULER_cancel (dc->h->sched, | 1521 | GNUNET_SCHEDULER_cancel (dc->h->sched, |
1535 | dc->task); | 1522 | dc->task); |
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 812f2b224..2c8022237 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c | |||
@@ -46,8 +46,9 @@ | |||
46 | * | 46 | * |
47 | * @param pi structure to fill in | 47 | * @param pi structure to fill in |
48 | * @param sc overall search context | 48 | * @param sc overall search context |
49 | * @return value returned by the callback | ||
49 | */ | 50 | */ |
50 | static void | 51 | static void * |
51 | make_search_status (struct GNUNET_FS_ProgressInfo *pi, | 52 | make_search_status (struct GNUNET_FS_ProgressInfo *pi, |
52 | struct GNUNET_FS_SearchContext *sc) | 53 | struct GNUNET_FS_SearchContext *sc) |
53 | { | 54 | { |
@@ -60,6 +61,8 @@ make_search_status (struct GNUNET_FS_ProgressInfo *pi, | |||
60 | = sc->uri; | 61 | = sc->uri; |
61 | pi->value.search.duration = GNUNET_TIME_absolute_get_duration (sc->start_time); | 62 | pi->value.search.duration = GNUNET_TIME_absolute_get_duration (sc->start_time); |
62 | pi->value.search.anonymity = sc->anonymity; | 63 | pi->value.search.anonymity = sc->anonymity; |
64 | return sc->h->upcb (sc->h->upcb_cls, | ||
65 | pi); | ||
63 | } | 66 | } |
64 | 67 | ||
65 | 68 | ||
@@ -103,11 +106,9 @@ notify_client_chk_result (struct GNUNET_FS_SearchContext *sc, | |||
103 | struct GNUNET_FS_ProgressInfo pi; | 106 | struct GNUNET_FS_ProgressInfo pi; |
104 | 107 | ||
105 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT; | 108 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT; |
106 | make_search_status (&pi, sc); | ||
107 | pi.value.search.specifics.result.meta = sr->meta; | 109 | pi.value.search.specifics.result.meta = sr->meta; |
108 | pi.value.search.specifics.result.uri = sr->uri; | 110 | pi.value.search.specifics.result.uri = sr->uri; |
109 | sr->client_info = sc->h->upcb (sc->h->upcb_cls, | 111 | sr->client_info = make_search_status (&pi, sc); |
110 | &pi); | ||
111 | } | 112 | } |
112 | 113 | ||
113 | 114 | ||
@@ -125,7 +126,6 @@ notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, | |||
125 | struct GNUNET_FS_ProgressInfo pi; | 126 | struct GNUNET_FS_ProgressInfo pi; |
126 | 127 | ||
127 | pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; | 128 | pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; |
128 | make_search_status (&pi, sc); | ||
129 | pi.value.search.specifics.update.cctx = sr->client_info; | 129 | pi.value.search.specifics.update.cctx = sr->client_info; |
130 | pi.value.search.specifics.update.meta = sr->meta; | 130 | pi.value.search.specifics.update.meta = sr->meta; |
131 | pi.value.search.specifics.update.uri = sr->uri; | 131 | pi.value.search.specifics.update.uri = sr->uri; |
@@ -135,8 +135,7 @@ notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, | |||
135 | = sr->availability_trials; | 135 | = sr->availability_trials; |
136 | pi.value.search.specifics.update.applicability_rank | 136 | pi.value.search.specifics.update.applicability_rank |
137 | = sr->optional_support; | 137 | = sr->optional_support; |
138 | sr->client_info = sc->h->upcb (sc->h->upcb_cls, | 138 | sr->client_info = make_search_status (&pi, sc); |
139 | &pi); | ||
140 | } | 139 | } |
141 | 140 | ||
142 | 141 | ||
@@ -184,6 +183,206 @@ get_result_present (void *cls, | |||
184 | 183 | ||
185 | 184 | ||
186 | /** | 185 | /** |
186 | * Start download probes for the given search result. | ||
187 | * | ||
188 | * @param sr the search result | ||
189 | */ | ||
190 | static void | ||
191 | start_probe (struct SearchResult *sr); | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Signal result of last probe to client and then schedule next | ||
196 | * probe. | ||
197 | */ | ||
198 | static void | ||
199 | signal_probe_result (struct SearchResult *sr) | ||
200 | { | ||
201 | struct GNUNET_FS_ProgressInfo pi; | ||
202 | |||
203 | pi.status = GNUNET_FS_STATUS_SEARCH_START; | ||
204 | pi.value.search.specifics.update.cctx = sr->client_info; | ||
205 | pi.value.search.specifics.update.meta = sr->meta; | ||
206 | pi.value.search.specifics.update.uri = sr->uri; | ||
207 | pi.value.search.specifics.update.availability_rank = sr->availability_success; | ||
208 | pi.value.search.specifics.update.availability_certainty = sr->availability_trials; | ||
209 | pi.value.search.specifics.update.applicability_rank = sr->optional_support; | ||
210 | sr->sc->client_info = make_search_status (&pi, sr->sc); | ||
211 | start_probe (sr); | ||
212 | } | ||
213 | |||
214 | |||
215 | /** | ||
216 | * Handle the case where we have failed to receive a response for our probe. | ||
217 | * | ||
218 | * @param cls our 'struct SearchResult*' | ||
219 | * @param tc scheduler context | ||
220 | */ | ||
221 | static void | ||
222 | probe_failure_handler (void *cls, | ||
223 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
224 | { | ||
225 | struct SearchResult *sr = cls; | ||
226 | sr->availability_trials++; | ||
227 | signal_probe_result (sr); | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Handle the case where we have gotten a response for our probe. | ||
233 | * | ||
234 | * @param cls our 'struct SearchResult*' | ||
235 | * @param tc scheduler context | ||
236 | */ | ||
237 | static void | ||
238 | probe_success_handler (void *cls, | ||
239 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
240 | { | ||
241 | struct SearchResult *sr = cls; | ||
242 | sr->availability_trials++; | ||
243 | sr->availability_success++; | ||
244 | signal_probe_result (sr); | ||
245 | } | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Notification of FS that a search probe has made progress. | ||
250 | * This function is used INSTEAD of the client's event handler | ||
251 | * for downloads where the GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. | ||
252 | * | ||
253 | * @param cls closure, always NULL (!), actual closure | ||
254 | * is in the client-context of the info struct | ||
255 | * @param info details about the event, specifying the event type | ||
256 | * and various bits about the event | ||
257 | * @return client-context (for the next progress call | ||
258 | * for this operation; should be set to NULL for | ||
259 | * SUSPEND and STOPPED events). The value returned | ||
260 | * will be passed to future callbacks in the respective | ||
261 | * field in the GNUNET_FS_ProgressInfo struct. | ||
262 | */ | ||
263 | void* | ||
264 | GNUNET_FS_search_probe_progress_ (void *cls, | ||
265 | const struct GNUNET_FS_ProgressInfo *info) | ||
266 | { | ||
267 | struct SearchResult *sr = info->value.download.cctx; | ||
268 | struct GNUNET_TIME_Relative dur; | ||
269 | |||
270 | switch (info->status) | ||
271 | { | ||
272 | case GNUNET_FS_STATUS_DOWNLOAD_START: | ||
273 | /* ignore */ | ||
274 | break; | ||
275 | case GNUNET_FS_STATUS_DOWNLOAD_RESUME: | ||
276 | /* probes should never be resumed */ | ||
277 | GNUNET_assert (0); | ||
278 | break; | ||
279 | case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: | ||
280 | /* probes should never be suspended */ | ||
281 | GNUNET_break (0); | ||
282 | break; | ||
283 | case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: | ||
284 | /* ignore */ | ||
285 | break; | ||
286 | case GNUNET_FS_STATUS_DOWNLOAD_ERROR: | ||
287 | if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) | ||
288 | { | ||
289 | GNUNET_SCHEDULER_cancel (sr->sc->h->sched, | ||
290 | sr->probe_cancel_task); | ||
291 | sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; | ||
292 | } | ||
293 | sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->sc->h->sched, | ||
294 | sr->remaining_probe_time, | ||
295 | &probe_failure_handler, | ||
296 | sr); | ||
297 | break; | ||
298 | case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: | ||
299 | if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) | ||
300 | { | ||
301 | GNUNET_SCHEDULER_cancel (sr->sc->h->sched, | ||
302 | sr->probe_cancel_task); | ||
303 | sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; | ||
304 | } | ||
305 | sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->sc->h->sched, | ||
306 | sr->remaining_probe_time, | ||
307 | &probe_success_handler, | ||
308 | sr); | ||
309 | break; | ||
310 | case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: | ||
311 | /* FIXME: clean up? schedule next probe? or already done? */ | ||
312 | sr = NULL; | ||
313 | break; | ||
314 | case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: | ||
315 | GNUNET_assert (sr->probe_cancel_task == GNUNET_SCHEDULER_NO_TASK); | ||
316 | sr->probe_active_time = GNUNET_TIME_absolute_get (); | ||
317 | sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->sc->h->sched, | ||
318 | sr->remaining_probe_time, | ||
319 | &probe_failure_handler, | ||
320 | sr); | ||
321 | break; | ||
322 | case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: | ||
323 | if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) | ||
324 | { | ||
325 | GNUNET_SCHEDULER_cancel (sr->sc->h->sched, | ||
326 | sr->probe_cancel_task); | ||
327 | sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; | ||
328 | } | ||
329 | dur = GNUNET_TIME_absolute_get_duration (sr->probe_active_time); | ||
330 | sr->remaining_probe_time = GNUNET_TIME_relative_subtract (sr->remaining_probe_time, | ||
331 | dur); | ||
332 | break; | ||
333 | default: | ||
334 | GNUNET_break (0); | ||
335 | return NULL; | ||
336 | } | ||
337 | return sr; | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Start download probes for the given search result. | ||
343 | * | ||
344 | * @param sr the search result | ||
345 | */ | ||
346 | static void | ||
347 | start_probe (struct SearchResult *sr) | ||
348 | { | ||
349 | uint64_t off; | ||
350 | uint64_t len; | ||
351 | |||
352 | if (sr->probe_ctx != NULL) | ||
353 | return; | ||
354 | if (0 == (sr->sc->h->flags & GNUNET_FS_FLAGS_DO_PROBES)) | ||
355 | return; | ||
356 | if (sr->availability_trials > AVAILABILITY_TRIALS_MAX) | ||
357 | return; | ||
358 | len = GNUNET_FS_uri_chk_get_file_size (sr->uri); | ||
359 | if (len == 0) | ||
360 | return; | ||
361 | if ( (len <= DBLOCK_SIZE) && (sr->availability_success > 0)) | ||
362 | return; | ||
363 | off = len / DBLOCK_SIZE; | ||
364 | if (off > 0) | ||
365 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, off); | ||
366 | off *= DBLOCK_SIZE; | ||
367 | if (len - off < DBLOCK_SIZE) | ||
368 | len = len - off; | ||
369 | else | ||
370 | len = DBLOCK_SIZE; | ||
371 | sr->remaining_probe_time = GNUNET_TIME_relative_multiply (sr->sc->h->avg_block_latency, | ||
372 | 2 * (1 + sr->availability_trials)); | ||
373 | sr->probe_ctx = GNUNET_FS_download_start (sr->sc->h, | ||
374 | sr->uri, | ||
375 | sr->meta, | ||
376 | NULL, NULL, | ||
377 | off, len, | ||
378 | sr->sc->anonymity, | ||
379 | GNUNET_FS_DOWNLOAD_NO_TEMPORARIES | | ||
380 | GNUNET_FS_DOWNLOAD_IS_PROBE, | ||
381 | sr, NULL); | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
187 | * We have received a KSK result. Check how it fits in with the | 386 | * We have received a KSK result. Check how it fits in with the |
188 | * overall query and notify the client accordingly. | 387 | * overall query and notify the client accordingly. |
189 | * | 388 | * |
@@ -224,6 +423,7 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, | |||
224 | if (NULL == sr) | 423 | if (NULL == sr) |
225 | { | 424 | { |
226 | sr = GNUNET_malloc (sizeof (struct SearchResult)); | 425 | sr = GNUNET_malloc (sizeof (struct SearchResult)); |
426 | sr->sc = sc; | ||
227 | sr->uri = GNUNET_FS_uri_dup (uri); | 427 | sr->uri = GNUNET_FS_uri_dup (uri); |
228 | sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); | 428 | sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); |
229 | sr->mandatory_missing = sc->mandatory_count; | 429 | sr->mandatory_missing = sc->mandatory_count; |
@@ -247,7 +447,7 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, | |||
247 | notify_client_chk_result (sc, sr); | 447 | notify_client_chk_result (sc, sr); |
248 | else | 448 | else |
249 | notify_client_chk_update (sc, sr); | 449 | notify_client_chk_update (sc, sr); |
250 | /* FIXME: consider starting probes for "sr" */ | 450 | start_probe (sr); |
251 | } | 451 | } |
252 | 452 | ||
253 | 453 | ||
@@ -301,14 +501,14 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, | |||
301 | (void*) uri)) | 501 | (void*) uri)) |
302 | return; /* duplicate result */ | 502 | return; /* duplicate result */ |
303 | sr = GNUNET_malloc (sizeof (struct SearchResult)); | 503 | sr = GNUNET_malloc (sizeof (struct SearchResult)); |
504 | sr->sc = sc; | ||
304 | sr->uri = GNUNET_FS_uri_dup (uri); | 505 | sr->uri = GNUNET_FS_uri_dup (uri); |
305 | sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); | 506 | sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); |
306 | GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, | 507 | GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, |
307 | &key, | 508 | &key, |
308 | sr, | 509 | sr, |
309 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | 510 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); |
310 | /* FIXME: consider starting probes for "sr" */ | 511 | start_probe (sr); |
311 | |||
312 | /* notify client */ | 512 | /* notify client */ |
313 | notify_client_chk_result (sc, sr); | 513 | notify_client_chk_result (sc, sr); |
314 | /* search for updates */ | 514 | /* search for updates */ |
@@ -921,9 +1121,7 @@ search_start (struct GNUNET_FS_Handle *h, | |||
921 | parent->child_tail, | 1121 | parent->child_tail, |
922 | sc); | 1122 | sc); |
923 | pi.status = GNUNET_FS_STATUS_SEARCH_START; | 1123 | pi.status = GNUNET_FS_STATUS_SEARCH_START; |
924 | make_search_status (&pi, sc); | 1124 | sc->client_info = make_search_status (&pi, sc); |
925 | sc->client_info = h->upcb (h->upcb_cls, | ||
926 | &pi); | ||
927 | GNUNET_CLIENT_notify_transmit_ready (client, | 1125 | GNUNET_CLIENT_notify_transmit_ready (client, |
928 | size, | 1126 | size, |
929 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | 1127 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, |
@@ -974,9 +1172,7 @@ GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) | |||
974 | // FIXME: make persistent! | 1172 | // FIXME: make persistent! |
975 | // FIXME: should this freeze all active probes? | 1173 | // FIXME: should this freeze all active probes? |
976 | pi.status = GNUNET_FS_STATUS_SEARCH_PAUSED; | 1174 | pi.status = GNUNET_FS_STATUS_SEARCH_PAUSED; |
977 | make_search_status (&pi, sc); | 1175 | sc->client_info = make_search_status (&pi, sc); |
978 | sc->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
979 | &pi); | ||
980 | } | 1176 | } |
981 | 1177 | ||
982 | 1178 | ||
@@ -995,9 +1191,7 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) | |||
995 | do_reconnect (sc, NULL); | 1191 | do_reconnect (sc, NULL); |
996 | // FIXME: make persistent! | 1192 | // FIXME: make persistent! |
997 | pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; | 1193 | pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; |
998 | make_search_status (&pi, sc); | 1194 | sc->client_info = make_search_status (&pi, sc); |
999 | sc->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
1000 | &pi); | ||
1001 | } | 1195 | } |
1002 | 1196 | ||
1003 | 1197 | ||
@@ -1020,12 +1214,10 @@ search_result_free (void *cls, | |||
1020 | struct GNUNET_FS_ProgressInfo pi; | 1214 | struct GNUNET_FS_ProgressInfo pi; |
1021 | 1215 | ||
1022 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; | 1216 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; |
1023 | make_search_status (&pi, sc); | ||
1024 | pi.value.search.specifics.result_stopped.cctx = sr->client_info; | 1217 | pi.value.search.specifics.result_stopped.cctx = sr->client_info; |
1025 | pi.value.search.specifics.result_stopped.meta = sr->meta; | 1218 | pi.value.search.specifics.result_stopped.meta = sr->meta; |
1026 | pi.value.search.specifics.result_stopped.uri = sr->uri; | 1219 | pi.value.search.specifics.result_stopped.uri = sr->uri; |
1027 | sr->client_info = h->upcb (h->upcb_cls, | 1220 | sr->client_info = make_search_status (&pi, sc); |
1028 | &pi); | ||
1029 | GNUNET_break (NULL == sr->client_info); | 1221 | GNUNET_break (NULL == sr->client_info); |
1030 | 1222 | ||
1031 | GNUNET_FS_uri_destroy (sr->uri); | 1223 | GNUNET_FS_uri_destroy (sr->uri); |
@@ -1066,9 +1258,7 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) | |||
1066 | &search_result_free, | 1258 | &search_result_free, |
1067 | sc); | 1259 | sc); |
1068 | pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; | 1260 | pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; |
1069 | make_search_status (&pi, sc); | 1261 | sc->client_info = make_search_status (&pi, sc); |
1070 | sc->client_info = sc->h->upcb (sc->h->upcb_cls, | ||
1071 | &pi); | ||
1072 | GNUNET_break (NULL == sc->client_info); | 1262 | GNUNET_break (NULL == sc->client_info); |
1073 | if (sc->task != GNUNET_SCHEDULER_NO_TASK) | 1263 | if (sc->task != GNUNET_SCHEDULER_NO_TASK) |
1074 | GNUNET_SCHEDULER_cancel (sc->h->sched, | 1264 | GNUNET_SCHEDULER_cancel (sc->h->sched, |
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index a228d0263..e3c99f3e9 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h | |||
@@ -1455,7 +1455,14 @@ enum GNUNET_FS_Flags | |||
1455 | * Is persistence of operations desired? | 1455 | * Is persistence of operations desired? |
1456 | * (will create SUSPEND/RESUME events). | 1456 | * (will create SUSPEND/RESUME events). |
1457 | */ | 1457 | */ |
1458 | GNUNET_FS_FLAGS_PERSISTENCE = 1 | 1458 | GNUNET_FS_FLAGS_PERSISTENCE = 1, |
1459 | |||
1460 | /** | ||
1461 | * Should we automatically trigger probes for search results | ||
1462 | * to determine availability? | ||
1463 | * (will create GNUNET_FS_STATUS_SEARCH_UPDATE events). | ||
1464 | */ | ||
1465 | GNUNET_FS_FLAGS_DO_PROBES = 2 | ||
1459 | 1466 | ||
1460 | }; | 1467 | }; |
1461 | 1468 | ||
@@ -2252,7 +2259,16 @@ enum GNUNET_FS_DownloadOptions | |||
2252 | * Do not append temporary data to | 2259 | * Do not append temporary data to |
2253 | * the target file (for the IBlocks). | 2260 | * the target file (for the IBlocks). |
2254 | */ | 2261 | */ |
2255 | GNUNET_FS_DOWNLOAD_NO_TEMPORARIES = 2 | 2262 | GNUNET_FS_DOWNLOAD_NO_TEMPORARIES = 2, |
2263 | |||
2264 | /** | ||
2265 | * Internal option used to flag this download as a 'probe' for a | ||
2266 | * search result. Impacts the priority with which the download is | ||
2267 | * run and causes signalling callbacks to be done differently. | ||
2268 | * Also, probe downloads are not serialized on suspension. Normal | ||
2269 | * clients should not use this! | ||
2270 | */ | ||
2271 | GNUNET_FS_DOWNLOAD_IS_PROBE = (1<<31) | ||
2256 | 2272 | ||
2257 | }; | 2273 | }; |
2258 | 2274 | ||
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h index fa443a463..b9c2d92f0 100644 --- a/src/include/gnunet_time_lib.h +++ b/src/include/gnunet_time_lib.h | |||
@@ -353,6 +353,17 @@ struct GNUNET_TIME_Relative GNUNET_TIME_relative_add (struct | |||
353 | GNUNET_TIME_Relative | 353 | GNUNET_TIME_Relative |
354 | a2); | 354 | a2); |
355 | 355 | ||
356 | /** | ||
357 | * Subtract relative timestamp from the other. | ||
358 | * | ||
359 | * @param a1 first timestamp | ||
360 | * @param a2 second timestamp | ||
361 | * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise | ||
362 | */ | ||
363 | struct GNUNET_TIME_Relative | ||
364 | GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, | ||
365 | struct GNUNET_TIME_Relative a2); | ||
366 | |||
356 | 367 | ||
357 | /** | 368 | /** |
358 | * Convert relative time to network byte order. | 369 | * Convert relative time to network byte order. |
diff --git a/src/util/time.c b/src/util/time.c index ce2f9517f..6eccf4d9a 100644 --- a/src/util/time.c +++ b/src/util/time.c | |||
@@ -345,6 +345,8 @@ GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, | |||
345 | /** | 345 | /** |
346 | * Add relative times together. | 346 | * Add relative times together. |
347 | * | 347 | * |
348 | * @param a1 first timestamp | ||
349 | * @param a2 second timestamp | ||
348 | * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise | 350 | * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise |
349 | */ | 351 | */ |
350 | struct GNUNET_TIME_Relative | 352 | struct GNUNET_TIME_Relative |
@@ -366,7 +368,32 @@ GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1, | |||
366 | 368 | ||
367 | 369 | ||
368 | /** | 370 | /** |
371 | * Subtract relative timestamp from the other. | ||
372 | * | ||
373 | * @param a1 first timestamp | ||
374 | * @param a2 second timestamp | ||
375 | * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise | ||
376 | */ | ||
377 | struct GNUNET_TIME_Relative | ||
378 | GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, | ||
379 | struct GNUNET_TIME_Relative a2) | ||
380 | { | ||
381 | struct GNUNET_TIME_Relative ret; | ||
382 | |||
383 | if (a2.value >= a1.value) | ||
384 | return GNUNET_TIME_relative_get_zero (); | ||
385 | if (a1.value == (uint64_t) - 1LL) | ||
386 | return GNUNET_TIME_relative_get_forever (); | ||
387 | ret.value = a1.value - a2.value; | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
369 | * Convert relative time to network byte order. | 393 | * Convert relative time to network byte order. |
394 | * | ||
395 | * @param a time to convert | ||
396 | * @return time in network byte order | ||
370 | */ | 397 | */ |
371 | struct GNUNET_TIME_RelativeNBO | 398 | struct GNUNET_TIME_RelativeNBO |
372 | GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) | 399 | GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) |
@@ -378,6 +405,9 @@ GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) | |||
378 | 405 | ||
379 | /** | 406 | /** |
380 | * Convert relative time from network byte order. | 407 | * Convert relative time from network byte order. |
408 | * | ||
409 | * @param a time to convert | ||
410 | * @return time in host byte order | ||
381 | */ | 411 | */ |
382 | struct GNUNET_TIME_Relative | 412 | struct GNUNET_TIME_Relative |
383 | GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) | 413 | GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) |
@@ -390,6 +420,9 @@ GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) | |||
390 | 420 | ||
391 | /** | 421 | /** |
392 | * Convert absolute time to network byte order. | 422 | * Convert absolute time to network byte order. |
423 | * | ||
424 | * @param a time to convert | ||
425 | * @return time in network byte order | ||
393 | */ | 426 | */ |
394 | struct GNUNET_TIME_AbsoluteNBO | 427 | struct GNUNET_TIME_AbsoluteNBO |
395 | GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) | 428 | GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) |
@@ -401,6 +434,9 @@ GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) | |||
401 | 434 | ||
402 | /** | 435 | /** |
403 | * Convert absolute time from network byte order. | 436 | * Convert absolute time from network byte order. |
437 | * | ||
438 | * @param a time to convert | ||
439 | * @return time in host byte order | ||
404 | */ | 440 | */ |
405 | struct GNUNET_TIME_Absolute | 441 | struct GNUNET_TIME_Absolute |
406 | GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) | 442 | GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) |