use one scheduling function
[oweals/gnunet.git] / src / ats-tests / perf_ats.c
index 4757a78d2b0e9122cd654734176b4fc270f25344..6198d1464c9f3784261a83a5d803afa7967f4c73 100644 (file)
 #include "gnunet_testbed_service.h"
 #include "gnunet_ats_service.h"
 #include "gnunet_core_service.h"
+#include "perf_ats.h"
 
-#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
-#define BENCHMARK_DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
-#define TESTNAME_PREFIX "perf_ats_"
-#define DEFAULT_SLAVES_NUM 3
-#define DEFAULT_MASTERS_NUM 1
 
 #define TEST_ATS_PREFRENCE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 #define TEST_ATS_PREFRENCE_START 1.0
 #define TEST_MESSAGE_SIZE 1000
 #define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 
-/**
- * Information about a benchmarking partner
- */
-struct BenchmarkPartner
-{
-  /**
-   * The peer itself this partner belongs to
-   */
-  struct BenchmarkPeer *me;
-
-  /**
-   * The partner peer
-   */
-  struct BenchmarkPeer *dest;
-
-  /**
-   * Core transmit handles
-   */
-  struct GNUNET_CORE_TransmitHandle *cth;
-
-  /**
-   * Transport transmit handles
-   */
-  struct GNUNET_TRANSPORT_TransmitHandle *tth;
-
-  /**
-   * Number of messages sent to this partner
-   */
-  unsigned int messages_sent;
-
-  /**
-   * Number of bytes sent to this partner
-   */
-  unsigned int bytes_sent;
-
-  /**
-   * Number of messages received from this partner
-   */
-  unsigned int messages_received;
-
-  /**
-   * Number of bytes received from this partner
-   */
-  unsigned int bytes_received;
-};
-
 /**
  * Connect peers with testbed
  */
@@ -111,123 +61,6 @@ struct TestbedConnectOperation
   struct GNUNET_TESTBED_Operation *connect_op;
 };
 
-/**
- * Information we track for a peer in the testbed.
- */
-struct BenchmarkPeer
-{
-  /**
-   * Handle with testbed.
-   */
-  struct GNUNET_TESTBED_Peer *peer;
-
-  /**
-   * Unique identifier
-   */
-  int no;
-
-  /**
-   * Is this peer a measter: GNUNET_YES/GNUNET_NO
-   */
-  int master;
-
-  /**
-   *  Peer ID
-   */
-  struct GNUNET_PeerIdentity id;
-
-  /**
-   * Testbed operation to get peer information
-   */
-  struct GNUNET_TESTBED_Operation *peer_id_op;
-
-  /**
-   * Testbed operation to connect to ATS performance service
-   */
-  struct GNUNET_TESTBED_Operation *ats_perf_op;
-
-  /**
-   * Testbed operation to connect to core
-   */
-  struct GNUNET_TESTBED_Operation *comm_op;
-
-  /**
-   * ATS performance handle
-   */
-  struct GNUNET_ATS_PerformanceHandle *ats_perf_handle;
-
-  /**
-   * Masters only:
-   * Testbed connect operations to connect masters to slaves
-   */
-  struct TestbedConnectOperation *core_connect_ops;
-
-  /**
-   *  Core handle
-   */
-  struct GNUNET_CORE_Handle *ch;
-
-  /**
-   *  Core handle
-   */
-  struct GNUNET_TRANSPORT_Handle *th;
-
-  /**
-   * Masters only:
-   * Peer to set ATS preferences for
-   */
-  struct BenchmarkPeer *pref_partner;
-
-  /**
-   * Masters only
-   * Progress task
-   */
-  GNUNET_SCHEDULER_TaskIdentifier ats_task;
-
-  /**
-   * Masters only
-   * Progress task
-   */
-  double pref_value;
-
-  /**
-   * Array of partners with num_slaves entries (if master) or
-   * num_master entries (if slave)
-   */
-  struct BenchmarkPartner *partners;
-
-  /**
-   * Number of core connections
-   */
-  int core_connections;
-
-  /**
-   * Masters only:
-   * Number of connections to slave peers
-   */
-  int core_slave_connections;
-
-  /**
-   * Total number of messages this peer has sent
-   */
-  unsigned int total_messages_sent;
-
-  /**
-   * Total number of bytes this peer has sent
-   */
-  unsigned int total_bytes_sent;
-
-  /**
-   * Total number of messages this peer has received
-   */
-  unsigned int total_messages_received;
-
-  /**
-   * Total number of bytes this peer has received
-   */
-  unsigned int total_bytes_received;
-};
-
 /**
  * Overall state of the performance benchmark
  */
@@ -264,6 +97,11 @@ static GNUNET_SCHEDULER_TaskIdentifier progress_task;
  */
 static int result;
 
+/**
+ * Test result logging
+ */
+static int logging;
+
 /**Test core (GNUNET_YES) or transport (GNUNET_NO)
  */
 static int test_core;
@@ -273,6 +111,11 @@ static int test_core;
  */
 static char *solver;
 
+/**
+ * Preference string
+ */
+static char *testname;
+
 /**
  * Preference string
  */
