[tor-commits] [metrics-tasks/master] Move #5755 code to #6443.

karsten at torproject.org karsten at torproject.org
Wed Jul 25 15:38:08 UTC 2012


commit de7426a511e4ad7d612d248d35766a10e97d7fe5
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Wed Jul 25 17:37:34 2012 +0200

    Move #5755 code to #6443.
---
 task-5755/.gitignore                               |   11 -
 .../src/CalculatePathSelectionProbabilities.java   |  293 --------------------
 task-6443/.gitignore                               |    5 +
 task-6443/README                                   |   16 +-
 .../src/CalculatePathSelectionProbabilities.java   |  293 ++++++++++++++++++++
 5 files changed, 311 insertions(+), 307 deletions(-)

diff --git a/task-5755/.gitignore b/task-5755/.gitignore
deleted file mode 100644
index 5d5ac29..0000000
--- a/task-5755/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-.classpath
-.project
-*.pdf
-bin/
-in/
-lib/
-*.csv
-*.png
-*.tar
-*.tar.bz2
-
diff --git a/task-5755/src/CalculatePathSelectionProbabilities.java b/task-5755/src/CalculatePathSelectionProbabilities.java
deleted file mode 100644
index 67bb200..0000000
--- a/task-5755/src/CalculatePathSelectionProbabilities.java
+++ /dev/null
@@ -1,293 +0,0 @@
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import org.torproject.descriptor.Descriptor;
-import org.torproject.descriptor.DescriptorFile;
-import org.torproject.descriptor.DescriptorReader;
-import org.torproject.descriptor.DescriptorSourceFactory;
-import org.torproject.descriptor.NetworkStatusEntry;
-import org.torproject.descriptor.RelayNetworkStatusConsensus;
-import org.torproject.descriptor.ServerDescriptor;
-
-/*
- * Calculate five path-selection probabilities for relays based on
- * consensus weights and advertised bandwidths:
- *
- *  - advertised_bandwidth_fraction: Relative advertised bandwidth of
- *    this relay compared to the total advertised bandwidth in the
- *    network.  If there were no bandwidth authorities, this fraction
- *    would be the probability of this relay to be selected by clients.
- *
- *  - consensus_weight_fraction: Fraction of this relay's consensus weight
- *    compared to the sum of all consensus weights in the network.  This
- *    fraction is a very rough approximation of the probability of this
- *    relay to be selected by clients.
- *
- *  - guard_probability: Probability of this relay to be selected for the
- *    guard position.  This probability is calculated based on consensus
- *    weights, relay flags, directory ports, and bandwidth weights in the
- *    consensus.  Path selection depends on more factors, so that this
- *    probability can only be an approximation.
- *
- *  - middle_probability: Probability of this relay to be selected for the
- *    middle position.  This probability is calculated based on consensus
- *    weights, relay flags, directory ports, and bandwidth weights in the
- *    consensus.  Path selection depends on more factors, so that this
- *    probability can only be an approximation.
- *
- *  - exit_probability: Probability of this relay to be selected for the
- *    exit position.  This probability is calculated based on consensus
- *    weights, relay flags, directory ports, and bandwidth weights in the
- *    consensus.  Path selection depends on more factors, so that this
- *    probability can only be an approximation.
- */
-public class CalculatePathSelectionProbabilities {
-  public static void main(String[] args) throws Exception {
-
-    /* Note: change to true if raw weights shall be written to disk. */
-    boolean writeRawWeights = false;
-
-    /* Read advertised bandwidths of all server descriptors in
-     * in/server-descriptors/ to memory.  This is a rather brute-force
-     * approach, but it's fine for running this analysis. */
-    DescriptorReader descriptorReader =
-        DescriptorSourceFactory.createDescriptorReader();
-    descriptorReader.addDirectory(new File("in/server-descriptors"));
-    Iterator<DescriptorFile> descriptorFiles =
-        descriptorReader.readDescriptors();
-    Map<String, Integer> serverDescriptors =
-        new HashMap<String, Integer>();
-    while (descriptorFiles.hasNext()) {
-      DescriptorFile descriptorFile = descriptorFiles.next();
-      for (Descriptor descriptor : descriptorFile.getDescriptors()) {
-        if (!(descriptor instanceof ServerDescriptor)) {
-          continue;
-        }
-        ServerDescriptor serverDescriptor = (ServerDescriptor) descriptor;
-        String digest = serverDescriptor.getServerDescriptorDigest();
-        int advertisedBandwidth = Math.min(Math.min(
-            serverDescriptor.getBandwidthBurst(),
-            serverDescriptor.getBandwidthObserved()),
-            serverDescriptor.getBandwidthRate());
-        serverDescriptors.put(digest.toUpperCase(), advertisedBandwidth);
-      }
-    }
-
-    /* Go through consensuses in in/consensuses/ in arbitrary order and
-     * calculate the five path-selection probabilities for each of them.
-     * Write results for a given consensuses to a single new line per
-     * relay to out.csv. */
-    descriptorReader = DescriptorSourceFactory.createDescriptorReader();
-    descriptorReader.addDirectory(new File("in/consensuses"));
-    descriptorFiles = descriptorReader.readDescriptors();
-    BufferedWriter bw = null;
-    if (writeRawWeights) {
-      bw = new BufferedWriter(new FileWriter("weights.csv"));
-      bw.write("validafter,fingerprint,advertised_bandwidth_fraction,"
-          + "consensus_weight_fraction,guard_probability,"
-          + "middle_probability,exit_probability\n");
-    }
-    BufferedWriter bw2 = new BufferedWriter(new FileWriter(
-        "cumulated-weights.csv"));
-    bw2.write("validafter,top_relays,total_exit_probability\n");
-    BufferedWriter bw3 = new BufferedWriter(new FileWriter(
-        "inverse-cumulated-weights.csv"));
-    bw3.write("validafter,total_exit_probability,top_relays\n");
-    while (descriptorFiles.hasNext()) {
-      DescriptorFile descriptorFile = descriptorFiles.next();
-      for (Descriptor descriptor : descriptorFile.getDescriptors()) {
-        if (!(descriptor instanceof RelayNetworkStatusConsensus)) {
-          continue;
-        }
-        RelayNetworkStatusConsensus consensus =
-            (RelayNetworkStatusConsensus) descriptor;
-
-        /* Extract valid-after time and bandwidth weights from the parsed
-         * consensus. */
-        SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
-            "yyyy-MM-dd HH:mm:ss");
-        dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-        String validAfter = dateTimeFormat.format(
-            consensus.getValidAfterMillis());
-        SortedMap<String, Integer> bandwidthWeights =
-            consensus.getBandwidthWeights();
-        if (bandwidthWeights == null) {
-          /* Consensus doesn't contain any bandwidth weights. */
-          continue;
-        }
-        SortedSet<String> weightKeys = new TreeSet<String>(Arrays.asList((
-            "Wgg,Wgm,Wgd,Wmg,Wmm,Wme,Wmd,Weg,Wem,Wee,Wed,Wgb,Wmb,Web,Wdb,"
-            + "Wbg,Wbm,Wbe,Wbd").split(",")));
-        weightKeys.removeAll(bandwidthWeights.keySet());
-        if (!weightKeys.isEmpty()) {
-          /* Consensus is missing at least some required bandwidth
-           * weights. */
-          continue;
-        }
-        double wgg = ((double) bandwidthWeights.get("Wgg")) / 10000.0,
-            wgd = ((double) bandwidthWeights.get("Wgd")) / 10000.0,
-            wmg = ((double) bandwidthWeights.get("Wmg")) / 10000.0,
-            wmm = ((double) bandwidthWeights.get("Wmm")) / 10000.0,
-            wme = ((double) bandwidthWeights.get("Wme")) / 10000.0,
-            wmd = ((double) bandwidthWeights.get("Wmd")) / 10000.0,
-            wee = ((double) bandwidthWeights.get("Wee")) / 10000.0,
-            wed = ((double) bandwidthWeights.get("Wed")) / 10000.0;
-
-        /* Go through network statuses and calculate the five weights for
-         * each of them.  Also sum up totals to calculate probabilities
-         * later. */
-        SortedMap<String, Double>
-            advertisedBandwidths = new TreeMap<String, Double>(),
-            consensusWeights = new TreeMap<String, Double>(),
-            guardWeights = new TreeMap<String, Double>(),
-            middleWeights = new TreeMap<String, Double>(),
-            exitWeights = new TreeMap<String, Double>();
-        double totalAdvertisedBandwidth = 0.0;
-        double totalConsensusWeight = 0.0;
-        double totalGuardWeight = 0.0;
-        double totalMiddleWeight = 0.0;
-        double totalExitWeight = 0.0;
-        for (NetworkStatusEntry relay :
-            consensus.getStatusEntries().values()) {
-          String fingerprint = relay.getFingerprint();
-          if (!relay.getFlags().contains("Running")) {
-            continue;
-          }
-          boolean isExit = relay.getFlags().contains("Exit") &&
-              !relay.getFlags().contains("BadExit");
-          boolean isGuard = relay.getFlags().contains("Guard");
-          String serverDescriptorDigest = relay.getDescriptor().
-              toUpperCase();
-          double advertisedBandwidth;
-          if (!serverDescriptors.containsKey(serverDescriptorDigest)) {
-            advertisedBandwidth = 0.0;
-          } else {
-            advertisedBandwidth = (double) serverDescriptors.get(
-                serverDescriptorDigest);
-          }
-          double consensusWeight = (double) relay.getBandwidth();
-          double guardWeight = (double) relay.getBandwidth();
-          double middleWeight = (double) relay.getBandwidth();
-          double exitWeight = (double) relay.getBandwidth();
-
-          /* Case 1: relay has both Guard and Exit flag and could be
-           * selected for either guard, middle, or exit position.  Apply
-           * bandwidth weights W?d. */
-          if (isGuard && isExit) {
-            guardWeight *= wgd;
-            middleWeight *= wmd;
-            exitWeight *= wed;
-
-          /* Case 2: relay only has the Guard flag, not the Exit flag.
-           * While, in theory, the relay could also be picked for the exit
-           * position (if it has a weird exit policy), Weg is hard-coded
-           * to 0 here.  Otherwise, relays with exit policy reject *:*
-           * would show up as possible exits, which makes no sense.  Maybe
-           * this is too much of an oversimplification?  For the other
-           * positions, apply bandwidth weights W?g. */
-          } else if (isGuard) {
-            guardWeight *= wgg;
-            middleWeight *= wmg;
-            exitWeight = 0.0;
-
-          /* Case 3: relay only has the Exit flag, not the Guard flag.  It
-           * cannot be picked for the guard position, so set Wge to 0.
-           * For the other positions, apply bandwidth weights W?e. */
-          } else if (isExit) {
-            guardWeight = 0.0;
-            middleWeight *= wme;
-            exitWeight *= wee;
-
-          /* Case 4: relay has neither Exit nor Guard flag.  Similar to
-           * case 2, this relay *could* have a weird exit policy and be
-           * picked in the exit position.  Same rationale applies, so Wme
-           * is set to 0.  The relay cannot be a guard, so Wgm is 0, too.
-           * For middle position, apply bandwidth weight Wmm. */
-          } else {
-            guardWeight = 0.0;
-            middleWeight *= wmm;
-            exitWeight = 0.0;
-          }
-
-          /* Store calculated weights and update totals. */
-          advertisedBandwidths.put(fingerprint, advertisedBandwidth);
-          consensusWeights.put(fingerprint, consensusWeight);
-          guardWeights.put(fingerprint, guardWeight);
-          middleWeights.put(fingerprint, middleWeight);
-          exitWeights.put(fingerprint, exitWeight);
-          totalAdvertisedBandwidth += advertisedBandwidth;
-          totalConsensusWeight += consensusWeight;
-          totalGuardWeight += guardWeight;
-          totalMiddleWeight += middleWeight;
-          totalExitWeight += exitWeight;
-        }
-
-        /* Write calculated path-selection probabilities to the output
-         * file. */
-        if (bw != null) {
-          for (NetworkStatusEntry relay :
-              consensus.getStatusEntries().values()) {
-            String fingerprint = relay.getFingerprint();
-            bw.write(String.format("%s,%s,%.9f,%.9f,%.9f,%.9f,%.9f%n",
-                validAfter,
-                fingerprint,
-                advertisedBandwidths.get(fingerprint)
-                    / totalAdvertisedBandwidth,
-                consensusWeights.get(fingerprint) / totalConsensusWeight,
-                guardWeights.get(fingerprint) / totalGuardWeight,
-                middleWeights.get(fingerprint) / totalMiddleWeight,
-                exitWeights.get(fingerprint) / totalExitWeight));
-          }
-        }
-
-        /* Write exit probabilities for top-x relays to the second and
-         * third output files. */
-        List<Double> sortedExitWeights = new ArrayList<Double>(
-            exitWeights.values());
-        Collections.sort(sortedExitWeights);
-        Collections.reverse(sortedExitWeights);
-        int topRelays = 0;
-        double totalExitProbability = 0.0;
-        List<Double> inverseProbabilities = new ArrayList<Double>(
-            Arrays.asList(new Double[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6,
-                0.7, 0.8, 0.9 }));
-        for (double exitWeight : sortedExitWeights) {
-          topRelays++;
-          totalExitProbability += exitWeight / totalExitWeight;
-          if (topRelays <= 50) {
-            bw2.write(String.format("%s,%d,%.9f%n", validAfter, topRelays,
-                totalExitProbability));
-          }
-          while (!inverseProbabilities.isEmpty() &&
-              totalExitProbability > inverseProbabilities.get(0)) {
-            bw3.write(String.format("%s,%.1f,%d%n", validAfter,
-                inverseProbabilities.remove(0), topRelays));
-          }
-          if (inverseProbabilities.isEmpty() && topRelays > 50) {
-            break;
-          }
-        }
-      }
-    }
-    if (bw != null) {
-      bw.close();
-    }
-    bw2.close();
-    bw3.close();
-  }
-}
-
diff --git a/task-6443/.gitignore b/task-6443/.gitignore
index 6a3a120..97fd265 100644
--- a/task-6443/.gitignore
+++ b/task-6443/.gitignore
@@ -1,3 +1,8 @@
+.classpath
+.project
+bin/
+in/
+lib/
 *.csv
 *.pdf
 *.png
