add path desirability calculations
authorChristian Grothoff <christian@grothoff.org>
Sun, 29 Jan 2017 22:41:23 +0000 (23:41 +0100)
committerChristian Grothoff <christian@grothoff.org>
Sun, 29 Jan 2017 22:41:23 +0000 (23:41 +0100)
src/cadet/desirability_table.c [new file with mode: 0644]
src/cadet/gnunet-service-cadet-new_paths.c
src/cadet/gnunet-service-cadet-new_peer.c
src/cadet/gnunet-service-cadet-new_peer.h

diff --git a/src/cadet/desirability_table.c b/src/cadet/desirability_table.c
new file mode 100644 (file)
index 0000000..21ec3e3
--- /dev/null
@@ -0,0 +1,35 @@
+/* This file is in the public domain. */
+
+/**
+ * @brief Program to simulate results from #GCP_get_desirability_of_path()
+ * for various plausible inputs.
+ * @author Christian Grothoff
+ */
+#include <stdio.h>
+
+int
+main ()
+{
+  for (unsigned int num_alts=1; num_alts<10; num_alts++)
+    for (unsigned int off=0; off<10; off++)
+      for (double delta=-(int) off;delta<=5;delta += 0.25)
+      {
+        double weight_alts;
+
+        if (delta <= - 1.0)
+          weight_alts = - 1.0 * num_alts / delta; /* discount alternative paths */
+        else if (delta >= 1.0)
+          weight_alts = 1.0 * num_alts * delta; /* overcount alternative paths */
+        else
+          weight_alts = 1.0 * num_alts; /* count alternative paths normally */
+
+        fprintf (stderr,
+                 "Paths: %u  Offset: %u  Delta: %5.2f  SCORE: %f\n",
+                 num_alts,
+                 off,
+                 delta,
+                 ((off + 1.0) / (weight_alts * weight_alts)));
+      }
+
+
+}
index 05d702717f4dc218299d09647423e71bebf38e44..05565c0430313a2fd5ab859a0a143a02427f4642 100644 (file)
@@ -76,8 +76,16 @@ struct CadetPeerPath
 static void
 recalculate_path_desirability (struct CadetPeerPath *path)
 {
-  /* FIXME: update path desirability! */
-  GNUNET_break (0); // not implemented
+  double result = 0.0;
+
+  for (unsigned int i=0;i<path->entries_length;i++)
+  {
+    struct CadetPeer *cp = path->entries[i]->peer;
+
+    result += GCP_get_desirability_of_path (cp,
+                                            i);
+  }
+  path->desirability = (GNUNET_CONTAINER_HeapCostType) result;
 }
 
 
index 9e84550ec4a46241bac54c75206cb718597f8aa4..cc13f6da612a70a7b694c6ef94b71d396801745a 100644 (file)
@@ -207,6 +207,12 @@ struct CadetPeer
    */
   unsigned int num_paths;
 
+  /**
+   * Sum over all of the offsets of all of the paths in the @a path_heads DLLs.
+   * Used to speed-up @GCP_get_desirability_of_path() calculation.
+   */
+  unsigned int off_sum;
+
   /**
    * Number of message queue managers of this peer that have a message in waiting.
    *
@@ -244,6 +250,67 @@ GCP_2s (const struct CadetPeer *cp)
 }
 
 
+/**
+ * Calculate how desirable a path is for @a cp if @a cp
+ * is at offset @a off.
+ *
+ * The 'desirability_table.c' program can be used to compute a list of
+ * sample outputs for different scenarios.  Basically, we score paths
+ * lower if there are many alternatives, and higher if they are
+ * shorter than average, and very high if they are much shorter than
+ * average and without many alternatives.
+ *
+ * @param cp a peer reachable via a path
+ * @param off offset of @a cp in the path
+ * @return score how useful a path is to reach @a cp,
+ *         positive scores mean path is more desirable
+ */
+double
+GCP_get_desirability_of_path (struct CadetPeer *cp,
+                              unsigned int off)
+{
+  unsigned int num_alts = cp->num_paths;
+  unsigned int off_sum;
+  double avg_sum;
+  double path_delta;
+  double weight_alts;
+
+  GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
+  GNUNET_assert (0 != cp->path_dll_length);
+
+  /* We maintain 'off_sum' in 'peer' and thereby
+     avoid the SLOW recalculation each time. Kept here
+     just to document what is going on. */
+#if SLOW
+  off_sum = 0;
+  for (unsigned int j=0;j<cp->path_dll_length;j++)
+    for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
+         NULL != pe;
+         pe = pe->next)
+      off_sum += j;
+  GNUNET_assert (off_sum == cp->off_sum);
+#else
+  off_sum = cp->off_sum;
+#endif
+  avg_sum = off_sum * 1.0 / cp->path_dll_length;
+  path_delta = off - avg_sum;
+  /* path_delta positiv: path off of peer above average (bad path for peer),
+     path_delta negativ: path off of peer below average (good path for peer) */
+  if (path_delta <= - 1.0)
+    weight_alts = - num_alts / path_delta; /* discount alternative paths */
+  else if (path_delta >= 1.0)
+    weight_alts = num_alts * path_delta; /* overcount alternative paths */
+  else
+    weight_alts = num_alts; /* count alternative paths normally */
+
+
+  /* off+1: long paths are generally harder to find and thus count
+     a bit more as they get longer.  However, above-average paths
+     still need to count less, hence the squaring of that factor. */
+  return (off + 1.0) / (weight_alts * weight_alts);
+}
+
+
 /**
  * This peer is no longer be needed, clean it up now.
  *
@@ -757,6 +824,7 @@ GCP_path_entry_add (struct CadetPeer *cp,
   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
                                cp->path_tails[off],
                                entry);
+  cp->off_sum += off;
   cp->num_paths++;
 
   /* If we have a tunnel to this peer, tell the tunnel that there is a
@@ -797,6 +865,7 @@ GCP_path_entry_remove (struct CadetPeer *cp,
                                cp->path_tails[off],
                                entry);
   GNUNET_assert (0 < cp->num_paths);
+  cp->off_sum -= off;
   cp->num_paths--;
   if ( (NULL == cp->core_mq) &&
        (NULL != cp->t) &&
index aaaef15b8bdae102a44b677484d5746eb047c0b5..e1d6fc33a5e3770d81e5a8132c180295c456c7e2 100644 (file)
@@ -59,6 +59,20 @@ GCP_get (const struct GNUNET_PeerIdentity *peer_id,
          int create);
 
 
+/**
+ * Calculate how desirable a path is for @a cp if
+ * @a cp is at offset @a off in the path.
+ *
+ * @param cp a peer reachable via a path
+ * @param off offset of @a cp in a path
+ * @return score how useful a path is to reach @a cp,
+ *         positive scores mean path is more desirable
+ */
+double
+GCP_get_desirability_of_path (struct CadetPeer *cp,
+                              unsigned int off);
+
+
 /**
  * Obtain the peer identity for a `struct CadetPeer`.
  *