@@ -291,7 +134,7 @@ static int num_masters;
 /**
  * Array of master peers
  */
-struct BenchmarkPeer *mps;
+static  struct BenchmarkPeer *mps;
 
 /**
  * Number slave peers
@@ -300,7 +143,17 @@ static int num_slaves;
 /**
  * Array of slave peers
  */
-struct BenchmarkPeer *sps;
+static struct BenchmarkPeer *sps;
+
+/**
+ * Benchmark duration
+ */
+static struct GNUNET_TIME_Relative perf_duration;
+
+/**
+ * Logging frequency
+ */
+static struct GNUNET_TIME_Relative log_frequency;
 
 /**
  * Benchmark state
@@ -315,7 +168,7 @@ evaluate ()
   unsigned int duration;
   struct BenchmarkPeer *mp;
 
-  duration = (BENCHMARK_DURATION.rel_value_us / (1000 * 1000));
+  duration = (perf_duration.rel_value_us / (1000 * 1000));
   for (c_m = 0; c_m < num_masters; c_m++)
   {
     mp = &mps[c_m];
@@ -353,6 +206,9 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   int c_s;
   int c_op;
 
+  if (GNUNET_YES == logging)
+    perf_logging_stop();
+
   shutdown_task = GNUNET_SCHEDULER_NO_TASK;
   if (GNUNET_SCHEDULER_NO_TASK != progress_task)
   {
@@ -508,21 +364,32 @@ static size_t
 comm_send_ready (void *cls, size_t size, void *buf)
 {
   static char msgbuf[TEST_MESSAGE_SIZE];
-  struct BenchmarkPartner *partner = cls;
+  struct BenchmarkPartner *p = cls;
   struct GNUNET_MessageHeader *msg;
 
   if (GNUNET_YES == test_core)
-    partner->cth = NULL;
+    p->cth = NULL;
   else
-    partner->tth = NULL;
+    p->tth = NULL;
+
+  if (NULL == buf)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  if (size < TEST_MESSAGE_SIZE)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n",
-      partner->me->no, partner->dest->no);
+      p->me->no, p->dest->no);
 
-  partner->messages_sent++;
-  partner->bytes_sent += TEST_MESSAGE_SIZE;
-  partner->me->total_messages_sent++;
-  partner->me->total_bytes_sent += TEST_MESSAGE_SIZE;
+  p->messages_sent++;
+  p->bytes_sent += TEST_MESSAGE_SIZE;
+  p->me->total_messages_sent++;
+  p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
 
   msg = (struct GNUNET_MessageHeader *) &msgbuf;
   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
@@ -532,6 +399,24 @@ comm_send_ready (void *cls, size_t size, void *buf)
   return TEST_MESSAGE_SIZE;
 }
 
+static void
+comm_schedule_send (struct BenchmarkPartner *p)
+{
+  if (GNUNET_YES == test_core)
+  {
+    p->cth = GNUNET_CORE_notify_transmit_ready (
+      p->me->ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &p->dest->id,
+      TEST_MESSAGE_SIZE, &comm_send_ready, p);
+  }
+  else
+  {
+    p->tth = GNUNET_TRANSPORT_notify_transmit_ready (
+      p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
+      &comm_send_ready, p);
+  }
+
+}
+
 static void
 print_progress ()
 {
@@ -539,7 +424,7 @@ print_progress ()
   progress_task = GNUNET_SCHEDULER_NO_TASK;
 
   fprintf (stderr, "%llu..",
-      (long long unsigned) BENCHMARK_DURATION.rel_value_us / (1000 * 1000) - calls);
+      (long long unsigned) perf_duration.rel_value_us / (1000 * 1000) - calls);
   calls++;
 
   progress_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
@@ -580,7 +465,7 @@ do_benchmark ()
 
   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
     GNUNET_SCHEDULER_cancel (shutdown_task);
-  shutdown_task = GNUNET_SCHEDULER_add_delayed (BENCHMARK_DURATION,
+  shutdown_task = GNUNET_SCHEDULER_add_delayed (perf_duration,
       &do_shutdown, NULL );
 
   progress_task = GNUNET_SCHEDULER_add_now (&print_progress, NULL );
@@ -589,21 +474,13 @@ do_benchmark ()
   for (c_m = 0; c_m < num_masters; c_m++)
   {
     for (c_s = 0; c_s < num_slaves; c_s++)
-    {
-      if (GNUNET_YES == test_core)
-        mps[c_m].partners[c_s].cth = GNUNET_CORE_notify_transmit_ready (
-          mps[c_m].ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &sps[c_s].id,
-          TEST_MESSAGE_SIZE, &comm_send_ready, &mps[c_m].partners[c_s]);
-      else
-      {
-        mps[c_m].partners[c_s].tth = GNUNET_TRANSPORT_notify_transmit_ready (
-          mps[c_m].th, &sps[c_s].id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
-          &comm_send_ready, &mps[c_m].partners[c_s]);
-      }
-    }
+      comm_schedule_send (&mps[c_m].partners[c_s]);
     if (pref_val != GNUNET_ATS_PREFERENCE_END)
       mps[c_m].ats_task = GNUNET_SCHEDULER_add_now (&ats_pref_task, &mps[c_m]);
   }
+  if (GNUNET_YES == logging)
+    perf_logging_start (log_frequency, testname, mps, num_masters);
+
 }
 
 static void
@@ -807,8 +684,8 @@ comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
   struct BenchmarkPartner *p = NULL;
   for (c_m = 0; c_m < num_masters; c_m++)
   {
-    if (0
-        == memcmp (other, &me->partners[c_m].dest->id,
+    /* Find a partner with other as destination */
+    if (0 == memcmp (other, &me->partners[c_m].dest->id,
             sizeof(struct GNUNET_PeerIdentity)))
     {
       p = &me->partners[c_m];
@@ -880,21 +757,7 @@ comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
   p->me->total_messages_received++;
   p->me->total_bytes_received += TEST_MESSAGE_SIZE;
 
-  if (GNUNET_YES == test_core)
-  {
-    GNUNET_assert (NULL == p->cth);
-    p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0,
-        GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE,
-        &comm_send_ready, p);
-  }
-  else
-  {
-    GNUNET_assert (NULL == p->tth);
-    p->tth = GNUNET_TRANSPORT_notify_transmit_ready (
-      me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
-      &comm_send_ready, p);
-  }
-
+  comm_schedule_send (p);
   return GNUNET_OK;
 }
 
