0.9.0pre1:
* FS: [CG]
- implement linking of downloads to searches in syncing (serialize/deserialize)
+ - 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!
- persistence testing (publish, unindex, search, download):
=> need driver!
=> schedule suspending tasks DURING event handler => good coverage!
- - track top-level operations in FS_Handle (needed for SUSPEND signalling)
- - generate SUSPEND events (publish, unindex, search, download) AND free memory!
- => 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
}
+/**
+ * Create a top-level activity entry.
+ *
+ * @param h global fs handle
+ * @param ssf suspend signal function to use
+ * @param ssf_cls closure for ssf
+ * @return fresh top-level activity handle
+ */
+struct TopLevelActivity *
+GNUNET_FS_make_top (struct GNUNET_FS_Handle *h,
+ SuspendSignalFunction ssf,
+ void *ssf_cls)
+{
+ struct TopLevelActivity *ret;
+
+ ret = GNUNET_malloc (sizeof (struct TopLevelActivity));
+ ret->ssf = ssf;
+ ret->ssf_cls = ssf_cls;
+ GNUNET_CONTAINER_DLL_insert (h->top_head,
+ h->top_tail,
+ ret);
+ return ret;
+}
+
+
+/**
+ * Destroy a top-level activity entry.
+ *
+ * @param h global fs handle
+ * @param top top level activity entry
+ */
+void
+GNUNET_FS_end_top (struct GNUNET_FS_Handle *h,
+ struct TopLevelActivity *top)
+{
+ GNUNET_CONTAINER_DLL_remove (h->top_head,
+ h->top_tail,
+ top);
+ GNUNET_free (top);
+}
+
+
+
/**
* Closure for "data_reader_file".
*/
void
GNUNET_FS_stop (struct GNUNET_FS_Handle *h)
{
- if (0 != (GNUNET_FS_FLAGS_PERSISTENCE & h->flags))
- {
- // FIXME: generate SUSPEND events and clean up state!
- }
+ /* generate SUSPEND events and clean up state */
+ while (h->top_head != NULL)
+ h->top_head->ssf (h->top_head->ssf_cls);
// FIXME: terminate receive-loop with client (do we need one?)
if (h->queue_job != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (h->sched,
*/
struct ContentHashKey
{
+ /**
+ * Hash of the original content, used for encryption.
+ */
GNUNET_HashCode key;
+
+ /**
+ * Hash of the encrypted content, used for querying.
+ */
GNUNET_HashCode query;
};
};
+/**
+ * Types of URIs.
+ */
enum uri_types
-{ chk, sks, ksk, loc };
+ {
+ /**
+ * Content-hash-key (simple file).
+ */
+ chk,
+
+ /**
+ * Signed key space (file in namespace).
+ */
+ sks,
+
+ /**
+ * Keyword search key (query with keywords).
+ */
+ ksk,
+
+ /**
+ * Location (chk with identity of hosting peer).
+ */
+ loc
+ };
/**
* A Universal Resource Identifier (URI), opaque.
*/
struct GNUNET_FS_Uri
{
+ /**
+ * Type of the URI.
+ */
enum uri_types type;
+
union
{
struct
GNUNET_FS_download_sync_ (struct GNUNET_FS_DownloadContext *dc);
+/**
+ * Function signature of the functions that can be called
+ * to trigger suspend signals and clean-up for top-level
+ * activities.
+ *
+ * @param cls closure
+ */
+typedef void (*SuspendSignalFunction)(void *cls);
+
+/**
+ * We track all of the top-level activities of FS
+ * so that we can signal 'suspend' on shutdown.
+ */
+struct TopLevelActivity
+{
+ /**
+ * This is a doubly-linked list.
+ */
+ struct TopLevelActivity *next;
+
+ /**
+ * This is a doubly-linked list.
+ */
+ struct TopLevelActivity *prev;
+
+ /**
+ * Function to call for suspend-signalling and clean up.
+ */
+ SuspendSignalFunction ssf;
+
+ /**
+ * Closure for 'ssf' (some struct GNUNET_FS_XXXHandle*)
+ */
+ void *ssf_cls;
+};
+
+
+/**
+ * Create a top-level activity entry.
+ *
+ * @param h global fs handle
+ * @param ssf suspend signal function to use
+ * @param ssf_cls closure for ssf
+ * @return fresh top-level activity handle
+ */
+struct TopLevelActivity *
+GNUNET_FS_make_top (struct GNUNET_FS_Handle *h,
+ SuspendSignalFunction ssf,
+ void *ssf_cls);
+
+
+/**
+ * Destroy a top-level activity entry.
+ *
+ * @param h global fs handle
+ * @param top top level activity entry
+ */
+void
+GNUNET_FS_end_top (struct GNUNET_FS_Handle *h,
+ struct TopLevelActivity *top);
+
+
/**
* Master context for most FS operations.
*/
*/
struct GNUNET_CLIENT_Connection *client;
+ /**
+ * Head of DLL of top-level activities.
+ */
+ struct TopLevelActivity *top_head;
+
+ /**
+ * Tail of DLL of top-level activities.
+ */
+ struct TopLevelActivity *top_tail;
+
/**
* Head of DLL of running jobs.
*/
*/
struct GNUNET_FS_Handle *h;
+ /**
+ * Our top-level activity entry (if we are top-level, otherwise NULL).
+ */
+ struct TopLevelActivity *top;
+
/**
* File-structure that is being shared.
*/
*/
struct GNUNET_FS_Handle *h;
+ /**
+ * Our top-level activity entry.
+ */
+ struct TopLevelActivity *top;
+
/**
* Name of the file that we are unindexing.
*/
*/
struct GNUNET_FS_Handle *h;
+ /**
+ * Our top-level activity entry (if we are top-level, otherwise NULL).
+ */
+ struct TopLevelActivity *top;
+
/**
* List of keywords that we're looking for.
*/
* Global FS context.
*/
struct GNUNET_FS_Handle *h;
+
+ /**
+ * Our top-level activity entry (if we are top-level, otherwise NULL).
+ */
+ struct TopLevelActivity *top;
/**
* Connection to the FS service.
}
+/**
+ * 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
+ */
+static void
+download_signal_suspend (void *cls)
+{
+ struct GNUNET_FS_DownloadContext *dc = cls;
+
+ GNUNET_FS_end_top (dc->h, dc->top);
+ /* FIXME: signal! */
+ GNUNET_free (dc);
+}
+
+
/**
* Download parts of a file. Note that this will store
* the blocks at the respective offset in the given file. Also, the
0,
1 /* 0 == CHK, 1 == top */);
GNUNET_FS_download_start_downloading_ (dc);
+ if (parent == NULL)
+ dc->top = GNUNET_FS_make_top (dc->h,
+ &download_signal_suspend,
+ dc);
+
return dc;
}
{
struct GNUNET_FS_ProgressInfo pi;
+ if (dc->top != NULL)
+ GNUNET_FS_end_top (dc->h, dc->top);
if (dc->search != NULL)
{
dc->search->download = NULL;
}
+/**
+ * Create SUSPEND event for the given publish operation
+ * and then clean up our state (without stop signal).
+ *
+ * @param cls the 'struct GNUNET_FS_PublishContext' to signal for
+ */
+static void
+publish_signal_suspend (void *cls)
+{
+ struct GNUNET_FS_PublishContext *pc = cls;
+
+ GNUNET_FS_end_top (pc->h, pc->top);
+ /* FIXME: signal! */
+ GNUNET_free (pc);
+}
+
/**
* Publish a file or directory.
*
&fip_signal_start,
ret);
ret->fi_pos = ret->fi;
-
+ ret->top = GNUNET_FS_make_top (h, &publish_signal_suspend, ret);
// FIXME: calculate space needed for "fi"
// and reserve as first task (then trigger
// "publish_main" from that continuation)!
void
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);
if (pc->serialization != NULL)
}
+/**
+ * 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)
+{
+ struct GNUNET_FS_SearchContext *sc = cls;
+
+ GNUNET_FS_end_top (sc->h, sc->top);
+ /* FIXME: signal! */
+ GNUNET_free (sc);
+}
/**
enum GNUNET_FS_SearchOptions options,
void *cctx)
{
- return search_start (h, uri, anonymity, options, cctx, NULL);
+ 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);
+ return ret;
}
pi.status = GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT;
GNUNET_FS_download_make_status_ (&pi,
sr->download);
+ /* FIXME: promote download to top-level! */
sr->download = NULL;
}
pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED;
unsigned int i;
struct GNUNET_FS_SearchContext *parent;
+ if (sc->top != NULL)
+ GNUNET_FS_end_top (sc->h, sc->top);
// FIXME: make un-persistent!
if (NULL != (parent = sc->parent))
{
}
+/**
+ * Create SUSPEND event for the given unindex operation
+ * and then clean up our state (without stop signal).
+ *
+ * @param cls the 'struct GNUNET_FS_UnindexContext' to signal for
+ */
+static void
+unindex_signal_suspend (void *cls)
+{
+ struct GNUNET_FS_UnindexContext *uc = cls;
+
+ GNUNET_FS_end_top (uc->h, uc->top);
+ /* FIXME: signal! */
+ GNUNET_free (uc);
+}
+
+
/**
* Unindex a file.
*
HASHING_BLOCKSIZE,
&GNUNET_FS_unindex_process_hash_,
ret);
+ ret->top = GNUNET_FS_make_top (h,
+ &unindex_signal_suspend,
+ ret);
return ret;
}
{
struct GNUNET_FS_ProgressInfo pi;
+ GNUNET_FS_end_top (uc->h, uc->top);
if ( (uc->state != UNINDEX_STATE_COMPLETE) &&
(uc->state != UNINDEX_STATE_ERROR) )
{