* @author Christian Grothoff
*
* TODO:
- * - 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)
*/
#define DEBUG_SEARCH GNUNET_NO
-
-
/**
* Fill in all of the generic fields for a search event and
* call the callback.
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);
* @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 *
uint32_t anonymity,
enum GNUNET_FS_SearchOptions options,
void *cctx,
- struct GNUNET_FS_SearchContext *parent);
+ struct GNUNET_FS_SearchResult *psearch);
/**
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);
+ GNUNET_free (uu.data.sks.identifier);
}
sm[i].type = htonl (GNUNET_BLOCK_TYPE_ANY);
sm[i].anonymity_level = htonl (sc->anonymity);
sm[i].query = sc->requests[i].query;
+ /* FIXME: should transmit hash codes of all already-known results here!
+ (and if they do not fit, add another message with the same
+ header and additional already-seen results!) */
}
}
else
GNUNET_CRYPTO_hash_xor (&idh,
&sm->target,
&sm->query);
+ /* FIXME: should transmit hash codes of all already-known results here!
+ (and if they do not fit, add another message with the same
+ header and additional already-seen results!) */
}
GNUNET_CLIENT_receive (sc->client,
&receive_results,
* @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 *
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;
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))
{
}
+/**
+ * Freeze probes for 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_freeze_probes (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;
+
+ if (sr->probe_ctx != NULL)
+ {
+ GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
+ sr->probe_ctx = NULL;
+ }
+ if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (h->sched,
+ 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;
+}
+
+
+/**
+ * Resume probes for 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_resume_probes (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
+{
+ 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;
+}
+
/**
* Signal suspend and free the given search result.
if (sr->download != NULL)
GNUNET_FS_download_signal_suspend_ (sr->download);
+ if (sr->update_search != NULL)
+ GNUNET_FS_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;
*
* @param cls the 'struct GNUNET_FS_SearchContext' to signal for
*/
-static void
-search_signal_suspend (void *cls)
+void
+GNUNET_FS_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);
GNUNET_free_non_null (sc->requests);
GNUNET_free_non_null (sc->emsg);
GNUNET_FS_uri_destroy (sc->uri);
+ GNUNET_free_non_null (sc->serialization);
GNUNET_free (sc);
}
{
struct GNUNET_FS_SearchContext *ret;
ret = search_start (h, uri, anonymity, options, cctx, NULL);
- ret->top = GNUNET_FS_make_top (h, &search_signal_suspend, ret);
+ ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_search_signal_suspend_, ret);
return ret;
}
GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO);
sc->client = NULL;
GNUNET_FS_search_sync_ (sc);
- // FIXME: should this freeze all active probes?
+ GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map,
+ &search_result_freeze_probes,
+ sc);
pi.status = GNUNET_FS_STATUS_SEARCH_PAUSED;
sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc);
}
GNUNET_FS_search_sync_ (sc);
pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED;
sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc);
+ GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map,
+ &search_result_resume_probes,
+ sc);
}
{
struct GNUNET_FS_SearchContext *sc = cls;
struct GNUNET_FS_Handle *h = sc->h;
- char pbuf[32];
struct GNUNET_FS_SearchResult *sr = value;
struct GNUNET_FS_ProgressInfo pi;
if (NULL != sr->download)
{
sr->download->search = NULL;
+ if (NULL != sr->download->serialization)
+ {
+ GNUNET_FS_remove_sync_file_ (sc->h,
+ GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD,
+ sr->download->serialization);
+ GNUNET_free (sr->download->serialization);
+ sr->download->serialization = NULL;
+ }
pi.status = GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT;
GNUNET_FS_download_make_status_ (&pi,
- sr->download);
- /* FIXME: promote download to top-level! */
+ sr->download);
+ 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;
pi.value.search.specifics.result_stopped.uri = sr->uri;
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_free_non_null (sr->serialization);
GNUNET_FS_uri_destroy (sr->uri);
GNUNET_CONTAINER_meta_data_destroy (sr->meta);
if (sr->probe_ctx != NULL)
{
struct GNUNET_FS_ProgressInfo pi;
unsigned int i;
- struct GNUNET_FS_SearchContext *parent;
- int had_result;
if (sc->top != NULL)
GNUNET_FS_end_top (sc->h, sc->top);
- if (sc->serialization != NULL)
- GNUNET_FS_remove_sync_file_ (sc->h,
- (sc->parent != NULL) ? "search-children" : "search",
- sc->serialization);
- 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);
- had_result = (0 != GNUNET_CONTAINER_multihashmap_size (sc->master_result_map)) ? GNUNET_YES : GNUNET_NO;
+ if (sc->psearch_result != NULL)
+ sc->psearch_result->update_search = NULL;
GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map,
&search_result_free,
sc);
- if (had_result)
- GNUNET_FS_remove_sync_dir_ (sc->h, "search-results", sc->serialization);
+ if (sc->serialization != NULL)
+ {
+ GNUNET_FS_remove_sync_file_ (sc->h,
+ (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->psearch_result != NULL)
+ ? GNUNET_FS_SYNC_PATH_CHILD_SEARCH
+ : GNUNET_FS_SYNC_PATH_MASTER_SEARCH,
+ sc->serialization);
+ GNUNET_free (sc->serialization);
+ }
pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED;
sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc);
GNUNET_break (NULL == sc->client_info);