From 6aefa4ac85435c8e7afb86e4e6daef77da69709a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 4 May 2010 08:50:09 +0000 Subject: [PATCH] generating SUSPEND events --- TODO | 3 +- src/fs/fs.h | 10 +++++ src/fs/fs_download.c | 79 +++++++++++++++++++++++---------- src/fs/fs_publish.c | 56 +++++++++++++++++++++-- src/fs/fs_search.c | 74 +++++++++++++++++++++++++++++- src/fs/fs_unindex.c | 11 ++++- src/include/gnunet_fs_service.h | 6 +++ 7 files changed, 207 insertions(+), 32 deletions(-) diff --git a/TODO b/TODO index 861e2915d..14f1d5ce6 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,5 @@ 0.9.0pre1: * FS: [CG] - - generate SUSPEND events (publish, unindex, search, download) AND free memory! - => test SUSPEND events - actually call 'sync' functions (publish, unindex, search, download) - code review: => refactor fs.c to join common code segments! @@ -10,6 +8,7 @@ - persistence testing (publish, unindex, search, download): => need driver! => schedule suspending tasks DURING event handler => good coverage! + => test SUSPEND events - gnunet-service-fs (hot-path routing, load-based routing, nitpicks) - [gnunet-service-fs.c:208]: member 'LocalGetContext::results_bf_size' is never used - [gnunet-service-fs.c:501]: member 'PendingRequest::used_pids_size' is never used diff --git a/src/fs/fs.h b/src/fs/fs.h index 275882c4f..1d3498a7c 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -1025,6 +1025,16 @@ GNUNET_FS_end_top (struct GNUNET_FS_Handle *h, struct TopLevelActivity *top); +/** + * Create SUSPEND event for the given download operation + * and then clean up our state (without stop signal). + * + * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for + */ +void +GNUNET_FS_download_signal_suspend_ (void *cls); + + /** * Master context for most FS operations. */ diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index d7c5370b1..2fd8e0412 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c @@ -1383,19 +1383,68 @@ deactivate_fs_download (void *cls) } +/** + * Free entries in the map. + * + * @param cls unused (NULL) + * @param key unused + * @param entry entry of type "struct DownloadRequest" which is freed + * @return GNUNET_OK + */ +static int +free_entry (void *cls, + const GNUNET_HashCode *key, + void *entry) +{ + GNUNET_free (entry); + return GNUNET_OK; +} + + /** * Create SUSPEND event for the given download operation * and then clean up our state (without stop signal). * - * @param cls the 'struct GNUNET_FS_UnindexContext' to signal for + * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for */ -static void -download_signal_suspend (void *cls) +void +GNUNET_FS_download_signal_suspend_ (void *cls) { struct GNUNET_FS_DownloadContext *dc = cls; + struct GNUNET_FS_ProgressInfo pi; - GNUNET_FS_end_top (dc->h, dc->top); - /* FIXME: signal! */ + if (dc->top != NULL) + GNUNET_FS_end_top (dc->h, dc->top); + while (NULL != dc->child_head) + GNUNET_FS_download_signal_suspend_ (dc->child_head); + if (dc->search != NULL) + { + dc->search->download = NULL; + dc->search = NULL; + } + if (dc->job_queue != NULL) + { + GNUNET_FS_dequeue_ (dc->job_queue); + dc->job_queue = NULL; + } + if (dc->parent != NULL) + GNUNET_CONTAINER_DLL_remove (dc->parent->child_head, + dc->parent->child_tail, + dc); + pi.status = GNUNET_FS_STATUS_DOWNLOAD_SUSPEND; + GNUNET_FS_download_make_status_ (&pi, dc); + if (GNUNET_SCHEDULER_NO_TASK != dc->task) + GNUNET_SCHEDULER_cancel (dc->h->sched, + dc->task); + GNUNET_CONTAINER_multihashmap_iterate (dc->active, + &free_entry, + NULL); + GNUNET_CONTAINER_multihashmap_destroy (dc->active); + GNUNET_free_non_null (dc->filename); + GNUNET_CONTAINER_meta_data_destroy (dc->meta); + GNUNET_FS_uri_destroy (dc->uri); + GNUNET_free_non_null (dc->temp_filename); + GNUNET_free_non_null (dc->serialization); GNUNET_free (dc); } @@ -1515,7 +1564,7 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, GNUNET_FS_download_start_downloading_ (dc); if (parent == NULL) dc->top = GNUNET_FS_make_top (dc->h, - &download_signal_suspend, + &GNUNET_FS_download_signal_suspend_, dc); return dc; @@ -1662,24 +1711,6 @@ GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc) } -/** - * Free entries in the map. - * - * @param cls unused (NULL) - * @param key unused - * @param entry entry of type "struct DownloadRequest" which is freed - * @return GNUNET_OK - */ -static int -free_entry (void *cls, - const GNUNET_HashCode *key, - void *entry) -{ - GNUNET_free (entry); - return GNUNET_OK; -} - - /** * Stop a download (aborts if download is incomplete). * diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 4101174bb..0c4ebba7b 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -929,6 +929,46 @@ fip_signal_start(void *cls, } +/** + * Signal the FS's progress function that we are suspending + * an upload. + * + * @param cls closure (of type "struct GNUNET_FS_PublishContext*") + * @param fi the entry in the publish-structure + * @param length length of the file or directory + * @param meta metadata for the file or directory (can be modified) + * @param uri pointer to the keywords that will be used for this entry (can be modified) + * @param anonymity pointer to selected anonymity level (can be modified) + * @param priority pointer to selected priority (can be modified) + * @param expirationTime pointer to selected expiration time (can be modified) + * @param client_info pointer to client context set upon creation (can be modified) + * @return GNUNET_OK to continue (always) + */ +static int +fip_signal_suspend(void *cls, + struct GNUNET_FS_FileInformation *fi, + uint64_t length, + struct GNUNET_CONTAINER_MetaData *meta, + struct GNUNET_FS_Uri **uri, + uint32_t *anonymity, + uint32_t *priority, + struct GNUNET_TIME_Absolute *expirationTime, + void **client_info) +{ + struct GNUNET_FS_PublishContext*sc = cls; + struct GNUNET_FS_ProgressInfo pi; + uint64_t off; + + GNUNET_free_non_null (fi->serialization); + fi->serialization = NULL; + off = (fi->chk_uri == NULL) ? 0 : length; + pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; + GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, sc, fi, off)); + *client_info = NULL; + return GNUNET_OK; +} + + /** * Create SUSPEND event for the given publish operation * and then clean up our state (without stop signal). @@ -940,9 +980,16 @@ publish_signal_suspend (void *cls) { struct GNUNET_FS_PublishContext *pc = cls; + if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) + { + GNUNET_SCHEDULER_cancel (pc->h->sched, pc->upload_task); + pc->upload_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_FS_file_information_inspect (pc->fi, + &fip_signal_suspend, + pc); GNUNET_FS_end_top (pc->h, pc->top); - /* FIXME: signal! */ - GNUNET_free (pc); + publish_cleanup (pc); } /** @@ -1074,7 +1121,10 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) { GNUNET_FS_end_top (pc->h, pc->top); if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) - GNUNET_SCHEDULER_cancel (pc->h->sched, pc->upload_task); + { + GNUNET_SCHEDULER_cancel (pc->h->sched, pc->upload_task); + pc->upload_task = GNUNET_SCHEDULER_NO_TASK; + } if (pc->serialization != NULL) { GNUNET_FS_remove_sync_file_ (pc->h, "publish", pc->serialization); diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 9ab024eeb..36aa26193 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -1168,6 +1168,46 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) } + +/** + * Signal suspend and free the given search result. + * + * @param cls the global FS handle + * @param key the key for the search result (unused) + * @param value the search result to free + * @return GNUNET_OK + */ +static int +search_result_suspend (void *cls, + const GNUNET_HashCode * key, + void *value) +{ + struct GNUNET_FS_SearchContext *sc = cls; + struct GNUNET_FS_Handle *h = sc->h; + struct GNUNET_FS_SearchResult *sr = value; + struct GNUNET_FS_ProgressInfo pi; + + if (sr->download != NULL) + GNUNET_FS_download_signal_suspend_ (sr->download); + pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND; + pi.value.search.specifics.result_suspend.cctx = sr->client_info; + pi.value.search.specifics.result_suspend.meta = sr->meta; + pi.value.search.specifics.result_suspend.uri = sr->uri; + sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc); + GNUNET_break (NULL == sr->client_info); + GNUNET_free_non_null (sr->serialization); + GNUNET_FS_uri_destroy (sr->uri); + GNUNET_CONTAINER_meta_data_destroy (sr->meta); + if (sr->probe_ctx != NULL) + GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); + if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (h->sched, + sr->probe_cancel_task); + GNUNET_free (sr); + return GNUNET_OK; +} + + /** * Create SUSPEND event for the given search operation * and then clean up our state (without stop signal). @@ -1178,9 +1218,41 @@ static void search_signal_suspend (void *cls) { struct GNUNET_FS_SearchContext *sc = cls; + struct GNUNET_FS_SearchContext *parent = cls; + struct GNUNET_FS_ProgressInfo pi; + unsigned int i; GNUNET_FS_end_top (sc->h, sc->top); - /* FIXME: signal! */ + if (NULL != (parent = sc->parent)) + { + GNUNET_CONTAINER_DLL_remove (parent->child_head, + parent->child_tail, + sc); + sc->parent = NULL; + } + while (NULL != sc->child_head) + search_signal_suspend (sc->child_head); + GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, + &search_result_suspend, + sc); + pi.status = GNUNET_FS_STATUS_SEARCH_SUSPEND; + sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc); + GNUNET_break (NULL == sc->client_info); + if (sc->task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (sc->h->sched, + sc->task); + if (NULL != sc->client) + GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO); + GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); + if (sc->requests != NULL) + { + GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri)); + for (i=0;iuri->data.ksk.keywordCount;i++) + GNUNET_CONTAINER_multihashmap_destroy (sc->requests[i].results); + } + GNUNET_free_non_null (sc->requests); + GNUNET_free_non_null (sc->emsg); + GNUNET_FS_uri_destroy (sc->uri); GNUNET_free (sc); } diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c index 6d4ee3f54..c79b3413e 100644 --- a/src/fs/fs_unindex.c +++ b/src/fs/fs_unindex.c @@ -403,9 +403,16 @@ static void unindex_signal_suspend (void *cls) { struct GNUNET_FS_UnindexContext *uc = cls; + struct GNUNET_FS_ProgressInfo pi; GNUNET_FS_end_top (uc->h, uc->top); - /* FIXME: signal! */ + pi.status = GNUNET_FS_STATUS_UNINDEX_SUSPEND; + GNUNET_FS_unindex_make_status_ (&pi, uc, + (uc->state == UNINDEX_STATE_COMPLETE) + ? uc->file_size : 0); + GNUNET_break (NULL == uc->client_info); + GNUNET_free (uc->filename); + GNUNET_free_non_null (uc->serialization); GNUNET_free (uc); } @@ -476,6 +483,7 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) if (uc->serialization != NULL) { GNUNET_FS_remove_sync_file_ (uc->h, "unindex", uc->serialization); + GNUNET_free (uc->serialization); uc->serialization = NULL; } pi.status = GNUNET_FS_STATUS_UNINDEX_STOPPED; @@ -485,7 +493,6 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) ? uc->file_size : 0); GNUNET_break (NULL == uc->client_info); GNUNET_free (uc->filename); - GNUNET_free_non_null (uc->serialization); GNUNET_free (uc); } diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index 0645a11c4..2207e274e 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h @@ -646,6 +646,12 @@ enum GNUNET_FS_Status */ GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED, + /** + * Event generated for each search result + * when the respective search is suspended. + */ + GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND, + /** * Last message from a search; this signals * that there will be no further events associated -- 2.25.1