aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-28 12:10:06 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-28 12:10:06 +0000
commitae300a58c5bdfcadca8837a1e23abe3e34032209 (patch)
treec90e62d0c32575dce3ac763fa1f67ca858823a5e /src
parent684476aafc7c225d565295fdac4a00ee8bfc207f (diff)
downloadgnunet-ae300a58c5bdfcadca8837a1e23abe3e34032209.tar.gz
gnunet-ae300a58c5bdfcadca8837a1e23abe3e34032209.zip
adding availability probes for search results
Diffstat (limited to 'src')
-rw-r--r--src/fs/fs.h134
-rw-r--r--src/fs/fs_download.c41
-rw-r--r--src/fs/fs_search.c240
-rw-r--r--src/include/gnunet_fs_service.h20
-rw-r--r--src/include/gnunet_time_lib.h11
-rw-r--r--src/util/time.c36
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
560GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh); 565GNUNET_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 */
584void*
585GNUNET_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
1060struct DownloadRequest 1089struct 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 */
50static void 51static void *
51make_search_status (struct GNUNET_FS_ProgressInfo *pi, 52make_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 */
190static void
191start_probe (struct SearchResult *sr);
192
193
194/**
195 * Signal result of last probe to client and then schedule next
196 * probe.
197 */
198static void
199signal_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 */
221static void
222probe_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 */
237static void
238probe_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 */
263void*
264GNUNET_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 */
346static void
347start_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 */
363struct GNUNET_TIME_Relative
364GNUNET_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 */
350struct GNUNET_TIME_Relative 352struct 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 */
377struct GNUNET_TIME_Relative
378GNUNET_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 */
371struct GNUNET_TIME_RelativeNBO 398struct GNUNET_TIME_RelativeNBO
372GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) 399GNUNET_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 */
382struct GNUNET_TIME_Relative 412struct GNUNET_TIME_Relative
383GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) 413GNUNET_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 */
394struct GNUNET_TIME_AbsoluteNBO 427struct GNUNET_TIME_AbsoluteNBO
395GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) 428GNUNET_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 */
405struct GNUNET_TIME_Absolute 441struct GNUNET_TIME_Absolute
406GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) 442GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)