fixing core API for early shutdown handling
authorChristian Grothoff <christian@grothoff.org>
Wed, 4 Nov 2009 15:43:09 +0000 (15:43 +0000)
committerChristian Grothoff <christian@grothoff.org>
Wed, 4 Nov 2009 15:43:09 +0000 (15:43 +0000)
src/core/core_api.c
src/fs/gnunet-service-fs.c
src/hostlist/gnunet-daemon-hostlist.c
src/include/gnunet_core_service.h
src/topology/gnunet-daemon-topology.c

index 91055dd03636634633bb82497925bcdbd1d2a06c..febdfaf4b4b6b9fb3b990b6f6e907b3d3079ff66 100644 (file)
@@ -804,7 +804,7 @@ transmit_start (void *cls, size_t size, void *buf)
  * @param timeout after how long should we give up trying to connect to the core service?
  * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
- *        connected to the core service
+ *        connected to the core service; note that timeout is only meaningful if init is not NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
  * @param bfc function to call to fill up spare bandwidth, can be NULL
@@ -817,8 +817,10 @@ transmit_start (void *cls, size_t size, void *buf)
  *                GNUNET_MessageHeader and hence we do not need to give it the full message
  *                can be used to improve efficiency, ignored if outbound_notify is NULLL
  * @param handlers callbacks for messages we care about, NULL-terminated
+ * @return handle to the core service (only useful for disconnect until 'init' is called);
+ *                NULL on error (in this case, init is never called)
  */
-void
+struct GNUNET_CORE_Handle *
 GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
                      const struct GNUNET_CONFIGURATION_Handle *cfg,
                      struct GNUNET_TIME_Relative timeout,
@@ -835,7 +837,6 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
 {
   struct GNUNET_CORE_Handle *h;
 
-  GNUNET_assert (init != NULL);
   h = GNUNET_malloc (sizeof (struct GNUNET_CORE_Handle));
   h->sched = sched;
   h->cfg = cfg;
@@ -852,9 +853,8 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
   h->client = GNUNET_CLIENT_connect (sched, "core", cfg);
   if (h->client == NULL)
     {
-      init (cls, NULL, NULL, NULL);
       GNUNET_free (h);
-      return;
+      return NULL;
     }
   h->startup_timeout = GNUNET_TIME_relative_to_absolute (timeout);
   h->hcnt = 0;
@@ -874,6 +874,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
                                          sizeof (uint16_t) * h->hcnt, timeout,
                                         GNUNET_YES,
                                          &transmit_start, h);
+  return h;
 }
 
 
index ca6b9b426c1bab003aacbbfe646b0360f790531d..0e592e094a201a3b4acd1c58462c6ccd5d64ebca 100644 (file)
@@ -792,6 +792,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *connected_peers;
  */
 static uint64_t max_pending_requests = 32;
 
+
 /**
  * Write the current index information list to disk.
  */ 
@@ -2326,10 +2327,16 @@ shutdown_task (void *cls,
   struct IndexInfo *pos;  
 
   if (NULL != core)
-    GNUNET_CORE_disconnect (core);
-  GNUNET_DATASTORE_disconnect (dsh,
-                              GNUNET_NO);
-  dsh = NULL;
+    {
+      GNUNET_CORE_disconnect (core);
+      core = NULL;
+    }
+  if (NULL != dsh)
+    {
+      GNUNET_DATASTORE_disconnect (dsh,
+                                  GNUNET_NO);
+      dsh = NULL;
+    }
   GNUNET_CONTAINER_multihashmap_iterate (requests_by_query,
                                         &destroy_pending_request_cb,
                                         NULL);
@@ -3274,73 +3281,6 @@ static struct GNUNET_CORE_MessageHandler p2p_handlers[] =
   };
 
 