diff --git a/task-6443/README b/task-6443/README
index 5f10bdf..57ff483 100644
--- a/task-6443/README
+++ b/task-6443/README
@@ -1,7 +1,17 @@
 Graph cdf of probability of selecting among the biggest k exits (#6443)
 
-- Run #5755 code to produce cumulated-weights.csv and
-  inverse-cumulated-weights.csv and copy those files to this directory.
+- Put consensuses and server descriptors into newly created directories
+  in/consensuses/ and in/server-descriptors/.
 
-- Plot CDFs using: R --slave -f cumulated-weights.R
+- Put metrics-lib's descriptor.jar, commons-codec, and commons-compress
+  into lib/ directory.
+
+- Compile Java class:
+  $ javac -d bin -cp lib/descriptor.jar src/CalculatePathSelectionProbabilities.java
+
+- Run Java class:
+  $ java -cp bin:lib/descriptor.jar:lib/commons-codec-1.6.jar:lib/commons-compress-1.4.1.jar CalculatePathSelectionProbabilities
+
+- Plot graphs:
+  $ R --slave -f cumulated-weights.R
 
diff --git a/task-6443/src/CalculatePathSelectionProbabilities.java b/task-6443/src/CalculatePathSelectionProbabilities.java
new file mode 100644
index 0000000..67bb200
--- /dev/null
+++ b/task-6443/src/CalculatePathSelectionProbabilities.java
@@ -0,0 +1,293 @@
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TimeZone;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.torproject.descriptor.Descriptor;
+import org.torproject.descriptor.DescriptorFile;
+import org.torproject.descriptor.DescriptorReader;
+import org.torproject.descriptor.DescriptorSourceFactory;
+import org.torproject.descriptor.NetworkStatusEntry;
+import org.torproject.descriptor.RelayNetworkStatusConsensus;
+import org.torproject.descriptor.ServerDescriptor;
+
+/*
+ * Calculate five path-selection probabilities for relays based on
+ * consensus weights and advertised bandwidths:
+ *
+ *  - advertised_bandwidth_fraction: Relative advertised bandwidth of
+ *    this relay compared to the total advertised bandwidth in the
+ *    network.  If there were no bandwidth authorities, this fraction
+ *    would be the probability of this relay to be selected by clients.
+ *
+ *  - consensus_weight_fraction: Fraction of this relay's consensus weight
+ *    compared to the sum of all consensus weights in the network.  This
+ *    fraction is a very rough approximation of the probability of this
+ *    relay to be selected by clients.
+ *
+ *  - guard_probability: Probability of this relay to be selected for the
+ *    guard position.  This probability is calculated based on consensus
+ *    weights, relay flags, directory ports, and bandwidth weights in the
+ *    consensus.  Path selection depends on more factors, so that this
+ *    probability can only be an approximation.
+ *
+ *  - middle_probability: Probability of this relay to be selected for the
+ *    middle position.  This probability is calculated based on consensus
+ *    weights, relay flags, directory ports, and bandwidth weights in the
+ *    consensus.  Path selection depends on more factors, so that this
+ *    probability can only be an approximation.
+ *
+ *  - exit_probability: Probability of this relay to be selected for the
+ *    exit position.  This probability is calculated based on consensus
+ *    weights, relay flags, directory ports, and bandwidth weights in the
+ *    consensus.  Path selection depends on more factors, so that this
+ *    probability can only be an approximation.
+ */
+public class CalculatePathSelectionProbabilities {
+  public static void main(String[] args) throws Exception {
+
+    /* Note: change to true if raw weights shall be written to disk. */
+    boolean writeRawWeights = false;
+
+    /* Read advertised bandwidths of all server descriptors in
+     * in/server-descriptors/ to memory.  This is a rather brute-force
+     * approach, but it's fine for running this analysis. */
+    DescriptorReader descriptorReader =
+        DescriptorSourceFactory.createDescriptorReader();
+    descriptorReader.addDirectory(new File("in/server-descriptors"));
+    Iterator<DescriptorFile> descriptorFiles =
+        descriptorReader.readDescriptors();
+    Map<String, Integer> serverDescriptors =
+        new HashMap<String, Integer>();
+    while (descriptorFiles.hasNext()) {
+      DescriptorFile descriptorFile = descriptorFiles.next();
+      for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+        if (!(descriptor instanceof ServerDescriptor)) {
+          continue;
+        }
+        ServerDescriptor serverDescriptor = (ServerDescriptor) descriptor;
+        String digest = serverDescriptor.getServerDescriptorDigest();
+        int advertisedBandwidth = Math.min(Math.min(
+            serverDescriptor.getBandwidthBurst(),
+            serverDescriptor.getBandwidthObserved()),
+            serverDescriptor.getBandwidthRate());
+        serverDescriptors.put(digest.toUpperCase(), advertisedBandwidth);
+      }
+    }
+
+    /* Go through consensuses in in/consensuses/ in arbitrary order and
+     * calculate the five path-selection probabilities for each of them.
+     * Write results for a given consensuses to a single new line per
+     * relay to out.csv. */
+    descriptorReader = DescriptorSourceFactory.createDescriptorReader();
+    descriptorReader.addDirectory(new File("in/consensuses"));
+    descriptorFiles = descriptorReader.readDescriptors();
+    BufferedWriter bw = null;
+    if (writeRawWeights) {
+      bw = new BufferedWriter(new FileWriter("weights.csv"));
+      bw.write("validafter,fingerprint,advertised_bandwidth_fraction,"
+          + "consensus_weight_fraction,guard_probability,"
+          + "middle_probability,exit_probability\n");
+    }
+    BufferedWriter bw2 = new BufferedWriter(new FileWriter(
+        "cumulated-weights.csv"));
+    bw2.write("validafter,top_relays,total_exit_probability\n");
+    BufferedWriter bw3 = new BufferedWriter(new FileWriter(
+        "inverse-cumulated-weights.csv"));
+    bw3.write("validafter,total_exit_probability,top_relays\n");
+    while (descriptorFiles.hasNext()) {
+      DescriptorFile descriptorFile = descriptorFiles.next();
+      for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+        if (!(descriptor instanceof RelayNetworkStatusConsensus)) {
+          continue;
+        }
+        RelayNetworkStatusConsensus consensus =
+            (RelayNetworkStatusConsensus) descriptor;
+
+        /* Extract valid-after time and bandwidth weights from the parsed
+         * consensus. */
+        SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
+            "yyyy-MM-dd HH:mm:ss");
+        dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+        String validAfter = dateTimeFormat.format(
+            consensus.getValidAfterMillis());
+        SortedMap<String, Integer> bandwidthWeights =
+            consensus.getBandwidthWeights();
+        if (bandwidthWeights == null) {
+          /* Consensus doesn't contain any bandwidth weights. */
+          continue;
+        }
+        SortedSet<String> weightKeys = new TreeSet<String>(Arrays.asList((
+            "Wgg,Wgm,Wgd,Wmg,Wmm,Wme,Wmd,Weg,Wem,Wee,Wed,Wgb,Wmb,Web,Wdb,"
+            + "Wbg,Wbm,Wbe,Wbd").split(",")));
+        weightKeys.removeAll(bandwidthWeights.keySet());
+        if (!weightKeys.isEmpty()) {
+          /* Consensus is missing at least some required bandwidth
+           * weights. */
+          continue;
+        }
+        double wgg = ((double) bandwidthWeights.get("Wgg")) / 10000.0,
+            wgd = ((double) bandwidthWeights.get("Wgd")) / 10000.0,
+            wmg = ((double) bandwidthWeights.get("Wmg")) / 10000.0,
+            wmm = ((double) bandwidthWeights.get("Wmm")) / 10000.0,
+            wme = ((double) bandwidthWeights.get("Wme")) / 10000.0,
+            wmd = ((double) bandwidthWeights.get("Wmd")) / 10000.0,
+            wee = ((double) bandwidthWeights.get("Wee")) / 10000.0,
+            wed = ((double) bandwidthWeights.get("Wed")) / 10000.0;
+
+        /* Go through network statuses and calculate the five weights for
+         * each of them.  Also sum up totals to calculate probabilities
+         * later. */
+        SortedMap<String, Double>
+            advertisedBandwidths = new TreeMap<String, Double>(),
+            consensusWeights = new TreeMap<String, Double>(),
+            guardWeights = new TreeMap<String, Double>(),
+            middleWeights = new TreeMap<String, Double>(),
+            exitWeights = new TreeMap<String, Double>();
+        double totalAdvertisedBandwidth = 0.0;
+        double totalConsensusWeight = 0.0;
+        double totalGuardWeight = 0.0;
+        double totalMiddleWeight = 0.0;
+        double totalExitWeight = 0.0;
+        for (NetworkStatusEntry relay :
+            consensus.getStatusEntries().values()) {
+          String fingerprint = relay.getFingerprint();
+          if (!relay.getFlags().contains("Running")) {
+            continue;
+          }
+          boolean isExit = relay.getFlags().contains("Exit") &&
+              !relay.getFlags().contains("BadExit");
+          boolean isGuard = relay.getFlags().contains("Guard");
+          String serverDescriptorDigest = relay.getDescriptor().
+              toUpperCase();
+          double advertisedBandwidth;
+          if (!serverDescriptors.containsKey(serverDescriptorDigest)) {
+            advertisedBandwidth = 0.0;
+          } else {
+            advertisedBandwidth = (double) serverDescriptors.get(
+                serverDescriptorDigest);
+          }
+          double consensusWeight = (double) relay.getBandwidth();
+          double guardWeight = (double) relay.getBandwidth();
+          double middleWeight = (double) relay.getBandwidth();
+          double exitWeight = (double) relay.getBandwidth();
+
+          /* Case 1: relay has both Guard and Exit flag and could be
+           * selected for either guard, middle, or exit position.  Apply
+           * bandwidth weights W?d. */
+          if (isGuard && isExit) {
+            guardWeight *= wgd;
+            middleWeight *= wmd;
+            exitWeight *= wed;
+
+          /* Case 2: relay only has the Guard flag, not the Exit flag.
+           * While, in theory, the relay could also be picked for the exit
+           * position (if it has a weird exit policy), Weg is hard-coded
+           * to 0 here.  Otherwise, relays with exit policy reject *:*
+           * would show up as possible exits, which makes no sense.  Maybe
+           * this is too much of an oversimplification?  For the other
+           * positions, apply bandwidth weights W?g. */
+          } else if (isGuard) {
+            guardWeight *= wgg;
+            middleWeight *= wmg;
+            exitWeight = 0.0;
+
+          /* Case 3: relay only has the Exit flag, not the Guard flag.  It
+           * cannot be picked for the guard position, so set Wge to 0.
+           * For the other positions, apply bandwidth weights W?e. */
+          } else if (isExit) {
+            guardWeight = 0.0;
+            middleWeight *= wme;
+            exitWeight *= wee;
+
+          /* Case 4: relay has neither Exit nor Guard flag.  Similar to
+           * case 2, this relay *could* have a weird exit policy and be
+           * picked in the exit position.  Same rationale applies, so Wme
+           * is set to 0.  The relay cannot be a guard, so Wgm is 0, too.
+           * For middle position, apply bandwidth weight Wmm. */
+          } else {
+            guardWeight = 0.0;
+            middleWeight *= wmm;
+            exitWeight = 0.0;
+          }
+
+          /* Store calculated weights and update totals. */
+          advertisedBandwidths.put(fingerprint, advertisedBandwidth);
+          consensusWeights.put(fingerprint, consensusWeight);
+          guardWeights.put(fingerprint, guardWeight);
+          middleWeights.put(fingerprint, middleWeight);
+          exitWeights.put(fingerprint, exitWeight);
+          totalAdvertisedBandwidth += advertisedBandwidth;
+          totalConsensusWeight += consensusWeight;
+          totalGuardWeight += guardWeight;
+          totalMiddleWeight += middleWeight;
+          totalExitWeight += exitWeight;
+        }
+
+        /* Write calculated path-selection probabilities to the output
+         * file. */
+        if (bw != null) {
+          for (NetworkStatusEntry relay :
+              consensus.getStatusEntries().values()) {
+            String fingerprint = relay.getFingerprint();
+            bw.write(String.format("%s,%s,%.9f,%.9f,%.9f,%.9f,%.9f%n",
+                validAfter,
+                fingerprint,
+                advertisedBandwidths.get(fingerprint)
+                    / totalAdvertisedBandwidth,
+                consensusWeights.get(fingerprint) / totalConsensusWeight,
+                guardWeights.get(fingerprint) / totalGuardWeight,
+                middleWeights.get(fingerprint) / totalMiddleWeight,
+                exitWeights.get(fingerprint) / totalExitWeight));
+          }
+        }
+
+        /* Write exit probabilities for top-x relays to the second and
+         * third output files. */
+        List<Double> sortedExitWeights = new ArrayList<Double>(
+            exitWeights.values());
+        Collections.sort(sortedExitWeights);
+        Collections.reverse(sortedExitWeights);
+        int topRelays = 0;
+        double totalExitProbability = 0.0;
+        List<Double> inverseProbabilities = new ArrayList<Double>(
+            Arrays.asList(new Double[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6,
+                0.7, 0.8, 0.9 }));
+        for (double exitWeight : sortedExitWeights) {
+          topRelays++;
+          totalExitProbability += exitWeight / totalExitWeight;
+          if (topRelays <= 50) {
+            bw2.write(String.format("%s,%d,%.9f%n", validAfter, topRelays,
+                totalExitProbability));
+          }
+          while (!inverseProbabilities.isEmpty() &&
+              totalExitProbability > inverseProbabilities.get(0)) {
+            bw3.write(String.format("%s,%.1f,%d%n", validAfter,
+                inverseProbabilities.remove(0), topRelays));
+          }
+          if (inverseProbabilities.isEmpty() && topRelays > 50) {
+            break;
+          }
+        }
+      }
+    }
+    if (bw != null) {
+      bw.close();
+    }
+    bw2.close();
+    bw3.close();
+  }
+}
+



More information about the tor-commits mailing list