generating SUSPEND events
authorChristian Grothoff <christian@grothoff.org>
Tue, 4 May 2010 08:50:09 +0000 (08:50 +0000)
committerChristian Grothoff <christian@grothoff.org>
Tue, 4 May 2010 08:50:09 +0000 (08:50 +0000)
TODO
src/fs/fs.h
src/fs/fs_download.c
src/fs/fs_publish.c
src/fs/fs_search.c
src/fs/fs_unindex.c
src/include/gnunet_fs_service.h

diff --git a/TODO b/TODO
index 861e2915d9012646a70d44347ac9e43f8f5fb9f3..14f1d5ce61c710e572a532640c8f1e4be5617a2d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,5 @@
 0.9.0pre1:
 * FS: [CG]
-  - 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!
@@ -10,6 +8,7 @@
   - persistence testing (publish, unindex, search, download):
     => need driver!
     => schedule suspending tasks DURING event handler => good coverage!
+    => 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 275882c4f6560db4356419644a35007fc89c602c..1d3498a7cb18b403591a8a63c8f3332b3cd6a436 100644 (file)
@@ -1025,6 +1025,16 @@ GNUNET_FS_end_top (struct GNUNET_FS_Handle *h,
                   struct TopLevelActivity *top);
 
 
+/**
+ * Create SUSPEND event for the given download operation
+ * and then clean up our state (without stop signal).
+ *
+ * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for
+ */
+void
+GNUNET_FS_download_signal_suspend_ (void *cls);
+
+
 /**
  * Master context for most FS operations.
  */
index d7c5370b1f0dd3dccf8d90348f83800abdba9a09..2fd8e0412b121b6977fcc5d98237f2efbef9ebc2 100644 (file)
@@ -1383,19 +1383,68 @@ deactivate_fs_download (void *cls)
 }
 
 
+/**
+ * Free entries in the map.
+ *
+ * @param cls unused (NULL)
+ * @param key unused
+ * @param entry entry of type "struct DownloadRequest" which is freed
+ * @return GNUNET_OK
+ */
+static int
+free_entry (void *cls,
+           const GNUNET_HashCode *key,
+           void *entry)
+{
+  GNUNET_free (entry);
+  return GNUNET_OK;
+}
+
+
 /**
  * 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
+ * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for
  */
-static void
-download_signal_suspend (void *cls)
+void
+GNUNET_FS_download_signal_suspend_ (void *cls)
 {
   struct GNUNET_FS_DownloadContext *dc = cls;
+  struct GNUNET_FS_ProgressInfo pi;
   
-  GNUNET_FS_end_top (dc->h, dc->top);
-  /* FIXME: signal! */
+  if (dc->top != NULL)
+    GNUNET_FS_end_top (dc->h, dc->top);
+  while (NULL != dc->child_head)
+    GNUNET_FS_download_signal_suspend_ (dc->child_head);  
+  if (dc->search != NULL)
+    {
+      dc->search->download = NULL;
+      dc->search = NULL;
+    }
+  if (dc->job_queue != NULL)
+    {
+      GNUNET_FS_dequeue_ (dc->job_queue);
+      dc->job_queue = NULL;
+    }
+  if (dc->parent != NULL)
+    GNUNET_CONTAINER_DLL_remove (dc->parent->child_head,
+                                dc->parent->child_tail,
+                                dc);  
+  pi.status = GNUNET_FS_STATUS_DOWNLOAD_SUSPEND;
+  GNUNET_FS_download_make_status_ (&pi, dc);
+  if (GNUNET_SCHEDULER_NO_TASK != dc->task)
+    GNUNET_SCHEDULER_cancel (dc->h->sched,
+                            dc->task);
+  GNUNET_CONTAINER_multihashmap_iterate (dc->active,
+                                        &free_entry,
+                                        NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (dc->active);
+  GNUNET_free_non_null (dc->filename);
+  GNUNET_CONTAINER_meta_data_destroy (dc->meta);
+  GNUNET_FS_uri_destroy (dc->uri);
+  GNUNET_free_non_null (dc->temp_filename);
+  GNUNET_free_non_null (dc->serialization);
   GNUNET_free (dc);
 }
 
@@ -1515,7 +1564,7 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
   GNUNET_FS_download_start_downloading_ (dc);
   if (parent == NULL)
     dc->top = GNUNET_FS_make_top (dc->h,
-                                 &download_signal_suspend,
+                                 &GNUNET_FS_download_signal_suspend_,
                                  dc);
 
   return dc;
@@ -1662,24 +1711,6 @@ GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc)
 }
 
 
