statistics cli: restructure for better scaling
authorJulius Bünger <buenger@mytum.de>
Sat, 23 Jun 2018 16:11:25 +0000 (18:11 +0200)
committerJulius Bünger <buenger@mytum.de>
Sat, 23 Jun 2018 16:13:29 +0000 (18:13 +0200)
src/statistics/gnunet-statistics.c

index 9093336e133c5836e4d6f00c91c5ea1c3a21b779..a92faa3d74af785dff10e9e907f43e7857524abf 100644 (file)
@@ -158,6 +158,11 @@ static struct GNUNET_CONTAINER_MultiHashMap *values;
  */
 static int num_nodes_ready;
 
+/**
+ * @brief Number of nodes that have their values ready.
+ */
+static int num_nodes_ready_shutdown;
+
 /**
  * @brief Create a new #ValueSet
  *
@@ -248,42 +253,6 @@ printer (void *cls,
   return GNUNET_YES;
 }
 
-/**
- * @brief Called once all statistic values are available.
- *
- * Implements #GNUNET_STATISTICS_Callback
- *
- * @param cls Closure - The index of the node.
- * @param succes Whether statistics were obtained successfully.
- */
-static void
-continuation_print (void *cls,
-                    int success)
-{
-  const unsigned index_node = *(unsigned *) cls;
-
-  nodes[index_node].gh = NULL;
-  if (GNUNET_OK != success)
-  {
-    if (NULL == remote_host)
-      FPRINTF (stderr,
-               "%s",
-               _("Failed to obtain statistics.\n"));
-    else
-      FPRINTF (stderr,
-               _("Failed to obtain statistics from host `%s:%llu'\n"),
-               remote_host,
-               remote_port);
-    ret = 1;
-  }
-  num_nodes_ready++;
-  if (num_nodes_ready == num_nodes)
-  {
-    GNUNET_CONTAINER_multihashmap_iterate (values, printer, NULL);
-    GNUNET_SCHEDULER_shutdown();
-  }
-}
-
 /**
  * Callback function to process statistic values.
  *
@@ -342,6 +311,112 @@ printer_watch (void *cls,
   return GNUNET_OK;
 }
 
+/**
+ * @brief Clean all data structures related to given node.
+ *
+ * Also clears global structures if we are the last node to clean.
+ *
+ * @param cls the index of the node
+ */
+static void
+clean_node (void *cls)
+{
+  const unsigned index_node = *(unsigned *) cls;
+  struct GNUNET_STATISTICS_Handle *h;
+  struct GNUNET_STATISTICS_GetHandle *gh;
+
+  if ( (NULL != path_testbed) && /* were issued with -t <testbed-path> option */
+       (NULL != nodes[index_node].conf) )
+  {
+    GNUNET_CONFIGURATION_destroy (nodes[index_node].conf);
+    nodes[index_node].conf = NULL;
+  }
+
+  h = nodes[index_node].handle;
+  gh = nodes[index_node].gh;
+
+  if (NULL != gh)
+  {
+    GNUNET_STATISTICS_get_cancel (gh);
+    gh = NULL;
+  }
+  if (GNUNET_YES == watch)
+  {
+    GNUNET_assert (GNUNET_OK ==
+      GNUNET_STATISTICS_watch_cancel (h,
+                                      subsystem,
+                                      name,
+                                      &printer_watch,
+                                      &nodes[index_node].index_node));
+  }
+
+  if (NULL != h)
+  {
+    GNUNET_STATISTICS_destroy (h, GNUNET_NO);
+    h = NULL;
+  }
+
+  num_nodes_ready_shutdown++;
+  if (num_nodes == num_nodes_ready_shutdown)
+  {
+    GNUNET_array_grow (nodes, num_nodes, 0);
+    GNUNET_CONTAINER_multihashmap_destroy (values);
+  }
+}
+
+/**
+ * @brief Print and shutdown
+ *
+ * @param cls unused
+ */
+static void
+print_finish (void *cls)
+{
+  GNUNET_CONTAINER_multihashmap_iterate (values, printer, NULL);
+  GNUNET_SCHEDULER_shutdown();
+}
+
+/**
+ * @brief Called once all statistic values are available.
+ *
+ * Implements #GNUNET_STATISTICS_Callback
+ *
+ * @param cls Closure - The index of the node.
+ * @param succes Whether statistics were obtained successfully.
+ */
+static void
+continuation_print (void *cls,
+                    int success)
+{
+  const unsigned index_node = *(unsigned *) cls;
+
+  nodes[index_node].gh = NULL;
+  if (GNUNET_OK != success)
+  {
+    if (NULL == remote_host)
+      FPRINTF (stderr,
+               "%s",
+               _("Failed to obtain statistics.\n"));
+    else
+      FPRINTF (stderr,
+               _("Failed to obtain statistics from host `%s:%llu'\n"),
+               remote_host,
+               remote_port);
+    ret = 1;
+  }
+  if (NULL != nodes[index_node].shutdown_task)
+  {
+    GNUNET_SCHEDULER_cancel (nodes[index_node].shutdown_task);
+    nodes[index_node].shutdown_task = NULL;
+  }
+  GNUNET_SCHEDULER_add_now (clean_node, &nodes[index_node].index_node);
+  num_nodes_ready++;
+  if (num_nodes_ready == num_nodes)
+  {
+    GNUNET_SCHEDULER_add_now (print_finish, NULL);
+  }
+}
+
 /**
  * Function called last by the statistics code.
  *
@@ -423,65 +498,6 @@ collector (void *cls,
   return GNUNET_OK;
 }
 
-/**
- * Function run on shutdown to clean up.
- *
- * @param cls the statistics handle
- */
-static void
-shutdown_task (void *cls)
-{
-  const unsigned index_node = *(unsigned *) cls;
-  struct GNUNET_STATISTICS_Handle *h;
-  struct GNUNET_STATISTICS_GetHandle *gh;
-
-  nodes[index_node].shutdown_task = NULL;
-  if ( (NULL != path_testbed) &&
-       (NULL != nodes[index_node].conf) )
-  {
-    GNUNET_CONFIGURATION_destroy (nodes[index_node].conf);
-    nodes[index_node].conf = NULL;
-  }
-
-  h = nodes[index_node].handle;
-  gh = nodes[index_node].gh;
-  if (NULL == h)
-  {
-    num_nodes_ready--;
-    if (0 == num_nodes_ready)
-    {
-      GNUNET_array_grow (nodes, num_nodes, 0);
-      GNUNET_CONTAINER_multihashmap_destroy (values);
-    }
-    return;
-  }
-  if (NULL != gh)
-  {
-    GNUNET_STATISTICS_get_cancel (gh);
-    gh = NULL;
-  }
-  if ( (GNUNET_YES == watch) &&
-       (NULL != subsystem) &&
-       (NULL != name) )
-    GNUNET_assert (GNUNET_OK ==
-       GNUNET_STATISTICS_watch_cancel (h,
-                                                   subsystem,
-                                                   name,
-                                                   &printer_watch,
-               &nodes[index_node].index_node));
-  GNUNET_STATISTICS_destroy (h,
-                             GNUNET_NO);
-  h = NULL;
-
-  num_nodes_ready--;
-  if (0 == num_nodes_ready)
-  {
-    GNUNET_array_grow (nodes, num_nodes, 0);
-    GNUNET_CONTAINER_multihashmap_destroy (values);
-  }
-}
-
-
 /**
  * Main task that does the actual work.
  *
@@ -562,18 +578,18 @@ main_task (void *cls)
                                  subsystem,
                                  name,
                                  &printer_watch,
-                                &nodes[index_node].index_node))
+                                 &nodes[index_node].index_node))
     {
       fprintf (stderr,
                _("Failed to initialize watch routine\n"));
       nodes[index_node].shutdown_task =
-        GNUNET_SCHEDULER_add_now (&shutdown_task,
+        GNUNET_SCHEDULER_add_now (&clean_node,
                                   &nodes[index_node].index_node);
       return;
     }
   }
   nodes[index_node].shutdown_task =
-    GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+    GNUNET_SCHEDULER_add_shutdown (&clean_node,
                                    &nodes[index_node].index_node);
 }