commit de7426a511e4ad7d612d248d35766a10e97d7fe5
Author: Karsten Loesing <karsten.loesing(a)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();
+ }
+}
+