-/**
- * Free entries in the map.
- *
- * @param cls unused (NULL)
- * @param key unused
- * @param entry entry of type "struct DownloadRequest" which is freed
- * @return GNUNET_OK
- */
-static int
-free_entry (void *cls,
-           const GNUNET_HashCode *key,
-           void *entry)
-{
-  GNUNET_free (entry);
-  return GNUNET_OK;
-}
-
-
 /**
  * Stop a download (aborts if download is incomplete).
  *
index 4101174bbe223977fce4b19a498245683bc2d4c3..0c4ebba7ba0a2e4eca222b160280aa82d5e4c4bb 100644 (file)
@@ -929,6 +929,46 @@ fip_signal_start(void *cls,
 }
 
 
+/**
+ * Signal the FS's progress function that we are suspending
+ * an upload.
+ *
+ * @param cls closure (of type "struct GNUNET_FS_PublishContext*")
+ * @param fi the entry in the publish-structure
+ * @param length length of the file or directory
+ * @param meta metadata for the file or directory (can be modified)
+ * @param uri pointer to the keywords that will be used for this entry (can be modified)
+ * @param anonymity pointer to selected anonymity level (can be modified)
+ * @param priority pointer to selected priority (can be modified)
+ * @param expirationTime pointer to selected expiration time (can be modified)
+ * @param client_info pointer to client context set upon creation (can be modified)
+ * @return GNUNET_OK to continue (always)
+ */
+static int
+fip_signal_suspend(void *cls,
+                  struct GNUNET_FS_FileInformation *fi,
+                  uint64_t length,
+                  struct GNUNET_CONTAINER_MetaData *meta,
+                  struct GNUNET_FS_Uri **uri,
+                  uint32_t *anonymity,
+                  uint32_t *priority,
+                  struct GNUNET_TIME_Absolute *expirationTime,
+                  void **client_info)
+{
+  struct GNUNET_FS_PublishContext*sc = cls;
+  struct GNUNET_FS_ProgressInfo pi;
+  uint64_t off;
+
+  GNUNET_free_non_null (fi->serialization);
+  fi->serialization = NULL;    
+  off = (fi->chk_uri == NULL) ? 0 : length;
+  pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED;
+  GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, sc, fi, off));
+  *client_info = NULL;
+  return GNUNET_OK;
+}
+
+
 /**
  * Create SUSPEND event for the given publish operation
  * and then clean up our state (without stop signal).
@@ -940,9 +980,16 @@ publish_signal_suspend (void *cls)
 {
   struct GNUNET_FS_PublishContext *pc = cls;
 
+  if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task)
+    {
+      GNUNET_SCHEDULER_cancel (pc->h->sched, pc->upload_task);
+      pc->upload_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  GNUNET_FS_file_information_inspect (pc->fi,
+                                     &fip_signal_suspend,
+                                     pc);
   GNUNET_FS_end_top (pc->h, pc->top);
-  /* FIXME: signal! */
-  GNUNET_free (pc);
+  publish_cleanup (pc);
 }
 
 /**
@@ -1074,7 +1121,10 @@ 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);
+    {
+      GNUNET_SCHEDULER_cancel (pc->h->sched, pc->upload_task);
+      pc->upload_task = GNUNET_SCHEDULER_NO_TASK;
+    }
   if (pc->serialization != NULL) 
     {
       GNUNET_FS_remove_sync_file_ (pc->h, "publish", pc->serialization);
index 9ab024eeb09d9010f44d2cc71ddcd614608b8535..36aa26193cab89a2c794fd949db8b5730c84109b 100644 (file)
@@ -1168,6 +1168,46 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc)
 }
 
 
+
+/**
+ * Signal suspend and free 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_suspend (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;
+  struct GNUNET_FS_ProgressInfo pi;
+
+  if (sr->download != NULL)
+    GNUNET_FS_download_signal_suspend_ (sr->download);
+  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;
+  pi.value.search.specifics.result_suspend.uri = sr->uri;
+  sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc);
+  GNUNET_break (NULL == sr->client_info);
+  GNUNET_free_non_null (sr->serialization);
+  GNUNET_FS_uri_destroy (sr->uri);
+  GNUNET_CONTAINER_meta_data_destroy (sr->meta);
+  if (sr->probe_ctx != NULL)
+    GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);    
+  if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (h->sched,
+                            sr->probe_cancel_task);    
+  GNUNET_free (sr);
+  return GNUNET_OK;
+}
+
+
 /**
  * Create SUSPEND event for the given search operation
  * and then clean up our state (without stop signal).
@@ -1178,9 +1218,41 @@ 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);
-  /* FIXME: signal! */
+  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);
+  pi.status = GNUNET_FS_STATUS_SEARCH_SUSPEND;
+  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,
+                            sc->task);
+  if (NULL != sc->client)
+    GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO);
+  GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map);
+  if (sc->requests != NULL)
+    {
+      GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri));
+      for (i=0;i<sc->uri->data.ksk.keywordCount;i++)
+       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);
 }
 
