aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_search.c
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/fs/fs_search.c
parent684476aafc7c225d565295fdac4a00ee8bfc207f (diff)
downloadgnunet-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.c240
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 */
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,