-/**
- * Task that will try to initiate a connection with the
- * core service.
- * 
- * @param cls unused
- * @param tc unused
- */
-static void
-core_connect_task (void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Function called by the core after we've
- * connected.
- *
- * @param cls closure, unused
- * @param server handle to the core service
- * @param my_identity our peer identity (unused)
- * @param publicKey our public key (unused)
- */
-static void
-core_start_cb (void *cls,
-              struct GNUNET_CORE_Handle * server,
-              const struct GNUNET_PeerIdentity *
-              my_identity,
-              const struct
-              GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
-              publicKey)
-{
-  if (server == NULL)
-    {
-      GNUNET_SCHEDULER_add_delayed (sched,
-                                   GNUNET_TIME_UNIT_SECONDS,
-                                   &core_connect_task,
-                                   NULL);
-      return;
-    }
-  core = server;
-}
-
-
-/**
- * Task that will try to initiate a connection with the
- * core service.
- * 
- * @param cls unused
- * @param tc unused
- */
-static void
-core_connect_task (void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_CORE_connect (sched,
-                      cfg,
-                      GNUNET_TIME_UNIT_FOREVER_REL,
-                      NULL,
-                      &core_start_cb,
-                      &peer_connect_handler,
-                      &peer_disconnect_handler,
-                      NULL, 
-                      NULL, GNUNET_NO,
-                      NULL, GNUNET_NO,
-                      p2p_handlers);
-}
-
-
 /**
  * Process fs requests.
  *
@@ -3366,21 +3306,42 @@ run (void *cls,
   read_index_list ();
   dsh = GNUNET_DATASTORE_connect (cfg,
                                  sched);
-  if (NULL == dsh)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Failed to connect to datastore service.\n"));
-      return;
-    }
+  core = GNUNET_CORE_connect (sched,
+                             cfg,
+                             GNUNET_TIME_UNIT_FOREVER_REL,
+                             NULL,
+                             NULL,
+                             &peer_connect_handler,
+                             &peer_disconnect_handler,
+                             NULL, 
+                             NULL, GNUNET_NO,
+                             NULL, GNUNET_NO,
+                             p2p_handlers);
+
   GNUNET_SERVER_disconnect_notify (server, 
                                   &handle_client_disconnect,
                                   NULL);
   GNUNET_SERVER_add_handlers (server, handlers);
-  core_connect_task (NULL, NULL);
   GNUNET_SCHEDULER_add_delayed (sched,
                                GNUNET_TIME_UNIT_FOREVER_REL,
                                &shutdown_task,
                                NULL);
+  if (NULL == dsh)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to connect to `%s' service.\n"),
+                 "datastore");
+      GNUNET_SCHEDULER_shutdown (sched);
+      return;
+    }
+  if (NULL == core)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to connect to `%s' service.\n"),
+                 "core");
+      GNUNET_SCHEDULER_shutdown (sched);
+      return;
+    }
 }
 
 
index 78584cac93dcc61f5ea8cd77d62d8e555edb4527..2c4aca6d0d1d07a5c066e022159b508f2e38290e 100644 (file)
@@ -70,6 +70,11 @@ static int provide_hostlist;
  */
 static struct GNUNET_STATISTICS_Handle *stats;
 
+/**
+ * Handle to the core service (NULL until we've connected to it).
+ */
+struct GNUNET_CORE_Handle *core;
+
 /**
  * gnunet-daemon-hostlist command line options.
  */
@@ -119,6 +124,7 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                                 GNUNET_NO);
       stats = NULL;
     }
+  GNUNET_CORE_disconnect (core);
 }
 
 
