From 3d43fe27b2927c6d99384b23eb19bc00641dc6f3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 4 May 2010 15:48:39 +0000 Subject: [PATCH] fixing mess with search update serialization and parenting --- TODO | 3 - src/fs/fs.c | 173 +++++++++++++++++--------------- src/fs/fs.h | 38 ++----- src/fs/fs_search.c | 81 +++++++-------- src/include/gnunet_fs_service.h | 10 +- 5 files changed, 147 insertions(+), 158 deletions(-) diff --git a/TODO b/TODO index 57510234c..d99128a96 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,5 @@ 0.9.0pre1: * FS: [CG] - - SKS update searches should be attached to individual search results, not to the - entire SKS search (!) - => API change (event signalling) & serialization change (!) - persistence testing (publish, unindex, search, download): => need driver! => schedule suspending tasks DURING event handler => good coverage! diff --git a/src/fs/fs.c b/src/fs/fs.c index f69fd564d..15fe86f71 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -1706,14 +1706,14 @@ GNUNET_FS_search_result_sync_ (struct GNUNET_FS_SearchResult *sr) uris = NULL; if (NULL == sr->serialization) sr->serialization = make_serialization_file_name_in_dir (sr->sc->h, - (sr->sc->parent == NULL) + (sr->sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sr->sc->serialization); if (NULL == sr->serialization) return; wh = get_write_handle_in_dir (sr->sc->h, - (sr->sc->parent == NULL) + (sr->sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sr->sc->serialization, @@ -1723,6 +1723,8 @@ GNUNET_FS_search_result_sync_ (struct GNUNET_FS_SearchResult *sr) GNUNET_BIO_write_string (wh, uris)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, sr->download != NULL ? sr->download->serialization : NULL)) || + (GNUNET_OK != + GNUNET_BIO_write_string (wh, sr->update_search != NULL ? sr->update_search->serialization : NULL)) || (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, sr->meta)) || (GNUNET_OK != @@ -1749,7 +1751,7 @@ GNUNET_FS_search_result_sync_ (struct GNUNET_FS_SearchResult *sr) if (wh != NULL) (void) GNUNET_BIO_write_close (wh); remove_sync_file_in_dir (sr->sc->h, - (sr->sc->parent == NULL) + (sr->sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sr->sc->serialization, @@ -1771,13 +1773,13 @@ void GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_BIO_WriteHandle *wh; - struct GNUNET_FS_SearchContext *scc; char *uris; char in_pause; const char *category; - - category = (sc->parent == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH; + category = (sc->psearch_result == NULL) + ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH + : GNUNET_FS_SYNC_PATH_CHILD_SEARCH; if (NULL == sc->serialization) sc->serialization = make_serialization_file_name (sc->h, category); @@ -1803,17 +1805,6 @@ GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext *sc) goto cleanup; GNUNET_free (uris); uris = NULL; - scc = sc->child_head; - while (NULL != scc) - { - if (scc->serialization == NULL) - break; - if (GNUNET_OK != - GNUNET_BIO_write_string (wh, scc->serialization)) - goto cleanup; - scc = scc->next; - } - GNUNET_BIO_write_string (wh, NULL); if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { @@ -1970,6 +1961,21 @@ deserialize_download (struct GNUNET_FS_Handle *h, const char *serialization); +/** + * Deserialize a search. + * + * @param h overall context + * @param rh file to deserialize from + * @param psearch_result parent search result + * @param serialization name under which the search was serialized + */ +static struct GNUNET_FS_SearchContext * +deserialize_search (struct GNUNET_FS_Handle *h, + struct GNUNET_BIO_ReadHandle *rh, + struct GNUNET_FS_SearchResult *psearch_result, + const char *serialization); + + /** * Function called with a filename of serialized search result * to deserialize. @@ -1987,6 +1993,7 @@ deserialize_search_result (void *cls, char *uris; char *emsg; char *download; + char *update_srch; struct GNUNET_BIO_ReadHandle *rh; struct GNUNET_BIO_ReadHandle *drh; struct GNUNET_FS_SearchResult *sr; @@ -1998,7 +2005,7 @@ deserialize_search_result (void *cls, if (ser != NULL) { remove_sync_file_in_dir (sc->h, - (sc->parent == NULL) + (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization, @@ -2017,6 +2024,8 @@ deserialize_search_result (void *cls, (NULL == (sr->uri = GNUNET_FS_uri_parse (uris, &emsg))) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "download-lnk", &download, 16)) || + (GNUNET_OK != + GNUNET_BIO_read_string (rh, "search-lnk", &update_srch, 16)) || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "result-meta", &sr->meta)) || (GNUNET_OK != @@ -2052,6 +2061,26 @@ deserialize_search_result (void *cls, } GNUNET_free (download); } + if (update_srch != NULL) + { + drh = get_read_handle (sc->h, + GNUNET_FS_SYNC_PATH_CHILD_SEARCH, + update_srch); + deserialize_search (sc->h, + drh, + sr, + update_srch); + if (GNUNET_OK != + GNUNET_BIO_read_close (drh, &emsg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to resume sub-search `%s': %s\n"), + update_srch, + emsg); + GNUNET_free (emsg); + } + GNUNET_free (update_srch); + } GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &sr->key, sr, @@ -2101,6 +2130,16 @@ signal_download_resume (struct GNUNET_FS_DownloadContext *dc) } +/** + * Signal resuming of a search to our clients (for the + * top level search and all sub-searches). + * + * @param sc search being resumed + */ +static void +signal_search_resume (struct GNUNET_FS_SearchContext *sc); + + /** * Iterator over search results signaling resume to the client for * each result. @@ -2139,10 +2178,21 @@ signal_result_resume (void *cls, { GNUNET_FS_search_start_probe_ (sr); } + if (sr->update_search != NULL) + signal_search_resume (sr->update_search); return GNUNET_YES; } +/** + * Free memory allocated by the search context and its children + * + * @param sc search context to free + */ +static void +free_search_context (struct GNUNET_FS_SearchContext *sc); + + /** * Iterator over search results freeing each. * @@ -2158,6 +2208,11 @@ free_result (void *cls, { struct GNUNET_FS_SearchResult *sr = value; + if (sr->update_search != NULL) + { + free_search_context (sr->update_search); + GNUNET_assert (NULL == sr->update_search); + } GNUNET_CONTAINER_meta_data_destroy (sr->meta); GNUNET_FS_uri_destroy (sr->uri); GNUNET_free (sr); @@ -2173,30 +2228,21 @@ free_result (void *cls, static void free_search_context (struct GNUNET_FS_SearchContext *sc) { - struct GNUNET_FS_SearchContext *scc; - - while (NULL != (scc = sc->child_head)) - { - GNUNET_CONTAINER_DLL_remove (sc->child_head, - sc->child_tail, - scc); - free_search_context (scc); - } - GNUNET_free_non_null (sc->emsg); if (sc->serialization != NULL) { GNUNET_FS_remove_sync_file_ (sc->h, - (sc->parent == NULL) + (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization); GNUNET_FS_remove_sync_dir_ (sc->h, - (sc->parent == NULL) + (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization); } GNUNET_free_non_null (sc->serialization); + GNUNET_free_non_null (sc->emsg); if (sc->uri != NULL) GNUNET_FS_uri_destroy (sc->uri); if (sc->master_result_map != NULL) @@ -2407,7 +2453,6 @@ deserialize_download (struct GNUNET_FS_Handle *h, static void signal_search_resume (struct GNUNET_FS_SearchContext *sc) { - struct GNUNET_FS_SearchContext *scc; struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_RESUME; @@ -2415,12 +2460,10 @@ signal_search_resume (struct GNUNET_FS_SearchContext *sc) pi.value.search.specifics.resume.is_paused = (sc->client == NULL) ? GNUNET_YES : GNUNET_NO; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc); - scc = sc->child_head; - while (NULL != scc) - { - signal_search_resume (scc); - scc = scc->next; - } + GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, + &signal_result_resume, + sc); + } @@ -2429,29 +2472,36 @@ signal_search_resume (struct GNUNET_FS_SearchContext *sc) * * @param h overall context * @param rh file to deserialize from - * @param parent parent search + * @param psearch_result parent search result * @param serialization name under which the search was serialized */ static struct GNUNET_FS_SearchContext * deserialize_search (struct GNUNET_FS_Handle *h, struct GNUNET_BIO_ReadHandle *rh, - struct GNUNET_FS_SearchContext *parent, + struct GNUNET_FS_SearchResult *psearch_result, const char *serialization) { struct GNUNET_FS_SearchContext *sc; - struct GNUNET_FS_SearchContext *scc; - struct GNUNET_BIO_ReadHandle *rhc; char *emsg; char *uris; - char *child_ser; char *dn; uint32_t options; char in_pause; + if ( (psearch_result != NULL) && + (psearch_result->update_search != NULL) ) + { + GNUNET_break (0); + return NULL; + } uris = NULL; emsg = NULL; sc = GNUNET_malloc (sizeof (struct GNUNET_FS_SearchContext)); - sc->parent = parent; + if (psearch_result != NULL) + { + sc->psearch_result = psearch_result; + psearch_result->update_search = sc; + } sc->h = h; sc->serialization = GNUNET_strdup (serialization); if ( (GNUNET_OK != @@ -2473,7 +2523,7 @@ deserialize_search (struct GNUNET_FS_Handle *h, sc->options = (enum GNUNET_FS_SearchOptions) options; sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16); dn = get_serialization_file_name_in_dir (h, - (sc->parent == NULL) + (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization, @@ -2490,42 +2540,7 @@ deserialize_search (struct GNUNET_FS_Handle *h, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not resume running search, will resume as paused search\n")); } - while (1) - { - if ( (GNUNET_OK != - GNUNET_BIO_read_string (rh, "child-serialization", &child_ser, 32))) - goto cleanup; - if (child_ser == NULL) - break; - rhc = get_read_handle (h, GNUNET_FS_SYNC_PATH_CHILD_SEARCH, child_ser); - if (rhc != NULL) - { - scc = deserialize_search (h, rhc, sc, child_ser); - if (scc != NULL) - GNUNET_CONTAINER_DLL_insert (sc->child_head, - sc->child_tail, - scc); - emsg = NULL; - if (GNUNET_OK != - GNUNET_BIO_read_close (rhc, &emsg)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Failed to resume sub-search `%s': %s\n"), - child_ser, - emsg); - GNUNET_free (emsg); - } - } - GNUNET_free (child_ser); - } - if (parent != NULL) - GNUNET_CONTAINER_DLL_insert (parent->child_head, - parent->child_tail, - sc); signal_search_resume (sc); - GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, - &signal_result_resume, - sc); GNUNET_free (uris); return sc; cleanup: diff --git a/src/fs/fs.h b/src/fs/fs.h index f4f21faea..d7dcd987d 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -646,11 +646,15 @@ struct GNUNET_FS_SearchResult /** * ID of an associated download based on this search result (or * NULL for none). - * - * FIXME: not yet serialized. */ struct GNUNET_FS_DownloadContext *download; + /** + * If this search result triggered an update search, this field + * links to the update search. + */ + struct GNUNET_FS_SearchContext *update_search; + /** * Name under which this search result is stored on disk. */ @@ -1457,34 +1461,10 @@ 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. - */ - struct GNUNET_FS_SearchContext *parent; - - /** - * 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 + * For update-searches, link to the search result 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. - */ - struct GNUNET_FS_SearchContext *next; - - /** - * For update-searches, link to the previous child belonging to the - * same parent. - */ - struct GNUNET_FS_SearchContext *prev; + struct GNUNET_FS_SearchResult *psearch_result; /** * Connection to the FS service. @@ -1618,8 +1598,6 @@ struct GNUNET_FS_DownloadContext /** * Associated search (used when downloading files * based on search results), or NULL for none. - * - * FIXME: not yet serialized */ struct GNUNET_FS_SearchResult *search; diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 8c324252f..9f62e04b1 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -53,7 +53,7 @@ GNUNET_FS_search_make_status_ (struct GNUNET_FS_ProgressInfo *pi, pi->value.search.cctx = sc->client_info; pi->value.search.pctx - = (sc->parent == NULL) ? NULL : sc->parent->client_info; + = (sc->psearch_result == NULL) ? NULL : sc->psearch_result->client_info; pi->value.search.query = sc->uri; pi->value.search.duration = GNUNET_TIME_absolute_get_duration (sc->start_time); @@ -462,7 +462,7 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, * @param anonymity desired level of anonymity * @param options options for the search * @param cctx client context - * @param parent parent search (for namespace update searches) + * @param psearch parent search result (for namespace update searches) * @return context that can be used to control the search */ static struct GNUNET_FS_SearchContext * @@ -471,7 +471,7 @@ search_start (struct GNUNET_FS_Handle *h, uint32_t anonymity, enum GNUNET_FS_SearchOptions options, void *cctx, - struct GNUNET_FS_SearchContext *parent); + struct GNUNET_FS_SearchResult *psearch); /** @@ -523,14 +523,12 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, uu.type = sks; uu.data.sks.namespace = sc->uri->data.sks.namespace; uu.data.sks.identifier = GNUNET_strdup (id_update); - /* FIXME: should attach update search to the individual result, not - the entire SKS search! */ - search_start (sc->h, - &uu, - sc->anonymity, - sc->options, - NULL, - sc); + (void) search_start (sc->h, + &uu, + sc->anonymity, + sc->options, + NULL, + sr); } @@ -1064,7 +1062,7 @@ try_reconnect (struct GNUNET_FS_SearchContext *sc) * @param anonymity desired level of anonymity * @param options options for the search * @param cctx initial value for the client context - * @param parent parent search (for namespace update searches) + * @param psearch parent search result (for namespace update searches) * @return context that can be used to control the search */ static struct GNUNET_FS_SearchContext * @@ -1073,7 +1071,7 @@ search_start (struct GNUNET_FS_Handle *h, uint32_t anonymity, enum GNUNET_FS_SearchOptions options, void *cctx, - struct GNUNET_FS_SearchContext *parent) + struct GNUNET_FS_SearchResult *psearch) { struct GNUNET_FS_SearchContext *sc; struct GNUNET_FS_ProgressInfo pi; @@ -1084,13 +1082,13 @@ search_start (struct GNUNET_FS_Handle *h, sc->uri = GNUNET_FS_uri_dup (uri); sc->anonymity = anonymity; sc->start_time = GNUNET_TIME_absolute_get (); - sc->parent = parent; + if (psearch != NULL) + { + sc->psearch_result = psearch; + psearch->update_search = sc; + } sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16); sc->client_info = cctx; - if (NULL != parent) - GNUNET_CONTAINER_DLL_insert (parent->child_head, - parent->child_tail, - sc); if (GNUNET_OK != GNUNET_FS_search_start_searching_ (sc)) { @@ -1206,6 +1204,8 @@ search_result_freeze_probes (void *cls, sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } + if (sr->update_search != NULL) + GNUNET_FS_search_pause (sr->update_search); return GNUNET_OK; } @@ -1226,10 +1226,22 @@ search_result_resume_probes (void *cls, struct GNUNET_FS_SearchResult *sr = value; GNUNET_FS_search_start_probe_ (sr); + if (sr->update_search != NULL) + GNUNET_FS_search_continue (sr->update_search); return GNUNET_OK; } +/** + * Create SUSPEND event for the given search operation + * and then clean up our state (without stop signal). + * + * @param cls the 'struct GNUNET_FS_SearchContext' to signal for + */ +static void +search_signal_suspend (void *cls); + + /** * Signal suspend and free the given search result. * @@ -1250,6 +1262,8 @@ search_result_suspend (void *cls, if (sr->download != NULL) GNUNET_FS_download_signal_suspend_ (sr->download); + if (sr->update_search != NULL) + search_signal_suspend (sr->update_search); 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; @@ -1279,20 +1293,10 @@ 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); - 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); @@ -1426,6 +1430,11 @@ search_result_free (void *cls, GNUNET_FS_download_sync_ (sr->download); sr->download = NULL; } + if (NULL != sr->update_search) + { + GNUNET_FS_search_stop (sr->update_search); + GNUNET_assert (sr->update_search == NULL); + } pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; pi.value.search.specifics.result_stopped.cctx = sr->client_info; pi.value.search.specifics.result_stopped.meta = sr->meta; @@ -1455,31 +1464,23 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; unsigned int i; - struct GNUNET_FS_SearchContext *parent; if (sc->top != NULL) GNUNET_FS_end_top (sc->h, sc->top); - if (NULL != (parent = sc->parent)) - { - GNUNET_CONTAINER_DLL_remove (parent->child_head, - parent->child_tail, - sc); - sc->parent = NULL; - } - while (NULL != sc->child_head) - GNUNET_FS_search_stop (sc->child_head); + if (sc->psearch_result != NULL) + sc->psearch_result->update_search = NULL; GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &search_result_free, sc); if (sc->serialization != NULL) { GNUNET_FS_remove_sync_file_ (sc->h, - (sc->parent != NULL) + (sc->psearch_result != NULL) ? GNUNET_FS_SYNC_PATH_CHILD_SEARCH : GNUNET_FS_SYNC_PATH_MASTER_SEARCH, sc->serialization); GNUNET_FS_remove_sync_dir_ (sc->h, - (sc->parent != NULL) + (sc->psearch_result != NULL) ? GNUNET_FS_SYNC_PATH_CHILD_SEARCH : GNUNET_FS_SYNC_PATH_MASTER_SEARCH, sc->serialization); diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index 2207e274e..d40ae4ef7 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h @@ -21,10 +21,6 @@ * @file include/gnunet_fs_service.h * @brief API for file-sharing via GNUnet * @author Christian Grothoff - * - * TODO: - * - extend API with support for publish simulation (-s) - * and URI-argument binding to keyword/namespace (-u) */ #ifndef GNUNET_FS_LIB_H #define GNUNET_FS_LIB_H @@ -1078,8 +1074,10 @@ struct GNUNET_FS_ProgressInfo /** * Client parent-context pointer; NULL for top-level searches, - * non-NULL for automatically triggered searches for updates in - * namespaces. + * refers to the client context of the associated search result + * for automatically triggered searches for updates in + * namespaces. In this case, 'presult' refers to that search + * result. */ void *pctx; -- 2.25.1