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/fs/fs_search.c | |
parent | 684476aafc7c225d565295fdac4a00ee8bfc207f (diff) | |
download | gnunet-ae300a58c5bdfcadca8837a1e23abe3e34032209.tar.gz gnunet-ae300a58c5bdfcadca8837a1e23abe3e34032209.zip |
adding availability probes for search results
Diffstat (limited to 'src/fs/fs_search.c')
-rw-r--r-- | src/fs/fs_search.c | 240 |
1 files changed, 215 insertions, 25 deletions
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, |