@@ -167,18 +173,26 @@ run (void *cls,
     {      
       GNUNET_HOSTLIST_server_start (cfg, sched, stats);
     }
-  GNUNET_CORE_connect (sched, cfg,
-                      GNUNET_TIME_UNIT_FOREVER_REL,
-                      NULL,
-                      &core_init,
-                      ch, dh,
-                      NULL,
-                      NULL, GNUNET_NO,
-                      NULL, GNUNET_NO,
-                      handlers);
+  core = GNUNET_CORE_connect (sched, cfg,
+                             GNUNET_TIME_UNIT_FOREVER_REL,
+                             NULL,
+                             &core_init,
+                             ch, dh,
+                             NULL,
+                             NULL, GNUNET_NO,
+                             NULL, GNUNET_NO,
+                             handlers);
   GNUNET_SCHEDULER_add_delayed (sched,
                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                 &cleaning_task, NULL);
+  if (NULL == core)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to connect to `%s' service.\n"),
+                 "core");
+      GNUNET_SCHEDULER_shutdown (sched);
+      return;     
+    }
 }
 
 
index ca02f9874fe88aa3c31cb22ac1b2c7b847a2bad6..dbe39d0d7e4e50640c7dd65a6ed8cf36cf7e620d 100644 (file)
@@ -156,7 +156,7 @@ typedef void
  * @param timeout after how long should we give up trying to connect to the core service?
  * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
- *        connected to the core service
+ *        connected to the core service; note that timeout is only meaningful if init is not NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
  * @param bfc function to call to fill up spare bandwidth, can be NULL
@@ -169,8 +169,10 @@ typedef void
  *                GNUNET_MessageHeader and hence we do not need to give it the full message
  *                can be used to improve efficiency, ignored if outbound_notify is NULLL
  * @param handlers callbacks for messages we care about, NULL-terminated
+ * @return handle to the core service (only useful for disconnect until 'init' is called),
+ *           NULL on error (in this case, init is never called)
  */
-void
+struct GNUNET_CORE_Handle *
 GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
                      const struct GNUNET_CONFIGURATION_Handle *cfg,
                      struct GNUNET_TIME_Relative timeout,
index cdf3da809f7865185383925213b7f064df4fa506..be6f272be17fe7312357aaf743a5d37cab7e1cfd 100644 (file)
@@ -809,6 +809,7 @@ core_init (void *cls,
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to core service, can not manage topology!\n"));
+      GNUNET_SCHEDULER_shutdown (sched);
       return;
     }
   handle = server;
@@ -1136,8 +1137,11 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
   GNUNET_TRANSPORT_disconnect (transport);
   transport = NULL;
-  GNUNET_CORE_disconnect (handle);
-  handle = NULL;
+  if (handle != NULL)
+    {
+      GNUNET_CORE_disconnect (handle);
+      handle = NULL;
+    }
   while (NULL != (pl = friends))
     {
       friends = pl->next;
@@ -1208,21 +1212,36 @@ run (void *cls,
                                        NULL,
                                        NULL,
                                        NULL);
-  GNUNET_CORE_connect (sched,
-                      cfg,
-                      GNUNET_TIME_UNIT_FOREVER_REL,
-                      NULL,
-                      &core_init,
-                      &connect_notify,
-                      &disconnect_notify,
-                      &hello_advertising,
-                      NULL, GNUNET_NO,
-                      NULL, GNUNET_NO,
-                      handlers);
-
+  handle = GNUNET_CORE_connect (sched,
+                               cfg,
+                               GNUNET_TIME_UNIT_FOREVER_REL,
+                               NULL,
+                               &core_init,
+                               &connect_notify,
+                               &disconnect_notify,
+                               &hello_advertising,
+                               NULL, GNUNET_NO,
+                               NULL, GNUNET_NO,
+                               handlers);
   GNUNET_SCHEDULER_add_delayed (sched,
                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                 &cleaning_task, NULL);
+  if (NULL == transport)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to connect to `%s' service.\n"),
+                 "transport");
+      GNUNET_SCHEDULER_shutdown (sched);
+      return;
+    }
+  if (NULL == handle)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to connect to `%s' service.\n"),
+                 "core");
+      GNUNET_SCHEDULER_shutdown (sched);
+      return;
+    }
 }