@@ -953,8 +816,6 @@ transport_recv_cb (void *cls,
                    const struct GNUNET_PeerIdentity * peer,
                    const struct GNUNET_MessageHeader * message)
 {
-  struct BenchmarkPeer *me = cls;
-
   if (TEST_MESSAGE_SIZE != ntohs (message->size) ||
       (TEST_MESSAGE_TYPE_PING != ntohs (message->type) &&
       TEST_MESSAGE_TYPE_PONG != ntohs (message->type)))
@@ -1200,6 +1061,7 @@ main_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers,
     mps[c_m].pref_value = TEST_ATS_PREFRENCE_START;
     mps[c_m].partners =
         GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer));
+    mps[c_m].num_partners = num_slaves;
     /* Initialize partners */
     for (c_s = 0; c_s < num_slaves; c_s++)
     {
@@ -1219,6 +1081,7 @@ main_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers,
     sps[c_s].master = GNUNET_NO;
     sps[c_s].partners =
         GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer));
+    sps[c_s].num_partners = num_masters;
     /* Initialize partners */
     for (c_m = 0; c_m < num_masters; c_m++)
     {
@@ -1320,6 +1183,22 @@ main (int argc, char *argv[])
     return -1;
   }
 
+  for (c = 0; c < (argc - 1); c++)
+  {
+    if (0 == strcmp (argv[c], "-d"))
+      break;
+  }
+  if (c < argc - 1)
+  {
+    if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &perf_duration))
+        fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]);
+  }
+  else
+  {
+    perf_duration = BENCHMARK_DURATION;
+  }
+  fprintf (stderr, "Running benchmark for %llu secs\n", (unsigned long long) (perf_duration.rel_value_us) / (1000 * 1000));
+
   for (c = 0; c < (argc - 1); c++)
   {
     if (0 == strcmp (argv[c], "-s"))
@@ -1352,6 +1231,35 @@ main (int argc, char *argv[])
   else
     num_masters = DEFAULT_MASTERS_NUM;
 
+  logging = GNUNET_NO;
+  for (c = 0; c < argc; c++)
+  {
+    if (0 == strcmp (argv[c], "-l"))
+      logging = GNUNET_YES;
+  }
+
+  if (GNUNET_YES == logging)
+  {
+    for (c = 0; c < (argc - 1); c++)
+    {
+      if (0 == strcmp (argv[c], "-f"))
+        break;
+    }
+    if (c < argc - 1)
+    {
+      if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &log_frequency))
+          fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]);
+    }
+    else
+    {
+      log_frequency = LOGGING_FREQUENCY;
+    }
+    fprintf (stderr, "Using log frequency %llu ms\n",
+        (unsigned long long) (log_frequency.rel_value_us) / (1000));
+  }
+
+  GNUNET_asprintf (&testname, "%s_%s_%s",solver, comm_name, pref_str);
+
   if (num_slaves < num_masters)
   {
     fprintf (stderr, "Number of master peers is lower than slaves! exit...\n");
@@ -1376,7 +1284,7 @@ main (int argc, char *argv[])
   event_mask = 0;
   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
-  (void) GNUNET_TESTBED_test_run ("perf_ats", conf_name,
+  (void) GNUNET_TESTBED_test_run ("perf-ats", conf_name,
       num_slaves + num_masters, event_mask, &controller_event_cb, NULL,
       &main_run, NULL );
 
@@ -1384,6 +1292,7 @@ main (int argc, char *argv[])
   GNUNET_free(pref_str);
   GNUNET_free(conf_name);
   GNUNET_free(test_name);
+  GNUNET_free(testname);
   GNUNET_free (comm_name);
   GNUNET_free(mps);
   GNUNET_free(sps);