[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [metrics-lib/master] Parse the new flag-thresholds line in votes.
commit c2a0dbf8bf100a19660ad512b88d93f3d7c18a1e
Author: Karsten Loesing <karsten.loesing@xxxxxxx>
Date: Tue Feb 5 14:49:28 2013 +0100
Parse the new flag-thresholds line in votes.
---
.../descriptor/RelayNetworkStatusVote.java | 41 ++++++++
.../descriptor/impl/NetworkStatusEntryImpl.java | 4 +-
.../torproject/descriptor/impl/ParseHelper.java | 26 ++++--
.../impl/RelayNetworkStatusConsensusImpl.java | 8 +-
.../impl/RelayNetworkStatusVoteImpl.java | 102 +++++++++++++++++++-
.../impl/RelayNetworkStatusVoteImplTest.java | 82 ++++++++++++++++
6 files changed, 246 insertions(+), 17 deletions(-)
diff --git a/src/org/torproject/descriptor/RelayNetworkStatusVote.java b/src/org/torproject/descriptor/RelayNetworkStatusVote.java
index eda0cef..98abb14 100644
--- a/src/org/torproject/descriptor/RelayNetworkStatusVote.java
+++ b/src/org/torproject/descriptor/RelayNetworkStatusVote.java
@@ -44,6 +44,47 @@ public interface RelayNetworkStatusVote extends Descriptor {
/* Return known relay flags. */
public SortedSet<String> getKnownFlags();
+ /* Return the minimum uptime in seconds that this authority requires for
+ * assigning the Stable flag, or -1 if the authority doesn't report this
+ * value. */
+ public long getStableUptime();
+
+ /* Return the minimum MTBF (mean time between failure) that this
+ * authority requires for assigning the Stable flag, or -1 if the
+ * authority doesn't report this value. */
+ public long getStableMtbf();
+
+ /* Return the minimum bandwidth that this authority requires for
+ * assigning the Fast flag, or -1 if the authority doesn't report this
+ * value. */
+ public long getFastBandwidth();
+
+ /* Return the minimum WFU (weighted fractional uptime) in percent that
+ * this authority requires for assigning the Guard flag, or -1.0 if the
+ * authority doesn't report this value. */
+ public double getGuardWfu();
+
+ /* Return the minimum time in seconds that this authority needs to know
+ * about a relay before assigning the Guard flag, or -1 if the authority
+ * doesn't report this information. */
+ public long getGuardTk();
+
+ /* Return the minimum bandwidth that this authority requires for
+ * assigning the Guard flag if exits can be guards, or -1 if the
+ * authority doesn't report this value. */
+ public long getGuardBandwidthIncludingExits();
+
+ /* Return the minimum bandwidth that this authority requires for
+ * assigning the Guard flag if exits can not be guards, or -1 if the
+ * authority doesn't report this value. */
+ public long getGuardBandwidthExcludingExits();
+
+ /* Return 1 if the authority has measured enough MTBF info to use the
+ * MTBF requirement instead of the uptime requirement for assigning the
+ * Stable flag, 0 if not, or -1 if the authority doesn't report this
+ * information. */
+ public int getEnoughMtbfInfo();
+
/* Return consensus parameters. */
public SortedMap<String, Integer> getConsensusParams();
diff --git a/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
index 121f66e..901e17e 100644
--- a/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
+++ b/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
@@ -149,8 +149,8 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
private void parseWLine(String line, String[] parts)
throws DescriptorParseException {
this.parsedAtMostOnceKeyword("w");
- SortedMap<String, Integer> pairs = ParseHelper.parseKeyValuePairs(
- line, parts, 1, "=");
+ SortedMap<String, Integer> pairs =
+ ParseHelper.parseKeyValueIntegerPairs(line, parts, 1, "=");
if (pairs.isEmpty()) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
diff --git a/src/org/torproject/descriptor/impl/ParseHelper.java b/src/org/torproject/descriptor/impl/ParseHelper.java
index 61d1eb0..1b7eff2 100644
--- a/src/org/torproject/descriptor/impl/ParseHelper.java
+++ b/src/org/torproject/descriptor/impl/ParseHelper.java
@@ -6,6 +6,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.TreeMap;
@@ -182,10 +183,10 @@ public class ParseHelper {
return hexString.toUpperCase();
}
- public static SortedMap<String, Integer> parseKeyValuePairs(String line,
- String[] parts, int startIndex, String separatorString)
+ public static SortedMap<String, String> parseKeyValueStringPairs(
+ String line, String[] parts, int startIndex, String separatorString)
throws DescriptorParseException {
- SortedMap<String, Integer> result = new TreeMap<String, Integer>();
+ SortedMap<String, String> result = new TreeMap<String, String>();
for (int i = startIndex; i < parts.length; i++) {
String pair = parts[i];
String[] pairParts = pair.split(separatorString);
@@ -193,11 +194,22 @@ public class ParseHelper {
throw new DescriptorParseException("Illegal key-value pair in "
+ "line '" + line + "'.");
}
- String pairName = pairParts[0];
+ result.put(pairParts[0], pairParts[1]);
+ }
+ return result;
+ }
+
+ public static SortedMap<String, Integer> parseKeyValueIntegerPairs(
+ String line, String[] parts, int startIndex, String separatorString)
+ throws DescriptorParseException {
+ SortedMap<String, Integer> result = new TreeMap<String, Integer>();
+ SortedMap<String, String> keyValueStringPairs =
+ ParseHelper.parseKeyValueStringPairs(line, parts, startIndex,
+ separatorString);
+ for (Map.Entry<String, String> e : keyValueStringPairs.entrySet()) {
try {
- int pairValue = Integer.parseInt(pairParts[1]);
- result.put(pairName, pairValue);
- } catch (NumberFormatException e) {
+ result.put(e.getKey(), Integer.parseInt(e.getValue()));
+ } catch (NumberFormatException ex) {
throw new DescriptorParseException("Illegal value in line '"
+ line + "'.");
}
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
index 35cb316..dad5bc3 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
@@ -257,14 +257,14 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
private void parseParamsLine(String line, String[] parts)
throws DescriptorParseException {
- this.consensusParams = ParseHelper.parseKeyValuePairs(line, parts, 1,
- "=");
+ this.consensusParams = ParseHelper.parseKeyValueIntegerPairs(line,
+ parts, 1, "=");
}
private void parseBandwidthWeightsLine(String line, String[] parts)
throws DescriptorParseException {
- this.bandwidthWeights = ParseHelper.parseKeyValuePairs(line, parts, 1,
- "=");
+ this.bandwidthWeights = ParseHelper.parseKeyValueIntegerPairs(line,
+ parts, 1, "=");
}
private String consensusDigest;
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index 3695074..c5ba980 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.SortedMap;
@@ -48,14 +49,28 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
+ "dir-key-certification,directory-signature").split(",")));
this.checkExactlyOnceKeywords(exactlyOnceKeywords);
Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList((
- "client-versions,server-versions,params,contact,legacy-key,"
- + "dir-key-crosscert,dir-address,directory-footer").split(",")));
+ "client-versions,server-versions,flag-thresholds,params,contact,"
+ + "legacy-key,dir-key-crosscert,dir-address,directory-footer").
+ split(",")));
this.checkAtMostOnceKeywords(atMostOnceKeywords);
this.checkFirstKeyword("network-status-version");
}
protected void parseHeader(byte[] headerBytes)
throws DescriptorParseException {
+ /* Initialize flag-thresholds values here for the case that the vote
+ * doesn't contain those values. Initializing them in the constructor
+ * or when declaring variables wouldn't work, because those parts are
+ * evaluated later and would overwrite everything we parse here. */
+ this.stableUptime = -1L;
+ this.stableMtbf = -1L;
+ this.fastBandwidth = -1L;
+ this.guardWfu = -1.0;
+ this.guardTk = -1L;
+ this.guardBandwidthIncludingExits = -1L;
+ this.guardBandwidthExcludingExits = -1L;
+ this.enoughMtbfInfo = -1;
+
Scanner s = new Scanner(new String(headerBytes)).useDelimiter("\n");
boolean skipCrypto = false; /* TODO Parse crypto parts. */
while (s.hasNext()) {
@@ -84,6 +99,8 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
this.parseServerVersionsLine(line, parts);
} else if (keyword.equals("known-flags")) {
this.parseKnownFlagsLine(line, parts);
+ } else if (keyword.equals("flag-thresholds")) {
+ this.parseFlagThresholdsLine(line, parts);
} else if (keyword.equals("params")) {
this.parseParamsLine(line, parts);
} else if (keyword.equals("dir-source")) {
@@ -247,10 +264,47 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
}
}
+ private void parseFlagThresholdsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length < 2) {
+ throw new DescriptorParseException("No flag thresholds in line '"
+ + line + "'.");
+ }
+ SortedMap<String, String> flagThresholds =
+ ParseHelper.parseKeyValueStringPairs(line, parts, 1, "=");
+ try {
+ for (Map.Entry<String, String> e : flagThresholds.entrySet()) {
+ if (e.getKey().equals("stable-uptime")) {
+ this.stableUptime = Long.parseLong(e.getValue());
+ } else if (e.getKey().equals("stable-mtbf")) {
+ this.stableMtbf = Long.parseLong(e.getValue());
+ } else if (e.getKey().equals("fast-speed")) {
+ this.fastBandwidth = Long.parseLong(e.getValue());
+ } else if (e.getKey().equals("guard-wfu")) {
+ this.guardWfu = Double.parseDouble(e.getValue().
+ replaceAll("%", ""));
+ } else if (e.getKey().equals("guard-tk")) {
+ this.guardTk = Long.parseLong(e.getValue());
+ } else if (e.getKey().equals("guard-bw-inc-exits")) {
+ this.guardBandwidthIncludingExits =
+ Long.parseLong(e.getValue());
+ } else if (e.getKey().equals("guard-bw-exc-exits")) {
+ this.guardBandwidthExcludingExits =
+ Long.parseLong(e.getValue());
+ } else if (e.getKey().equals("enough-mtbf")) {
+ this.enoughMtbfInfo = Integer.parseInt(e.getValue());
+ }
+ }
+ } catch (NumberFormatException ex) {
+ throw new DescriptorParseException("Illegal value in line '"
+ + line + "'.");
+ }
+ }
+
private void parseParamsLine(String line, String[] parts)
throws DescriptorParseException {
- this.consensusParams = ParseHelper.parseKeyValuePairs(line, parts, 1,
- "=");
+ this.consensusParams = ParseHelper.parseKeyValueIntegerPairs(line,
+ parts, 1, "=");
}
private void parseDirSourceLine(String line, String[] parts)
@@ -465,6 +519,46 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
return new TreeSet<String>(this.knownFlags);
}
+ private long stableUptime;
+ public long getStableUptime() {
+ return this.stableUptime;
+ }
+
+ private long stableMtbf;
+ public long getStableMtbf() {
+ return this.stableMtbf;
+ }
+
+ private long fastBandwidth;
+ public long getFastBandwidth() {
+ return this.fastBandwidth;
+ }
+
+ private double guardWfu;
+ public double getGuardWfu() {
+ return this.guardWfu;
+ }
+
+ private long guardTk;
+ public long getGuardTk() {
+ return this.guardTk;
+ }
+
+ private long guardBandwidthIncludingExits;
+ public long getGuardBandwidthIncludingExits() {
+ return this.guardBandwidthIncludingExits;
+ }
+
+ private long guardBandwidthExcludingExits;
+ public long getGuardBandwidthExcludingExits() {
+ return this.guardBandwidthExcludingExits;
+ }
+
+ private int enoughMtbfInfo;
+ public int getEnoughMtbfInfo() {
+ return this.enoughMtbfInfo;
+ }
+
private SortedMap<String, Integer> consensusParams;
public SortedMap<String, Integer> getConsensusParams() {
return this.consensusParams == null ? null:
diff --git a/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java b/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java
index 7fbdb7d..b3fbcfd 100644
--- a/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java
+++ b/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java
@@ -115,6 +115,17 @@ public class RelayNetworkStatusVoteImplTest {
vb.knownFlagsLine = line;
return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
}
+ private String flagThresholdsLine = "flag-thresholds "
+ + "stable-uptime=693369 stable-mtbf=153249 fast-speed=40960 "
+ + "guard-wfu=94.669% guard-tk=691200 guard-bw-inc-exits=174080 "
+ + "guard-bw-exc-exits=184320 enough-mtbf=1";
+ private static RelayNetworkStatusVote
+ createWithFlagThresholdsLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.flagThresholdsLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
+ }
private String paramsLine = "params "
+ "CircuitPriorityHalflifeMsec=30000 bwauthbestratio=1 "
+ "bwauthcircs=1 bwauthdescbw=0 bwauthkp=10000 bwauthpid=1 "
@@ -388,6 +399,9 @@ public class RelayNetworkStatusVoteImplTest {
if (this.knownFlagsLine != null) {
sb.append(this.knownFlagsLine + "\n");
}
+ if (this.flagThresholdsLine != null) {
+ sb.append(this.flagThresholdsLine + "\n");
+ }
if (this.paramsLine != null) {
sb.append(this.paramsLine + "\n");
}
@@ -749,6 +763,74 @@ public class RelayNetworkStatusVoteImplTest {
VoteBuilder.createWithKnownFlagsLine("known-flags ");
}
+ @Test()
+ public void testFlagThresholdsLine() throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ RelayNetworkStatusVote vote =
+ new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
+ assertEquals(693369L, vote.getStableUptime());
+ assertEquals(153249L, vote.getStableMtbf());
+ assertEquals(40960L, vote.getFastBandwidth());
+ assertEquals(94.669, vote.getGuardWfu(), 0.001);
+ assertEquals(691200L, vote.getGuardTk());
+ assertEquals(174080L, vote.getGuardBandwidthIncludingExits());
+ assertEquals(184320L, vote.getGuardBandwidthExcludingExits());
+ assertEquals(1, vote.getEnoughMtbfInfo());
+ }
+
+ @Test()
+ public void testFlagThresholdsNoLine() throws DescriptorParseException {
+ RelayNetworkStatusVote vote =
+ VoteBuilder.createWithFlagThresholdsLine(null);
+ assertEquals(-1L, vote.getStableUptime());
+ assertEquals(-1L, vote.getStableMtbf());
+ assertEquals(-1L, vote.getFastBandwidth());
+ assertEquals(-1.0, vote.getGuardWfu(), 0.001);
+ assertEquals(-1L, vote.getGuardTk());
+ assertEquals(-1L, vote.getGuardBandwidthIncludingExits());
+ assertEquals(-1L, vote.getGuardBandwidthExcludingExits());
+ assertEquals(-1, vote.getEnoughMtbfInfo());
+ }
+
+ @Test()
+ public void testFlagThresholdsAllZeroes()
+ throws DescriptorParseException {
+ RelayNetworkStatusVote vote =
+ VoteBuilder.createWithFlagThresholdsLine("flag-thresholds "
+ + "stable-uptime=0 stable-mtbf=0 fast-speed=0 guard-wfu=0.0% "
+ + "guard-tk=0 guard-bw-inc-exits=0 guard-bw-exc-exits=0 "
+ + "enough-mtbf=0");
+ assertEquals(0L, vote.getStableUptime());
+ assertEquals(0L, vote.getStableMtbf());
+ assertEquals(0L, vote.getFastBandwidth());
+ assertEquals(0.0, vote.getGuardWfu(), 0.001);
+ assertEquals(0L, vote.getGuardTk());
+ assertEquals(0L, vote.getGuardBandwidthIncludingExits());
+ assertEquals(0L, vote.getGuardBandwidthExcludingExits());
+ assertEquals(0, vote.getEnoughMtbfInfo());
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testFlagThresholdsNoSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithFlagThresholdsLine("flag-thresholds");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testFlagThresholdsOneSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithFlagThresholdsLine("flag-thresholds ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testFlagThresholdDuplicate()
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.flagThresholdsLine = vb.flagThresholdsLine + "\n"
+ + vb.flagThresholdsLine;
+ new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
+ }
+
@Test(expected = DescriptorParseException.class)
public void testNicknameMissing() throws DescriptorParseException {
VoteBuilder.createWithDirSourceLine("dir-source "
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits