From ae300a58c5bdfcadca8837a1e23abe3e34032209 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 28 Apr 2010 12:10:06 +0000 Subject: adding availability probes for search results --- src/fs/fs.h | 134 +++++++++++++--------- src/fs/fs_download.c | 41 +++---- src/fs/fs_search.c | 240 +++++++++++++++++++++++++++++++++++----- src/include/gnunet_fs_service.h | 20 +++- src/include/gnunet_time_lib.h | 11 ++ src/util/time.c | 36 ++++++ 6 files changed, 375 insertions(+), 107 deletions(-) (limited to 'src') 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 @@ -83,6 +83,11 @@ */ #define BLOOMFILTER_K 16 +/** + * Number of availability trials we perform per search result. + */ +#define AVAILABILITY_TRIALS_MAX 8 + /** * By how much (in ms) do we decrement the TTL * at each hop? @@ -560,6 +565,28 @@ void GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh); + +/** + * Notification of FS that a search probe has made progress. + * This function is used INSTEAD of the client's event handler + * for downloads where the GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. + * + * @param cls closure, always NULL (!), actual closure + * is in the client-context of the info struct + * @param info details about the event, specifying the event type + * and various bits about the event + * @return client-context (for the next progress call + * for this operation; should be set to NULL for + * SUSPEND and STOPPED events). The value returned + * will be passed to future callbacks in the respective + * field in the GNUNET_FS_ProgressInfo struct. + */ +void* +GNUNET_FS_search_probe_progress_ (void *cls, + const struct GNUNET_FS_ProgressInfo *info); + + + /** * Master context for most FS operations. */ @@ -799,16 +826,14 @@ struct GNUNET_FS_UnindexContext char *filename; /** - * Connection to the FS service, - * only valid during the UNINDEX_STATE_FS_NOTIFY - * phase. + * Connection to the FS service, only valid during the + * UNINDEX_STATE_FS_NOTIFY phase. */ struct GNUNET_CLIENT_Connection *client; /** - * Connection to the datastore service, - * only valid during the UNINDEX_STATE_DS_NOTIFY - * phase. + * Connection to the datastore service, only valid during the + * UNINDEX_STATE_DS_NOTIFY phase. */ struct GNUNET_DATASTORE_Handle *dsh; @@ -838,8 +863,7 @@ struct GNUNET_FS_UnindexContext struct GNUNET_TIME_Absolute start_time; /** - * Hash of the file's contents (once - * computed). + * Hash of the file's contents (once computed). */ GNUNET_HashCode file_id; @@ -858,8 +882,12 @@ struct SearchResult { /** - * URI to which this search result - * refers to. + * Search context this result belongs to. + */ + struct GNUNET_FS_SearchContext *sc; + + /** + * URI to which this search result refers to. */ struct GNUNET_FS_Uri *uri; @@ -874,43 +902,49 @@ struct SearchResult void *client_info; /** - * ID of a job that is currently probing - * this results' availability (NULL if we - * are not currently probing). + * ID of a job that is currently probing this results' availability + * (NULL if we are not currently probing). */ struct GNUNET_FS_DownloadContext *probe_ctx; - + /** - * ID of the task that will clean up the probe_ctx - * should it not complete on time (and that will - * need to be cancelled if we clean up the search - * result before then). + * ID of the task that will clean up the probe_ctx should it not + * complete on time (and that will need to be cancelled if we clean + * up the search result before then). */ GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; /** - * Number of mandatory keywords for which - * we have NOT yet found the search result; - * when this value hits zero, the search - * result is given to the callback. + * When did the current probe become active? + */ + struct GNUNET_TIME_Absolute probe_active_time; + + /** + * How much longer should we run the current probe before giving up? + */ + struct GNUNET_TIME_Relative remaining_probe_time; + + /** + * Number of mandatory keywords for which we have NOT yet found the + * search result; when this value hits zero, the search result is + * given to the callback. */ uint32_t mandatory_missing; /** - * Number of optional keywords under which - * this result was also found. + * Number of optional keywords under which this result was also + * found. */ uint32_t optional_support; /** - * Number of availability tests that - * have succeeded for this result. + * Number of availability tests that have succeeded for this result. */ uint32_t availability_success; /** - * Number of availability trials that we - * have performed for this search result. + * Number of availability trials that we have performed for this + * search result. */ uint32_t availability_trials; @@ -969,36 +1003,32 @@ struct GNUNET_FS_SearchContext struct GNUNET_FS_Uri *uri; /** - * For update-searches, link to the - * base-SKS search that triggered the - * update search; otherwise NULL. + * For update-searches, link to the base-SKS search that triggered + * the update search; otherwise NULL. */ struct GNUNET_FS_SearchContext *parent; /** - * For update-searches, link to the - * first child search that triggered the - * update search; otherwise NULL. + * For update-searches, link to the first child search that + * triggered the update search; otherwise NULL. */ struct GNUNET_FS_SearchContext *child_head; /** - * For update-searches, link to the - * last child search that triggered the - * update search; otherwise NULL. + * For update-searches, link to the last child search that triggered + * the update search; otherwise NULL. */ struct GNUNET_FS_SearchContext *child_tail; /** - * For update-searches, link to the - * next child belonging to the same parent. + * For update-searches, link to the next child belonging to the same + * parent. */ struct GNUNET_FS_SearchContext *next; /** - * For update-searches, link to the - * previous child belonging to the same - * parent. + * For update-searches, link to the previous child belonging to the + * same parent. */ struct GNUNET_FS_SearchContext *prev; @@ -1021,9 +1051,8 @@ struct GNUNET_FS_SearchContext struct GNUNET_CONTAINER_MultiHashMap *master_result_map; /** - * Per-keyword information for a keyword search. - * This array will have exactly as many entries - * as there were keywords. + * Per-keyword information for a keyword search. This array will + * have exactly as many entries as there were keywords. */ struct SearchRequestEntry *requests; @@ -1033,12 +1062,10 @@ struct GNUNET_FS_SearchContext struct GNUNET_TIME_Absolute start_time; /** - * ID of a task that is using this struct - * and that must be cancelled when the search - * is being stopped (if not GNUNET_SCHEDULER_NO_TASK). - * Used for the task that adds some artificial - * delay when trying to reconnect to the FS - * service. + * ID of a task that is using this struct and that must be cancelled + * when the search is being stopped (if not + * GNUNET_SCHEDULER_NO_TASK). Used for the task that adds some + * artificial delay when trying to reconnect to the FS service. */ GNUNET_SCHEDULER_TaskIdentifier task; @@ -1051,6 +1078,8 @@ struct GNUNET_FS_SearchContext * Number of mandatory keywords in this query. */ uint32_t mandatory_count; + + }; @@ -1060,8 +1089,7 @@ struct GNUNET_FS_SearchContext struct DownloadRequest { /** - * While pending, we keep all download requests - * in a linked list. + * While pending, we keep all download requests in a linked list. */ struct DownloadRequest *next; 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 @@ * @author Christian Grothoff * * TODO: - * - location URI suppport (can wait, easy) * - persistence (can wait) + * - location URI suppport (can wait, easy) + * - different priority for scheduling probe downloads? * - check if iblocks can be computed from existing blocks (can wait, hard) */ #include "platform.h" @@ -137,8 +138,8 @@ compute_dblock_offset (uint64_t offset, /** - * Fill in all of the generic fields for - * a download event. + * Fill in all of the generic fields for a download event and call the + * callback. * * @param pi structure to fill in * @param dc overall download context @@ -168,6 +169,12 @@ make_download_status (struct GNUNET_FS_ProgressInfo *pi, = GNUNET_TIME_calculate_eta (dc->start_time, dc->completed, dc->length); + if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) + dc->client_info = dc->h->upcb (dc->h->upcb_cls, + pi); + else + dc->client_info = GNUNET_FS_search_probe_progress_ (NULL, + pi); } /** @@ -624,8 +631,6 @@ check_completed (struct GNUNET_FS_DownloadContext *dc) /* signal completion */ pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; make_download_status (&pi, dc); - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); if (dc->parent != NULL) check_completed (dc->parent); } @@ -847,10 +852,8 @@ process_result_with_request (void *cls, dc->emsg = GNUNET_strdup ("Internal error or bogus download URI"); /* signal error */ pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; - make_download_status (&pi, dc); pi.value.download.specifics.error.message = dc->emsg; - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); + make_download_status (&pi, dc); /* abort all pending requests */ if (NULL != dc->th) { @@ -913,11 +916,8 @@ process_result_with_request (void *cls, /* signal error */ pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; - make_download_status (&pi, dc); pi.value.download.specifics.error.message = emsg; - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); - + make_download_status (&pi, dc); /* abort all pending requests */ if (NULL != dc->th) { @@ -961,13 +961,11 @@ process_result_with_request (void *cls, } pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS; - make_download_status (&pi, dc); pi.value.download.specifics.progress.data = pt; pi.value.download.specifics.progress.offset = sm->offset; pi.value.download.specifics.progress.data_len = prc->size; pi.value.download.specifics.progress.depth = sm->depth; - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); + make_download_status (&pi, dc); GNUNET_assert (dc->completed <= dc->length); if (dc->completed == dc->length) { @@ -999,8 +997,6 @@ process_result_with_request (void *cls, /* signal completion */ pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; make_download_status (&pi, dc); - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); if (dc->parent != NULL) check_completed (dc->parent); } @@ -1296,8 +1292,6 @@ activate_fs_download (void *cls, GNUNET_TIME_UNIT_FOREVER_REL); pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; make_download_status (&pi, dc); - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); GNUNET_CONTAINER_multihashmap_iterate (dc->active, &retry_entry, dc); @@ -1336,8 +1330,6 @@ deactivate_fs_download (void *cls) } pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE; make_download_status (&pi, dc); - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); } @@ -1464,10 +1456,8 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, #endif // FIXME: make persistent pi.status = GNUNET_FS_STATUS_DOWNLOAD_START; - make_download_status (&pi, dc); pi.value.download.specifics.start.meta = meta; - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); + make_download_status (&pi, dc); schedule_block_download (dc, &dc->uri->data.chk.chk, 0, @@ -1527,9 +1517,6 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED; make_download_status (&pi, dc); - dc->client_info = dc->h->upcb (dc->h->upcb_cls, - &pi); - if (GNUNET_SCHEDULER_NO_TASK != dc->task) GNUNET_SCHEDULER_cancel (dc->h->sched, 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 @@ * * @param pi structure to fill in * @param sc overall search context + * @return value returned by the callback */ -static void +static void * make_search_status (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_SearchContext *sc) { @@ -60,6 +61,8 @@ make_search_status (struct GNUNET_FS_ProgressInfo *pi, = sc->uri; pi->value.search.duration = GNUNET_TIME_absolute_get_duration (sc->start_time); pi->value.search.anonymity = sc->anonymity; + return sc->h->upcb (sc->h->upcb_cls, + pi); } @@ -103,11 +106,9 @@ notify_client_chk_result (struct GNUNET_FS_SearchContext *sc, struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_RESULT; - make_search_status (&pi, sc); pi.value.search.specifics.result.meta = sr->meta; pi.value.search.specifics.result.uri = sr->uri; - sr->client_info = sc->h->upcb (sc->h->upcb_cls, - &pi); + sr->client_info = make_search_status (&pi, sc); } @@ -125,7 +126,6 @@ notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; - make_search_status (&pi, sc); pi.value.search.specifics.update.cctx = sr->client_info; pi.value.search.specifics.update.meta = sr->meta; pi.value.search.specifics.update.uri = sr->uri; @@ -135,8 +135,7 @@ notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, = sr->availability_trials; pi.value.search.specifics.update.applicability_rank = sr->optional_support; - sr->client_info = sc->h->upcb (sc->h->upcb_cls, - &pi); + sr->client_info = make_search_status (&pi, sc); } @@ -183,6 +182,206 @@ get_result_present (void *cls, } +/** + * Start download probes for the given search result. + * + * @param sr the search result + */ +static void +start_probe (struct SearchResult *sr); + + +/** + * Signal result of last probe to client and then schedule next + * probe. + */ +static void +signal_probe_result (struct SearchResult *sr) +{ + struct GNUNET_FS_ProgressInfo pi; + + pi.status = GNUNET_FS_STATUS_SEARCH_START; + pi.value.search.specifics.update.cctx = sr->client_info; + pi.value.search.specifics.update.meta = sr->meta; + pi.value.search.specifics.update.uri = sr->uri; + pi.value.search.specifics.update.availability_rank = sr->availability_success; + pi.value.search.specifics.update.availability_certainty = sr->availability_trials; + pi.value.search.specifics.update.applicability_rank = sr->optional_support; + sr->sc->client_info = make_search_status (&pi, sr->sc); + start_probe (sr); +} + + +/** + * Handle the case where we have failed to receive a response for our probe. + * + * @param cls our 'struct SearchResult*' + * @param tc scheduler context + */ +static void +probe_failure_handler (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct SearchResult *sr = cls; + sr->availability_trials++; + signal_probe_result (sr); +} + + +/** + * Handle the case where we have gotten a response for our probe. + * + * @param cls our 'struct SearchResult*' + * @param tc scheduler context + */ +static void +probe_success_handler (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct SearchResult *sr = cls; + sr->availability_trials++; + sr->availability_success++; + signal_probe_result (sr); +} + + +/** + * Notification of FS that a search probe has made progress. + * This function is used INSTEAD of the client's event handler + * for downloads where the GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. + * + * @param cls closure, always NULL (!), actual closure + * is in the client-context of the info struct + * @param info details about the event, specifying the event type + * and various bits about the event + * @return client-context (for the next progress call + * for this operation; should be set to NULL for + * SUSPEND and STOPPED events). The value returned + * will be passed to future callbacks in the respective + * field in the GNUNET_FS_ProgressInfo struct. + */ +void* +GNUNET_FS_search_probe_progress_ (void *cls, + const struct GNUNET_FS_ProgressInfo *info) +{ + struct SearchResult *sr = info->value.download.cctx; + struct GNUNET_TIME_Relative dur; + + switch (info->status) + { + case GNUNET_FS_STATUS_DOWNLOAD_START: + /* ignore */ + break; + case GNUNET_FS_STATUS_DOWNLOAD_RESUME: + /* probes should never be resumed */ + GNUNET_assert (0); + break; + case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: + /* probes should never be suspended */ + GNUNET_break (0); + break; + case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: + /* ignore */ + break; + case GNUNET_FS_STATUS_DOWNLOAD_ERROR: + if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (sr->sc->h->sched, + sr->probe_cancel_task); + sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; + } + sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->sc->h->sched, + sr->remaining_probe_time, + &probe_failure_handler, + sr); + break; + case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: + if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (sr->sc->h->sched, + sr->probe_cancel_task); + sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; + } + sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->sc->h->sched, + sr->remaining_probe_time, + &probe_success_handler, + sr); + break; + case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: + /* FIXME: clean up? schedule next probe? or already done? */ + sr = NULL; + break; + case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: + GNUNET_assert (sr->probe_cancel_task == GNUNET_SCHEDULER_NO_TASK); + sr->probe_active_time = GNUNET_TIME_absolute_get (); + sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->sc->h->sched, + sr->remaining_probe_time, + &probe_failure_handler, + sr); + break; + case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: + if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (sr->sc->h->sched, + sr->probe_cancel_task); + sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; + } + dur = GNUNET_TIME_absolute_get_duration (sr->probe_active_time); + sr->remaining_probe_time = GNUNET_TIME_relative_subtract (sr->remaining_probe_time, + dur); + break; + default: + GNUNET_break (0); + return NULL; + } + return sr; +} + + +/** + * Start download probes for the given search result. + * + * @param sr the search result + */ +static void +start_probe (struct SearchResult *sr) +{ + uint64_t off; + uint64_t len; + + if (sr->probe_ctx != NULL) + return; + if (0 == (sr->sc->h->flags & GNUNET_FS_FLAGS_DO_PROBES)) + return; + if (sr->availability_trials > AVAILABILITY_TRIALS_MAX) + return; + len = GNUNET_FS_uri_chk_get_file_size (sr->uri); + if (len == 0) + return; + if ( (len <= DBLOCK_SIZE) && (sr->availability_success > 0)) + return; + off = len / DBLOCK_SIZE; + if (off > 0) + off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, off); + off *= DBLOCK_SIZE; + if (len - off < DBLOCK_SIZE) + len = len - off; + else + len = DBLOCK_SIZE; + sr->remaining_probe_time = GNUNET_TIME_relative_multiply (sr->sc->h->avg_block_latency, + 2 * (1 + sr->availability_trials)); + sr->probe_ctx = GNUNET_FS_download_start (sr->sc->h, + sr->uri, + sr->meta, + NULL, NULL, + off, len, + sr->sc->anonymity, + GNUNET_FS_DOWNLOAD_NO_TEMPORARIES | + GNUNET_FS_DOWNLOAD_IS_PROBE, + sr, NULL); +} + + /** * We have received a KSK result. Check how it fits in with the * overall query and notify the client accordingly. @@ -224,6 +423,7 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, if (NULL == sr) { sr = GNUNET_malloc (sizeof (struct SearchResult)); + sr->sc = sc; sr->uri = GNUNET_FS_uri_dup (uri); sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); sr->mandatory_missing = sc->mandatory_count; @@ -247,7 +447,7 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, notify_client_chk_result (sc, sr); else notify_client_chk_update (sc, sr); - /* FIXME: consider starting probes for "sr" */ + start_probe (sr); } @@ -301,14 +501,14 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, (void*) uri)) return; /* duplicate result */ sr = GNUNET_malloc (sizeof (struct SearchResult)); + sr->sc = sc; sr->uri = GNUNET_FS_uri_dup (uri); sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &key, sr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - /* FIXME: consider starting probes for "sr" */ - + start_probe (sr); /* notify client */ notify_client_chk_result (sc, sr); /* search for updates */ @@ -921,9 +1121,7 @@ search_start (struct GNUNET_FS_Handle *h, parent->child_tail, sc); pi.status = GNUNET_FS_STATUS_SEARCH_START; - make_search_status (&pi, sc); - sc->client_info = h->upcb (h->upcb_cls, - &pi); + sc->client_info = make_search_status (&pi, sc); GNUNET_CLIENT_notify_transmit_ready (client, size, GNUNET_CONSTANTS_SERVICE_TIMEOUT, @@ -974,9 +1172,7 @@ GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) // FIXME: make persistent! // FIXME: should this freeze all active probes? pi.status = GNUNET_FS_STATUS_SEARCH_PAUSED; - make_search_status (&pi, sc); - sc->client_info = sc->h->upcb (sc->h->upcb_cls, - &pi); + sc->client_info = make_search_status (&pi, sc); } @@ -995,9 +1191,7 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) do_reconnect (sc, NULL); // FIXME: make persistent! pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; - make_search_status (&pi, sc); - sc->client_info = sc->h->upcb (sc->h->upcb_cls, - &pi); + sc->client_info = make_search_status (&pi, sc); } @@ -1020,12 +1214,10 @@ search_result_free (void *cls, struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; - make_search_status (&pi, sc); pi.value.search.specifics.result_stopped.cctx = sr->client_info; pi.value.search.specifics.result_stopped.meta = sr->meta; pi.value.search.specifics.result_stopped.uri = sr->uri; - sr->client_info = h->upcb (h->upcb_cls, - &pi); + sr->client_info = make_search_status (&pi, sc); GNUNET_break (NULL == sr->client_info); GNUNET_FS_uri_destroy (sr->uri); @@ -1066,9 +1258,7 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) &search_result_free, sc); pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; - make_search_status (&pi, sc); - sc->client_info = sc->h->upcb (sc->h->upcb_cls, - &pi); + sc->client_info = make_search_status (&pi, sc); GNUNET_break (NULL == sc->client_info); if (sc->task != GNUNET_SCHEDULER_NO_TASK) 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 * Is persistence of operations desired? * (will create SUSPEND/RESUME events). */ - GNUNET_FS_FLAGS_PERSISTENCE = 1 + GNUNET_FS_FLAGS_PERSISTENCE = 1, + + /** + * Should we automatically trigger probes for search results + * to determine availability? + * (will create GNUNET_FS_STATUS_SEARCH_UPDATE events). + */ + GNUNET_FS_FLAGS_DO_PROBES = 2 }; @@ -2252,7 +2259,16 @@ enum GNUNET_FS_DownloadOptions * Do not append temporary data to * the target file (for the IBlocks). */ - GNUNET_FS_DOWNLOAD_NO_TEMPORARIES = 2 + GNUNET_FS_DOWNLOAD_NO_TEMPORARIES = 2, + + /** + * Internal option used to flag this download as a 'probe' for a + * search result. Impacts the priority with which the download is + * run and causes signalling callbacks to be done differently. + * Also, probe downloads are not serialized on suspension. Normal + * clients should not use this! + */ + GNUNET_FS_DOWNLOAD_IS_PROBE = (1<<31) }; 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 GNUNET_TIME_Relative a2); +/** + * Subtract relative timestamp from the other. + * + * @param a1 first timestamp + * @param a2 second timestamp + * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise + */ +struct GNUNET_TIME_Relative +GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, + struct GNUNET_TIME_Relative a2); + /** * 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, /** * Add relative times together. * + * @param a1 first timestamp + * @param a2 second timestamp * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise */ struct GNUNET_TIME_Relative @@ -365,8 +367,33 @@ GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1, } +/** + * Subtract relative timestamp from the other. + * + * @param a1 first timestamp + * @param a2 second timestamp + * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise + */ +struct GNUNET_TIME_Relative +GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, + struct GNUNET_TIME_Relative a2) +{ + struct GNUNET_TIME_Relative ret; + + if (a2.value >= a1.value) + return GNUNET_TIME_relative_get_zero (); + if (a1.value == (uint64_t) - 1LL) + return GNUNET_TIME_relative_get_forever (); + ret.value = a1.value - a2.value; + return ret; +} + + /** * Convert relative time to network byte order. + * + * @param a time to convert + * @return time in network byte order */ struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) @@ -378,6 +405,9 @@ GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) /** * Convert relative time from network byte order. + * + * @param a time to convert + * @return time in host byte order */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) @@ -390,6 +420,9 @@ GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) /** * Convert absolute time to network byte order. + * + * @param a time to convert + * @return time in network byte order */ struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) @@ -401,6 +434,9 @@ GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) /** * Convert absolute time from network byte order. + * + * @param a time to convert + * @return time in host byte order */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) -- cgit v1.2.3