index 6d4ee3f54b45f8b7f34d5aabc3365c98562a648b..c79b3413ea96ba32db8c852896aa7101d94d4a39 100644 (file)
@@ -403,9 +403,16 @@ static void
 unindex_signal_suspend (void *cls)
 {
   struct GNUNET_FS_UnindexContext *uc = cls;
+  struct GNUNET_FS_ProgressInfo pi;
 
   GNUNET_FS_end_top (uc->h, uc->top);
-  /* FIXME: signal! */
+  pi.status = GNUNET_FS_STATUS_UNINDEX_SUSPEND;
+  GNUNET_FS_unindex_make_status_ (&pi, uc, 
+                                 (uc->state == UNINDEX_STATE_COMPLETE)
+                                 ? uc->file_size : 0);
+  GNUNET_break (NULL == uc->client_info);
+  GNUNET_free (uc->filename);
+  GNUNET_free_non_null (uc->serialization);
   GNUNET_free (uc);
 }
 
@@ -476,6 +483,7 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc)
   if (uc->serialization != NULL)
     {
       GNUNET_FS_remove_sync_file_ (uc->h, "unindex", uc->serialization);
+      GNUNET_free (uc->serialization);
       uc->serialization = NULL;
     }
   pi.status = GNUNET_FS_STATUS_UNINDEX_STOPPED;
@@ -485,7 +493,6 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc)
                                  ? uc->file_size : 0);
   GNUNET_break (NULL == uc->client_info);
   GNUNET_free (uc->filename);
-  GNUNET_free_non_null (uc->serialization);
   GNUNET_free (uc);
 }
 
index 0645a11c4b01e075a8bedfd4845629636e3f7d4c..2207e274e336295671cfb056da0c102095820b0e 100644 (file)
@@ -646,6 +646,12 @@ enum GNUNET_FS_Status
    */
   GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED,
 
+  /**
+   * Event generated for each search result
+   * when the respective search is suspended.
+   */
+  GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND,
+
   /**
    * Last message from a search; this signals
    * that there will be no further events associated