From 014972b06f9180cc39ad10b34559b441edc3a33f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 3 May 2010 08:48:06 +0000 Subject: [PATCH] search deserialization --- src/fs/fs.c | 301 +++++++++++++++++++++++++++++++++++++++++++-- src/fs/fs.h | 209 +++++++++++++++++++------------ src/fs/fs_search.c | 150 +++++++++++++--------- 3 files changed, 507 insertions(+), 153 deletions(-) diff --git a/src/fs/fs.c b/src/fs/fs.c index 94777fb05..5b8dc3e90 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -127,9 +127,6 @@ process_job_queue (void *cls, while (NULL != (qe = next)) { next = qe->next; - /* FIXME: might be faster/simpler to do this calculation only once - when we start a job (OTOH, this would allow us to dynamically - and easily adjust qe->blocks over time, given the right API...) */ run_time = GNUNET_TIME_relative_multiply (h->avg_block_latency, qe->blocks * qe->start_times); end_time = GNUNET_TIME_absolute_add (qe->start_time, @@ -1248,6 +1245,21 @@ GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc) } +/** + * Synchronize this search result with its mirror + * on disk. Note that all internal FS-operations that change + * publishing structs should already call "sync" internally, + * so this function is likely not useful for clients. + * + * @param sc the struct to sync + */ +void +GNUNET_FS_search_result_sync_ (struct SearchResult *sr) +{ + /* FIXME */ +} + + /** * Synchronize this search struct with its mirror * on disk. Note that all internal FS-operations that change @@ -1290,7 +1302,7 @@ GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext *sc) return; } #endif - /* FIXME: do search-specific deserialization here! */ + /* FIXME: do search-specific serialization here! */ if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { @@ -1462,6 +1474,250 @@ deserialize_unindex (struct GNUNET_FS_Handle *h) } +/** + * Function called with a filename of serialized search result + * to deserialize. + * + * @param cls the 'struct GNUNET_FS_SearchContext*' + * @param filename complete filename (absolute path) + * @return GNUNET_OK (continue to iterate) + */ +static int +deserialize_search_result (void *cls, + const char *filename) +{ + struct GNUNET_FS_SearchContext *sc = cls; + char pbuf[32]; + char *ser; + char *uris; + char *emsg; + struct GNUNET_BIO_ReadHandle *rh; + struct SearchResult *sr; + GNUNET_HashCode key; + + ser = get_serialization_short_name (filename); + rh = GNUNET_BIO_read_open (filename); + if (rh == NULL) + { + if (ser != NULL) + { + GNUNET_snprintf (pbuf, + sizeof (pbuf), + "%s%s%s", + "search-results", + DIR_SEPARATOR_STR, + sc->serialization); + GNUNET_FS_remove_sync_file_ (sc->h, pbuf, ser); + GNUNET_free (ser); + } + return GNUNET_OK; + } + emsg = NULL; + uris = NULL; + sr = GNUNET_malloc (sizeof (struct SearchResult)); + sr->serialization = ser; + if ( (GNUNET_OK != + GNUNET_BIO_read_string (rh, "result-uri", &uris, 10*1024)) || + (NULL == (sr->uri = GNUNET_FS_uri_parse (uris, &emsg))) || + ( (GNUNET_YES != GNUNET_FS_uri_test_chk (sr->uri)) && + (GNUNET_YES != GNUNET_FS_uri_test_loc (sr->uri)) ) || + (GNUNET_OK != + GNUNET_BIO_read_meta_data (rh, "result-meta", &sr->meta)) || + (GNUNET_OK != + GNUNET_BIO_read (rh, "result-key", &key, sizeof (key))) || + (GNUNET_OK != + GNUNET_BIO_read_int32 (rh, &sr->mandatory_missing)) || + (GNUNET_OK != + GNUNET_BIO_read_int32 (rh, &sr->optional_support)) || + (GNUNET_OK != + GNUNET_BIO_read_int32 (rh, &sr->availability_success)) || + (GNUNET_OK != + GNUNET_BIO_read_int32 (rh, &sr->availability_trials)) ) + goto cleanup; + GNUNET_free (uris); + GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, + &key, + sr, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + return GNUNET_OK; + cleanup: + GNUNET_free_non_null (emsg); + GNUNET_free_non_null (uris); + if (sr->uri != NULL) + GNUNET_FS_uri_destroy (sr->uri); + if (sr->meta != NULL) + GNUNET_CONTAINER_meta_data_destroy (sr->meta); + GNUNET_free (sr->serialization); + GNUNET_free (sr); + return GNUNET_OK; +} + + +/** + * Iterator over search results signaling resume to the client for + * each result. + * + * @param cls closure, the 'struct GNUNET_FS_SearchContext' + * @param key current key code + * @param value value in the hash map, the 'struct SearchResult' + * @return GNUNET_YES (we should continue to iterate) + */ +static int +signal_result_resume (void *cls, + const GNUNET_HashCode * key, + void *value) +{ + struct GNUNET_FS_SearchContext *sc = cls; + struct GNUNET_FS_ProgressInfo pi; + struct SearchResult *sr = value; + + if (0 == sr->mandatory_missing) + { + pi.status = GNUNET_FS_STATUS_SEARCH_RESUME_RESULT; + pi.value.search.specifics.resume_result.meta = sr->meta; + pi.value.search.specifics.resume_result.uri = sr->uri; + pi.value.search.specifics.resume_result.availability_rank = 2*sr->availability_success - sr->availability_trials; + pi.value.search.specifics.resume_result.availability_certainty = sr->availability_trials; + pi.value.search.specifics.resume_result.applicability_rank = sr->optional_support; + sr->client_info = GNUNET_FS_search_make_status_ (&pi, + sc); + } + GNUNET_FS_search_start_probe_ (sr); + return GNUNET_YES; +} + + +/** + * Iterator over search results freeing each. + * + * @param cls closure, the 'struct GNUNET_FS_SearchContext' + * @param key current key code + * @param value value in the hash map, the 'struct SearchResult' + * @return GNUNET_YES (we should continue to iterate) + */ +static int +free_result (void *cls, + const GNUNET_HashCode * key, + void *value) +{ + struct SearchResult *sr = value; + + GNUNET_CONTAINER_meta_data_destroy (sr->meta); + GNUNET_FS_uri_destroy (sr->uri); + GNUNET_free (sr); + return GNUNET_YES; +} + + +/** + * Deserialize a search. + * + * @param h overall context + * @param rh file to deserialize from + * @param parent parent search + * @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, + const char *serialization) +{ + struct GNUNET_FS_SearchContext *sc; + char pbuf[32]; + struct GNUNET_FS_ProgressInfo pi; + char *emsg; + char *uris; + char *child_ser; + char *dn; + uint32_t options; + char in_pause; + + uris = NULL; + child_ser = NULL; + emsg = NULL; + sc = GNUNET_malloc (sizeof (struct GNUNET_FS_SearchContext)); + sc->parent = parent; + sc->h = h; + sc->serialization = GNUNET_strdup (serialization); + if ( (GNUNET_OK != + GNUNET_BIO_read_string (rh, "search-uri", &uris, 10*1024)) || + (NULL == (sc->uri = GNUNET_FS_uri_parse (uris, &emsg))) || + ( (GNUNET_YES != GNUNET_FS_uri_test_ksk (sc->uri)) && + (GNUNET_YES != GNUNET_FS_uri_test_sks (sc->uri)) ) || + (GNUNET_OK != + GNUNET_BIO_read_int64 (rh, &sc->start_time.value)) || + (GNUNET_OK != + GNUNET_BIO_read_string (rh, "child-serialization", &child_ser, 32)) || + (GNUNET_OK != + GNUNET_BIO_read_string (rh, "search-emsg", &sc->emsg, 10*1024)) || + (GNUNET_OK != + GNUNET_BIO_read_int32 (rh, &options)) || + (GNUNET_OK != + GNUNET_BIO_read (rh, "search-pause", &in_pause, sizeof (in_pause))) || + (GNUNET_OK != + GNUNET_BIO_read_int32 (rh, &sc->anonymity)) ) + goto cleanup; + /* FIXME: adjust start_time.value */ + sc->options = (enum GNUNET_FS_SearchOptions) options; + sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16); + GNUNET_snprintf (pbuf, + sizeof (pbuf), + "%s%s%s", + "search-results", + DIR_SEPARATOR_STR, + sc->serialization); + dn = get_serialization_file_name (h, pbuf, ""); + if (dn != NULL) + { + GNUNET_DISK_directory_scan (dn, &deserialize_search_result, sc); + GNUNET_free (dn); + } + if ('\0' == in_pause) + { + if (GNUNET_OK != + GNUNET_FS_search_start_searching_ (sc)) + goto cleanup; + } + if (child_ser != NULL) + { + /* FIXME: deserialize child-search! */ + } + if (parent != NULL) + GNUNET_CONTAINER_DLL_insert (parent->child_head, + parent->child_tail, + sc); + pi.status = GNUNET_FS_STATUS_SEARCH_RESUME; + pi.value.search.specifics.resume.message = sc->emsg; + pi.value.search.specifics.resume.is_paused = ('\0' == in_pause) ? GNUNET_NO : GNUNET_YES; + sc->client_info = GNUNET_FS_search_make_status_ (&pi, + sc); + GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, + &signal_result_resume, + sc); + return sc; + cleanup: + GNUNET_free_non_null (child_ser); + GNUNET_free_non_null (sc->emsg); + GNUNET_free_non_null (emsg); + if (sc->serialization != NULL) + GNUNET_FS_remove_sync_file_ (h, "search", sc->serialization); + /* FIXME: remove 'pbuf' directory with search results as well! */ + GNUNET_free_non_null (sc->serialization); + if (sc->uri != NULL) + GNUNET_FS_uri_destroy (sc->uri); + if (sc->master_result_map != NULL) + { + GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, + &free_result, + sc); + GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); + } + GNUNET_free (sc); + GNUNET_free_non_null (uris); + return NULL; +} + /** * Function called with a filename of serialized search operation @@ -1475,11 +1731,34 @@ static int deserialize_search_file (void *cls, const char *filename) { - /* FIXME */ - // Deserialize Search: - // * for each query, read file with search results - // * for each search result with active download, deserialize download - // * for each directory search result, check for active downloads of contents + struct GNUNET_FS_Handle *h = cls; + char *ser; + char *emsg; + struct GNUNET_BIO_ReadHandle *rh; + struct GNUNET_FS_SearchContext *sc; + + ser = get_serialization_short_name (filename); + rh = GNUNET_BIO_read_open (filename); + if (rh == NULL) + { + if (ser != NULL) + { + GNUNET_FS_remove_sync_file_ (h, "search", ser); + GNUNET_free (ser); + } + return GNUNET_OK; + } + sc = deserialize_search (h, rh, NULL, ser); + GNUNET_free (ser); + if (GNUNET_OK != + GNUNET_BIO_read_close (rh, &emsg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failure while resuming unindexing operation `%s': %s\n"), + filename, + emsg); + GNUNET_free (emsg); + } return GNUNET_OK; } @@ -1490,7 +1769,7 @@ deserialize_search_file (void *cls, * @param h master context */ static void -deserialize_search (struct GNUNET_FS_Handle *h) +deserialize_search_master (struct GNUNET_FS_Handle *h) { char *dn; @@ -1570,7 +1849,7 @@ GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched, /* FIXME: could write one generic deserialization function instead of these four... */ deserialize_publish (ret); - deserialize_search (ret); + deserialize_search_master (ret); /* FIXME: deserialize downloads that are NOT part of searches */ deserialize_unindex (ret); } diff --git a/src/fs/fs.h b/src/fs/fs.h index 3c111f33e..33ee8dde0 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -342,8 +342,7 @@ struct GNUNET_FS_FileInformation struct GNUNET_FS_TreeEncoder *te; /** - * Error message (non-NULL if this operation - * failed). + * Error message (non-NULL if this operation failed). */ char *emsg; @@ -542,6 +541,87 @@ struct GNUNET_FS_QueueEntry +/** + * Information we store for each search result. + */ +struct SearchResult +{ + + /** + * Search context this result belongs to. + */ + struct GNUNET_FS_SearchContext *sc; + + /** + * URI to which this search result refers to. + */ + struct GNUNET_FS_Uri *uri; + + /** + * Metadata for the search result. + */ + struct GNUNET_CONTAINER_MetaData *meta; + + /** + * Client info for this search result. + */ + void *client_info; + + /** + * ID of a job that is currently probing this results' availability + * (NULL if we are not currently probing). + */ + struct GNUNET_FS_DownloadContext *probe_ctx; + + /** + * Name under which this search result is stored on disk. + */ + char *serialization; + + /** + * 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; + + /** + * 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. + */ + uint32_t optional_support; + + /** + * 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. + */ + uint32_t availability_trials; + +}; + + /** * Add a job to the queue. * @@ -698,6 +778,19 @@ GNUNET_FS_unindex_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_UnindexContext *uc, uint64_t offset); +/** + * Fill in all of the generic fields for a search event and + * call the callback. + * + * @param pi structure to fill in + * @param sc overall search context + * @return value returned by the callback + */ +void * +GNUNET_FS_search_make_status_ (struct GNUNET_FS_ProgressInfo *pi, + struct GNUNET_FS_SearchContext *sc); + + /** * Connect to the datastore and remove the blocks. * @@ -706,6 +799,23 @@ GNUNET_FS_unindex_make_status_ (struct GNUNET_FS_ProgressInfo *pi, void GNUNET_FS_unindex_do_remove_ (struct GNUNET_FS_UnindexContext *uc); +/** + * Build the request and actually initiate the search using the + * GNUnet FS service. + * + * @param sc search context + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc); + +/** + * Start download probes for the given search result. + * + * @param sr the search result + */ +void +GNUNET_FS_search_start_probe_ (struct SearchResult *sr); /** * Remove serialization/deserialization file from disk. @@ -731,7 +841,6 @@ GNUNET_FS_remove_sync_file_ (struct GNUNET_FS_Handle *h, void GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *f); - /** * Synchronize this publishing struct with its mirror * on disk. Note that all internal FS-operations that change @@ -743,7 +852,6 @@ GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *f); void GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc); - /** * Synchronize this unindex struct with its mirror * on disk. Note that all internal FS-operations that change @@ -755,8 +863,6 @@ GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc); void GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc); - - /** * Synchronize this search struct with its mirror * on disk. Note that all internal FS-operations that change @@ -768,6 +874,16 @@ GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc); void GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext *sc); +/** + * Synchronize this search result with its mirror + * on disk. Note that all internal FS-operations that change + * publishing structs should already call "sync" internally, + * so this function is likely not useful for clients. + * + * @param sc the struct to sync + */ +void +GNUNET_FS_search_result_sync_ (struct SearchResult *sr); /** @@ -1068,82 +1184,6 @@ struct GNUNET_FS_UnindexContext }; -/** - * Information we store for each search result. - */ -struct SearchResult -{ - - /** - * Search context this result belongs to. - */ - struct GNUNET_FS_SearchContext *sc; - - /** - * URI to which this search result refers to. - */ - struct GNUNET_FS_Uri *uri; - - /** - * Metadata for the search result. - */ - struct GNUNET_CONTAINER_MetaData *meta; - - /** - * Client info for this search result. - */ - void *client_info; - - /** - * 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). - */ - GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; - - /** - * 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. - */ - uint32_t optional_support; - - /** - * 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. - */ - uint32_t availability_trials; - -}; - - /** * Information we keep for each keyword in * a keyword search. @@ -1240,6 +1280,11 @@ struct GNUNET_FS_SearchContext */ char *serialization; + /** + * Error message (non-NULL if this operation failed). + */ + char *emsg; + /** * Map that contains a "struct SearchResult" for each result that * was found in the search. The key for each entry is the XOR of diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index efe5bf34a..a9670cb43 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -24,10 +24,11 @@ * @author Christian Grothoff * * TODO: + * - insert code for serialization where needed + * - remove *directory* with search results upon completion + * - centralize code that sprintf's the 'pbuf[32]' strings * - add support for pushing "already seen" information * to FS service for bloomfilter (can wait) - * - handle availability probes (can wait) - * - make operations persistent (can wait) */ #include "platform.h" @@ -41,16 +42,16 @@ /** - * Fill in all of the generic fields for - * a search event. + * Fill in all of the generic fields for a search event and + * call the callback. * * @param pi structure to fill in * @param sc overall search context * @return value returned by the callback */ -static void * -make_search_status (struct GNUNET_FS_ProgressInfo *pi, - struct GNUNET_FS_SearchContext *sc) +void * +GNUNET_FS_search_make_status_ (struct GNUNET_FS_ProgressInfo *pi, + struct GNUNET_FS_SearchContext *sc) { pi->value.search.sc = sc; pi->value.search.cctx @@ -108,7 +109,7 @@ notify_client_chk_result (struct GNUNET_FS_SearchContext *sc, pi.status = GNUNET_FS_STATUS_SEARCH_RESULT; pi.value.search.specifics.result.meta = sr->meta; pi.value.search.specifics.result.uri = sr->uri; - sr->client_info = make_search_status (&pi, sc); + sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc); } @@ -135,7 +136,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 = make_search_status (&pi, sc); + sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc); } @@ -182,15 +183,6 @@ 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. @@ -207,8 +199,8 @@ signal_probe_result (struct SearchResult *sr) 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); + sr->sc->client_info = GNUNET_FS_search_make_status_ (&pi, sr->sc); + GNUNET_FS_search_start_probe_ (sr); } @@ -343,8 +335,8 @@ GNUNET_FS_search_probe_progress_ (void *cls, * * @param sr the search result */ -static void -start_probe (struct SearchResult *sr) +void +GNUNET_FS_search_start_probe_ (struct SearchResult *sr) { uint64_t off; uint64_t len; @@ -447,7 +439,7 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, notify_client_chk_result (sc, sr); else notify_client_chk_update (sc, sr); - start_probe (sr); + GNUNET_FS_search_start_probe_ (sr); } @@ -510,7 +502,7 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, &key, sr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - start_probe (sr); + GNUNET_FS_search_start_probe_ (sr); /* notify client */ notify_client_chk_result (sc, sr); /* search for updates */ @@ -1067,46 +1059,69 @@ search_start (struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchContext *parent) { struct GNUNET_FS_SearchContext *sc; - struct GNUNET_CLIENT_Connection *client; struct GNUNET_FS_ProgressInfo pi; - size_t size; + + sc = GNUNET_malloc (sizeof(struct GNUNET_FS_SearchContext)); + sc->h = h; + sc->options = options; + sc->uri = GNUNET_FS_uri_dup (uri); + sc->anonymity = anonymity; + sc->start_time = GNUNET_TIME_absolute_get (); + sc->parent = parent; + 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)) + { + GNUNET_FS_uri_destroy (sc->uri); + GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); + GNUNET_free (sc); + return NULL; + } + pi.status = GNUNET_FS_STATUS_SEARCH_START; + sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc); + return sc; +} + + +/** + * Build the request and actually initiate the search using the + * GNUnet FS service. + * + * @param sc search context + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) +{ unsigned int i; const char *keyword; GNUNET_HashCode hc; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; struct GNUNET_CRYPTO_RsaPrivateKey *pk; + size_t size; - if (GNUNET_FS_uri_test_ksk (uri)) + GNUNET_assert (NULL == sc->client); + if (GNUNET_FS_uri_test_ksk (sc->uri)) { - size = sizeof (struct SearchMessage) * uri->data.ksk.keywordCount; + size = sizeof (struct SearchMessage) * sc->uri->data.ksk.keywordCount; } else { - GNUNET_assert (GNUNET_FS_uri_test_sks (uri)); + GNUNET_assert (GNUNET_FS_uri_test_sks (sc->uri)); size = sizeof (struct SearchMessage); } if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Too many keywords specified for a single search.")); - return NULL; + return GNUNET_SYSERR; } - client = GNUNET_CLIENT_connect (h->sched, - "fs", - h->cfg); - if (NULL == client) - return NULL; - sc = GNUNET_malloc (sizeof(struct GNUNET_FS_SearchContext)); - sc->h = h; - sc->options = options; - sc->uri = GNUNET_FS_uri_dup (uri); - sc->anonymity = anonymity; - sc->start_time = GNUNET_TIME_absolute_get (); - sc->client = client; - sc->parent = parent; - sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16); - sc->client_info = cctx; - if (GNUNET_FS_uri_test_ksk (uri)) + if (GNUNET_FS_uri_test_ksk (sc->uri)) { GNUNET_assert (0 != sc->uri->data.ksk.keywordCount); sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * @@ -1130,22 +1145,23 @@ search_start (struct GNUNET_FS_Handle *h, &sc->requests[i].key); } } - if (NULL != parent) - GNUNET_CONTAINER_DLL_insert (parent->child_head, - parent->child_tail, - sc); - pi.status = GNUNET_FS_STATUS_SEARCH_START; - sc->client_info = make_search_status (&pi, sc); - GNUNET_CLIENT_notify_transmit_ready (client, + sc->client = GNUNET_CLIENT_connect (sc->h->sched, + "fs", + sc->h->cfg); + if (NULL == sc->client) + return GNUNET_SYSERR; + GNUNET_CLIENT_notify_transmit_ready (sc->client, size, GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_search_request, - sc); - return sc; + sc); + return GNUNET_OK; } + + /** * Start search for content. * @@ -1188,7 +1204,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; - sc->client_info = make_search_status (&pi, sc); + sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc); } @@ -1207,7 +1223,7 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) do_reconnect (sc, NULL); // FIXME: make persistent! pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; - sc->client_info = make_search_status (&pi, sc); + sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc); } @@ -1226,6 +1242,7 @@ search_result_free (void *cls, { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_FS_Handle *h = sc->h; + char pbuf[32]; struct SearchResult *sr = value; struct GNUNET_FS_ProgressInfo pi; @@ -1233,9 +1250,21 @@ search_result_free (void *cls, 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 = make_search_status (&pi, sc); + sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc); GNUNET_break (NULL == sr->client_info); - + if (sr->serialization != NULL) + { + GNUNET_snprintf (pbuf, + sizeof (pbuf), + "%s%s%s", + "search-results", + DIR_SEPARATOR_STR, + sc->serialization); + GNUNET_FS_remove_sync_file_ (sc->h, + pbuf, + sr->serialization); + GNUNET_free (sr->serialization); + } GNUNET_FS_uri_destroy (sr->uri); GNUNET_CONTAINER_meta_data_destroy (sr->meta); if (sr->probe_ctx != NULL) @@ -1274,7 +1303,7 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) &search_result_free, sc); pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; - sc->client_info = make_search_status (&pi, sc); + 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, @@ -1289,6 +1318,7 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) 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); } -- 2.25.1