towards suspend
authorChristian Grothoff <christian@grothoff.org>
Mon, 3 May 2010 21:35:44 +0000 (21:35 +0000)
committerChristian Grothoff <christian@grothoff.org>
Mon, 3 May 2010 21:35:44 +0000 (21:35 +0000)
TODO
src/fs/fs.c
src/fs/fs.h
src/fs/fs_download.c
src/fs/fs_publish.c
src/fs/fs_search.c
src/fs/fs_unindex.c

diff --git a/TODO b/TODO
index 88d5d2877c58b4381009c89b3cb7995cdae7093c..c9141e21fc688b69e0d3d02742d5e45c8f3a0ac3 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,8 @@
 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!
@@ -9,9 +11,6 @@
   - 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
index f0753eee24cc4af889e3a606d0f6773440bf309a..d0e73b21a6e38554f3cdb7449e492031db49fa1b 100644 (file)
@@ -212,6 +212,49 @@ GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh)
 }
 
 
+/**
+ * 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".
  */
@@ -2513,10 +2556,9 @@ GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched,
 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,
index 7b30367ea88b40922875254a162301268664712d..275882c4f6560db4356419644a35007fc89c602c 100644 (file)
  */
 struct ContentHashKey 
 {
+  /**
+   * Hash of the original content, used for encryption.
+   */
   GNUNET_HashCode key;
+
+  /**
+   * Hash of the encrypted content, used for querying.
+   */
   GNUNET_HashCode query;
 };
 
@@ -212,15 +219,42 @@ struct Location
 
 };
 
+/**
+ * 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
@@ -929,6 +963,68 @@ void
 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.
  */
@@ -964,6 +1060,16 @@ struct GNUNET_FS_Handle
    */
   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.
    */
@@ -1034,6 +1140,11 @@ struct GNUNET_FS_PublishContext
    */ 
   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.
    */
@@ -1162,6 +1273,11 @@ struct GNUNET_FS_UnindexContext
    */
   struct GNUNET_FS_Handle *h;
 
+  /**
+   * Our top-level activity entry.
+   */
+  struct TopLevelActivity *top;
+
   /**
    * Name of the file that we are unindexing.
    */
@@ -1273,6 +1389,11 @@ struct GNUNET_FS_SearchContext
    */
   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.
    */
@@ -1420,6 +1541,11 @@ struct GNUNET_FS_DownloadContext
    * 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.
index 6390539bcf7cce7e2958441da879dd6410e8d491..bf59918e7534f47adfade0b52fb59b5efef1669c 100644 (file)
@@ -1383,6 +1383,23 @@ deactivate_fs_download (void *cls)
 }
 
 
+/**
+ * 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
@@ -1496,6 +1513,11 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
                           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;
 }
 
@@ -1665,6 +1687,8 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *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;
index c4dbe624eb35b21cb3d0b73aed64fea58a2ee6b0..4101174bbe223977fce4b19a498245683bc2d4c3 100644 (file)
@@ -929,6 +929,22 @@ fip_signal_start(void *cls,
 }
 
 
+/**
+ * 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.
  *
@@ -983,7 +999,7 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h,
                                      &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)!
@@ -1056,6 +1072,7 @@ fip_signal_stop(void *cls,
 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) 
index 611a089c412c8e93d0cb9729cb3283b558e85afb..00909ce97f42b8d2b5ab22fa911610b3d1655fc8 100644 (file)
@@ -1161,6 +1161,21 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc)
 }
 
 
+/**
+ * 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);
+}
 
 
 /**
@@ -1181,7 +1196,10 @@ GNUNET_FS_search_start (struct GNUNET_FS_Handle *h,
                        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;
 }
 
 
@@ -1253,6 +1271,7 @@ search_result_free (void *cls,
       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;
@@ -1298,6 +1317,8 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc)
   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))
     {
index 4b4e526dd412035c4d9fa40f680f4ea36c7aed70..6d4ee3f54b45f8b7f34d5aabc3365c98562a648b 100644 (file)
@@ -393,6 +393,23 @@ GNUNET_FS_unindex_process_hash_ (void *cls,
 }
 
 
+/**
+ * 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.
  *
@@ -432,6 +449,9 @@ GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h,
                           HASHING_BLOCKSIZE,
                           &GNUNET_FS_unindex_process_hash_,
                           ret);
+  ret->top = GNUNET_FS_make_top (h,
+                                &unindex_signal_suspend,
+                                ret);
   return ret;
 }
 
@@ -446,6 +466,7 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc)
 {  
   struct GNUNET_FS_ProgressInfo pi;
 
+  GNUNET_FS_end_top (uc->h, uc->top);
   if ( (uc->state != UNINDEX_STATE_COMPLETE) &&
        (uc->state != UNINDEX_STATE_ERROR) )
     {