tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
April 2014
- 22 participants
- 2020 discussions

14 Apr '14
commit ee43e6bc383dfd0899b31b6cbf651716145b8dbb
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Fri Mar 21 15:44:12 2014 +0100
Turn latitude and longitude into floats.
---
.../torproject/onionoo/DetailsDocumentWriter.java | 8 +++----
src/org/torproject/onionoo/LookupService.java | 21 +++++++++--------
src/org/torproject/onionoo/NodeStatus.java | 12 +++++-----
test/org/torproject/onionoo/LookupServiceTest.java | 24 ++++++++++----------
4 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/src/org/torproject/onionoo/DetailsDocumentWriter.java b/src/org/torproject/onionoo/DetailsDocumentWriter.java
index cea6ba3..309b80d 100644
--- a/src/org/torproject/onionoo/DetailsDocumentWriter.java
+++ b/src/org/torproject/onionoo/DetailsDocumentWriter.java
@@ -127,8 +127,8 @@ public class DetailsDocumentWriter implements DescriptorListener,
String running = entry.getRunning() ? "true" : "false";
int dirPort = entry.getDirPort();
String countryCode = entry.getCountryCode();
- String latitude = entry.getLatitude();
- String longitude = entry.getLongitude();
+ Float latitude = entry.getLatitude();
+ Float longitude = entry.getLongitude();
String countryName = entry.getCountryName();
String regionName = entry.getRegionName();
String cityName = entry.getCityName();
@@ -173,10 +173,10 @@ public class DetailsDocumentWriter implements DescriptorListener,
sb.append(",\n\"country\":\"" + countryCode + "\"");
}
if (latitude != null) {
- sb.append(",\n\"latitude\":" + latitude);
+ sb.append(String.format(",\n\"latitude\":%.4f", latitude));
}
if (longitude != null) {
- sb.append(",\n\"longitude\":" + longitude);
+ sb.append(String.format(",\n\"longitude\":%.4f", longitude));
}
if (countryName != null) {
sb.append(",\n\"country_name\":\""
diff --git a/src/org/torproject/onionoo/LookupService.java b/src/org/torproject/onionoo/LookupService.java
index a950f02..a968bc0 100644
--- a/src/org/torproject/onionoo/LookupService.java
+++ b/src/org/torproject/onionoo/LookupService.java
@@ -51,19 +51,19 @@ class LookupResult {
return this.cityName;
}
- private String latitude;
- public void setLatitude(String latitude) {
+ private Float latitude;
+ public void setLatitude(Float latitude) {
this.latitude = latitude;
}
- public String getLatitude() {
+ public Float getLatitude() {
return this.latitude;
}
- private String longitude;
- public void setLongitude(String longitude) {
+ private Float longitude;
+ public void setLongitude(Float longitude) {
this.longitude = longitude;
}
- public String getLongitude() {
+ public Float getLongitude() {
return this.longitude;
}
@@ -169,8 +169,8 @@ public class LookupService {
/* Obtain a map from IP address numbers to blocks and to latitudes and
longitudes. */
Map<Long, Long> addressNumberBlocks = new HashMap<Long, Long>();
- Map<Long, String[]> addressNumberLatLong =
- new HashMap<Long, String[]>();
+ Map<Long, Float[]> addressNumberLatLong =
+ new HashMap<Long, Float[]>();
try {
SortedSet<Long> sortedAddressNumbers = new TreeSet<Long>(
addressStringNumbers.values());
@@ -220,7 +220,8 @@ public class LookupService {
addressNumberBlocks.put(addressNumber, blockNumber);
if (parts[6].length() > 0 && parts[7].length() > 0) {
addressNumberLatLong.put(addressNumber,
- new String[] { parts[6], parts[7] });
+ new Float[] { Float.parseFloat(parts[6]),
+ Float.parseFloat(parts[7]) });
}
}
} catch (NumberFormatException e) {
@@ -374,7 +375,7 @@ public class LookupService {
}
}
if (addressNumberLatLong.containsKey(addressNumber)) {
- String[] latLong = addressNumberLatLong.get(addressNumber);
+ Float[] latLong = addressNumberLatLong.get(addressNumber);
lookupResult.setLatitude(latLong[0]);
lookupResult.setLongitude(latLong[1]);
}
diff --git a/src/org/torproject/onionoo/NodeStatus.java b/src/org/torproject/onionoo/NodeStatus.java
index 8e89682..6fd33de 100644
--- a/src/org/torproject/onionoo/NodeStatus.java
+++ b/src/org/torproject/onionoo/NodeStatus.java
@@ -80,19 +80,19 @@ public class NodeStatus extends Document {
return new TreeSet<String>(this.exitAddresses);
}
- private String latitude;
- public void setLatitude(String latitude) {
+ private Float latitude;
+ public void setLatitude(Float latitude) {
this.latitude = latitude;
}
- public String getLatitude() {
+ public Float getLatitude() {
return this.latitude;
}
- private String longitude;
- public void setLongitude(String longitude) {
+ private Float longitude;
+ public void setLongitude(Float longitude) {
this.longitude = longitude;
}
- public String getLongitude() {
+ public Float getLongitude() {
return this.longitude;
}
diff --git a/test/org/torproject/onionoo/LookupServiceTest.java b/test/org/torproject/onionoo/LookupServiceTest.java
index e12ab2a..23b5a91 100644
--- a/test/org/torproject/onionoo/LookupServiceTest.java
+++ b/test/org/torproject/onionoo/LookupServiceTest.java
@@ -98,7 +98,7 @@ public class LookupServiceTest {
List<String> geoLite2CityLocationsLines,
List<String> geoipASNum2Lines, String addressString,
String countryCode, String countryName, String regionName,
- String cityName, String latitude, String longitude, String aSNumber,
+ String cityName, Float latitude, Float longitude, String aSNumber,
String aSName) {
this.addressStrings.add(addressString);
this.populateLines();
@@ -151,14 +151,14 @@ public class LookupServiceTest {
this.lookupResults.get(addressString).getLatitude() == null);
} else {
assertEquals(latitude,
- this.lookupResults.get(addressString).getLatitude());
+ this.lookupResults.get(addressString).getLatitude(), 0.01);
}
if (longitude == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
this.lookupResults.get(addressString).getLongitude() == null);
} else {
assertEquals(longitude,
- this.lookupResults.get(addressString).getLongitude());
+ this.lookupResults.get(addressString).getLongitude(), 0.01);
}
if (aSNumber == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
@@ -189,22 +189,22 @@ public class LookupServiceTest {
@Test()
public void testLookup8888() {
this.assertLookupResult(null, null, null, "8.8.8.8", "us",
- "United States", "California", "Mountain View", "37.3860",
- "-122.0838", "AS15169", "Google Inc.");
+ "United States", "California", "Mountain View", 37.3860f,
+ -122.0838f, "AS15169", "Google Inc.");
}
@Test()
public void testLookup8880() {
this.assertLookupResult(null, null, null, "8.8.8.0", "us",
- "United States", "California", "Mountain View", "37.3860",
- "-122.0838", "AS15169", "Google Inc.");
+ "United States", "California", "Mountain View", 37.3860f,
+ -122.0838f, "AS15169", "Google Inc.");
}
@Test()
public void testLookup888255() {
this.assertLookupResult(null, null, null, "8.8.8.255", "us",
- "United States", "California", "Mountain View", "37.3860",
- "-122.0838", "AS15169", "Google Inc.");
+ "United States", "California", "Mountain View", 37.3860f,
+ -122.0838f, "AS15169", "Google Inc.");
}
@Test()
@@ -253,7 +253,7 @@ public class LookupServiceTest {
geoLite2CityLocationsLines.add("6252001,NA,\"North America\",US,"
+ "\"United States\",,,,,");
this.assertLookupResult(null, geoLite2CityLocationsLines, null,
- "8.8.8.8", null, null, null, null, "37.3860", "-122.0838",
+ "8.8.8.8", null, null, null, null, 37.3860f, -122.0838f,
"AS15169", "Google Inc.");
}
@@ -347,8 +347,8 @@ public class LookupServiceTest {
geoipASNum2Lines.add("134744320,134750463,\"AS3356 Level 3 "
+ "Communications\"");
this.assertLookupResult(null, null, geoipASNum2Lines, "8.8.8.8", "us",
- "United States", "California", "Mountain View", "37.3860",
- "-122.0838", null, null);
+ "United States", "California", "Mountain View", 37.3860f,
+ -122.0838f, null, null);
}
@Test()
1
0
commit 46743dc511827a12199a6d8177ff2d5591d7dd61
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Thu Mar 20 18:36:53 2014 +0100
Split up ResponseBuilder class.
Suggested by SonarQube.
---
src/org/torproject/onionoo/RequestHandler.java | 757 +++++++++++++++++++++++
src/org/torproject/onionoo/ResourceServlet.java | 49 +-
src/org/torproject/onionoo/ResponseBuilder.java | 724 +---------------------
3 files changed, 800 insertions(+), 730 deletions(-)
diff --git a/src/org/torproject/onionoo/RequestHandler.java b/src/org/torproject/onionoo/RequestHandler.java
new file mode 100644
index 0000000..6a25549
--- /dev/null
+++ b/src/org/torproject/onionoo/RequestHandler.java
@@ -0,0 +1,757 @@
+/* Copyright 2011--2014 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.onionoo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+
+public class RequestHandler {
+
+ private static long summaryFileLastModified = -1L;
+ private static DocumentStore documentStore;
+ private static Time time;
+ private static boolean successfullyReadSummaryFile = false;
+ private static String relaysPublishedString, bridgesPublishedString;
+ private static List<String> relaysByConsensusWeight = null;
+ private static Map<String, String> relayFingerprintSummaryLines = null,
+ bridgeFingerprintSummaryLines = null;
+ private static Map<String, Set<String>> relaysByCountryCode = null,
+ relaysByASNumber = null, relaysByFlag = null, bridgesByFlag = null,
+ relaysByContact = null;
+ private static SortedMap<Integer, Set<String>>
+ relaysByFirstSeenDays = null, bridgesByFirstSeenDays = null,
+ relaysByLastSeenDays = null, bridgesByLastSeenDays = null;
+ private static final long SUMMARY_MAX_AGE = DateTimeHelper.SIX_HOURS;
+
+ public static void initialize(DocumentStore documentStoreParam,
+ Time timeParam) {
+ documentStore = documentStoreParam;
+ time = timeParam;
+ readSummaryFile();
+ }
+
+ public static boolean update() {
+ readSummaryFile();
+ return successfullyReadSummaryFile;
+ }
+
+ private static void readSummaryFile() {
+ long newSummaryFileLastModified = -1L;
+ UpdateStatus updateStatus = documentStore.retrieve(UpdateStatus.class,
+ false);
+ if (updateStatus != null &&
+ updateStatus.getDocumentString() != null) {
+ String updateString = updateStatus.getDocumentString();
+ try {
+ newSummaryFileLastModified = Long.parseLong(updateString.trim());
+ } catch (NumberFormatException e) {
+ /* Handle below. */
+ }
+ }
+ if (newSummaryFileLastModified < 0L) {
+ // TODO Does this actually solve anything? Should we instead
+ // switch to a variant of the maintenance mode and re-check when
+ // the next requests comes in that happens x seconds after this one?
+ successfullyReadSummaryFile = false;
+ return;
+ }
+ if (newSummaryFileLastModified + SUMMARY_MAX_AGE
+ < time.currentTimeMillis()) {
+ // TODO Does this actually solve anything? Should we instead
+ // switch to a variant of the maintenance mode and re-check when
+ // the next requests comes in that happens x seconds after this one?
+ successfullyReadSummaryFile = false;
+ return;
+ }
+ if (newSummaryFileLastModified > summaryFileLastModified) {
+ List<String> newRelaysByConsensusWeight = new ArrayList<String>();
+ Map<String, String>
+ newRelayFingerprintSummaryLines = new HashMap<String, String>(),
+ newBridgeFingerprintSummaryLines =
+ new HashMap<String, String>();
+ Map<String, Set<String>>
+ newRelaysByCountryCode = new HashMap<String, Set<String>>(),
+ newRelaysByASNumber = new HashMap<String, Set<String>>(),
+ newRelaysByFlag = new HashMap<String, Set<String>>(),
+ newBridgesByFlag = new HashMap<String, Set<String>>(),
+ newRelaysByContact = new HashMap<String, Set<String>>();
+ SortedMap<Integer, Set<String>>
+ newRelaysByFirstSeenDays = new TreeMap<Integer, Set<String>>(),
+ newBridgesByFirstSeenDays = new TreeMap<Integer, Set<String>>(),
+ newRelaysByLastSeenDays = new TreeMap<Integer, Set<String>>(),
+ newBridgesByLastSeenDays = new TreeMap<Integer, Set<String>>();
+ long relaysLastValidAfterMillis = -1L,
+ bridgesLastPublishedMillis = -1L;
+ String newRelaysPublishedString, newBridgesPublishedString;
+ Set<NodeStatus> currentRelays = new HashSet<NodeStatus>(),
+ currentBridges = new HashSet<NodeStatus>();
+ SortedSet<String> fingerprints = documentStore.list(
+ NodeStatus.class, false);
+ // TODO We should be able to learn if something goes wrong when
+ // reading the summary file, rather than silently having an empty
+ // list of fingerprints.
+ for (String fingerprint : fingerprints) {
+ NodeStatus node = documentStore.retrieve(NodeStatus.class, true,
+ fingerprint);
+ if (node.isRelay()) {
+ relaysLastValidAfterMillis = Math.max(
+ relaysLastValidAfterMillis, node.getLastSeenMillis());
+ currentRelays.add(node);
+ } else {
+ bridgesLastPublishedMillis = Math.max(
+ bridgesLastPublishedMillis, node.getLastSeenMillis());
+ currentBridges.add(node);
+ }
+ }
+ newRelaysPublishedString = DateTimeHelper.format(
+ relaysLastValidAfterMillis);
+ newBridgesPublishedString = DateTimeHelper.format(
+ bridgesLastPublishedMillis);
+ List<String> orderRelaysByConsensusWeight = new ArrayList<String>();
+ for (NodeStatus entry : currentRelays) {
+ String fingerprint = entry.getFingerprint().toUpperCase();
+ String hashedFingerprint = entry.getHashedFingerprint().
+ toUpperCase();
+ entry.setRunning(entry.getLastSeenMillis() ==
+ relaysLastValidAfterMillis);
+ String line = formatRelaySummaryLine(entry);
+ newRelayFingerprintSummaryLines.put(fingerprint, line);
+ newRelayFingerprintSummaryLines.put(hashedFingerprint, line);
+ long consensusWeight = entry.getConsensusWeight();
+ orderRelaysByConsensusWeight.add(String.format("%020d %s",
+ consensusWeight, fingerprint));
+ orderRelaysByConsensusWeight.add(String.format("%020d %s",
+ consensusWeight, hashedFingerprint));
+ if (entry.getCountryCode() != null) {
+ String countryCode = entry.getCountryCode();
+ if (!newRelaysByCountryCode.containsKey(countryCode)) {
+ newRelaysByCountryCode.put(countryCode,
+ new HashSet<String>());
+ }
+ newRelaysByCountryCode.get(countryCode).add(fingerprint);
+ newRelaysByCountryCode.get(countryCode).add(hashedFingerprint);
+ }
+ if (entry.getASNumber() != null) {
+ String aSNumber = entry.getASNumber();
+ if (!newRelaysByASNumber.containsKey(aSNumber)) {
+ newRelaysByASNumber.put(aSNumber, new HashSet<String>());
+ }
+ newRelaysByASNumber.get(aSNumber).add(fingerprint);
+ newRelaysByASNumber.get(aSNumber).add(hashedFingerprint);
+ }
+ for (String flag : entry.getRelayFlags()) {
+ String flagLowerCase = flag.toLowerCase();
+ if (!newRelaysByFlag.containsKey(flagLowerCase)) {
+ newRelaysByFlag.put(flagLowerCase, new HashSet<String>());
+ }
+ newRelaysByFlag.get(flagLowerCase).add(fingerprint);
+ newRelaysByFlag.get(flagLowerCase).add(hashedFingerprint);
+ }
+ int daysSinceFirstSeen = (int) ((newSummaryFileLastModified
+ - entry.getFirstSeenMillis()) / 86400000L);
+ if (!newRelaysByFirstSeenDays.containsKey(daysSinceFirstSeen)) {
+ newRelaysByFirstSeenDays.put(daysSinceFirstSeen,
+ new HashSet<String>());
+ }
+ newRelaysByFirstSeenDays.get(daysSinceFirstSeen).add(fingerprint);
+ newRelaysByFirstSeenDays.get(daysSinceFirstSeen).add(
+ hashedFingerprint);
+ int daysSinceLastSeen = (int) ((newSummaryFileLastModified
+ - entry.getLastSeenMillis()) / 86400000L);
+ if (!newRelaysByLastSeenDays.containsKey(daysSinceLastSeen)) {
+ newRelaysByLastSeenDays.put(daysSinceLastSeen,
+ new HashSet<String>());
+ }
+ newRelaysByLastSeenDays.get(daysSinceLastSeen).add(fingerprint);
+ newRelaysByLastSeenDays.get(daysSinceLastSeen).add(
+ hashedFingerprint);
+ String contact = entry.getContact();
+ if (!newRelaysByContact.containsKey(contact)) {
+ newRelaysByContact.put(contact, new HashSet<String>());
+ }
+ newRelaysByContact.get(contact).add(fingerprint);
+ newRelaysByContact.get(contact).add(hashedFingerprint);
+ }
+ Collections.sort(orderRelaysByConsensusWeight);
+ newRelaysByConsensusWeight = new ArrayList<String>();
+ for (String relay : orderRelaysByConsensusWeight) {
+ newRelaysByConsensusWeight.add(relay.split(" ")[1]);
+ }
+ for (NodeStatus entry : currentBridges) {
+ String hashedFingerprint = entry.getFingerprint().toUpperCase();
+ String hashedHashedFingerprint = entry.getHashedFingerprint().
+ toUpperCase();
+ entry.setRunning(entry.getRelayFlags().contains("Running") &&
+ entry.getLastSeenMillis() == bridgesLastPublishedMillis);
+ String line = formatBridgeSummaryLine(entry);
+ newBridgeFingerprintSummaryLines.put(hashedFingerprint, line);
+ newBridgeFingerprintSummaryLines.put(hashedHashedFingerprint,
+ line);
+ for (String flag : entry.getRelayFlags()) {
+ String flagLowerCase = flag.toLowerCase();
+ if (!newBridgesByFlag.containsKey(flagLowerCase)) {
+ newBridgesByFlag.put(flagLowerCase, new HashSet<String>());
+ }
+ newBridgesByFlag.get(flagLowerCase).add(hashedFingerprint);
+ newBridgesByFlag.get(flagLowerCase).add(
+ hashedHashedFingerprint);
+ }
+ int daysSinceFirstSeen = (int) ((newSummaryFileLastModified
+ - entry.getFirstSeenMillis()) / 86400000L);
+ if (!newBridgesByFirstSeenDays.containsKey(daysSinceFirstSeen)) {
+ newBridgesByFirstSeenDays.put(daysSinceFirstSeen,
+ new HashSet<String>());
+ }
+ newBridgesByFirstSeenDays.get(daysSinceFirstSeen).add(
+ hashedFingerprint);
+ newBridgesByFirstSeenDays.get(daysSinceFirstSeen).add(
+ hashedHashedFingerprint);
+ int daysSinceLastSeen = (int) ((newSummaryFileLastModified
+ - entry.getLastSeenMillis()) / 86400000L);
+ if (!newBridgesByLastSeenDays.containsKey(daysSinceLastSeen)) {
+ newBridgesByLastSeenDays.put(daysSinceLastSeen,
+ new HashSet<String>());
+ }
+ newBridgesByLastSeenDays.get(daysSinceLastSeen).add(
+ hashedFingerprint);
+ newBridgesByLastSeenDays.get(daysSinceLastSeen).add(
+ hashedHashedFingerprint);
+ }
+ relaysByConsensusWeight = newRelaysByConsensusWeight;
+ relayFingerprintSummaryLines = newRelayFingerprintSummaryLines;
+ bridgeFingerprintSummaryLines = newBridgeFingerprintSummaryLines;
+ relaysByCountryCode = newRelaysByCountryCode;
+ relaysByASNumber = newRelaysByASNumber;
+ relaysByFlag = newRelaysByFlag;
+ bridgesByFlag = newBridgesByFlag;
+ relaysByContact = newRelaysByContact;
+ relaysByFirstSeenDays = newRelaysByFirstSeenDays;
+ relaysByLastSeenDays = newRelaysByLastSeenDays;
+ bridgesByFirstSeenDays = newBridgesByFirstSeenDays;
+ bridgesByLastSeenDays = newBridgesByLastSeenDays;
+ relaysPublishedString = newRelaysPublishedString;
+ bridgesPublishedString = newBridgesPublishedString;
+ }
+ summaryFileLastModified = newSummaryFileLastModified;
+ successfullyReadSummaryFile = true;
+ }
+
+ private static String formatRelaySummaryLine(NodeStatus entry) {
+ String nickname = !entry.getNickname().equals("Unnamed") ?
+ entry.getNickname() : null;
+ String fingerprint = entry.getFingerprint();
+ String running = entry.getRunning() ? "true" : "false";
+ List<String> addresses = new ArrayList<String>();
+ addresses.add(entry.getAddress());
+ for (String orAddress : entry.getOrAddresses()) {
+ addresses.add(orAddress);
+ }
+ for (String exitAddress : entry.getExitAddresses()) {
+ if (!addresses.contains(exitAddress)) {
+ addresses.add(exitAddress);
+ }
+ }
+ StringBuilder addressesBuilder = new StringBuilder();
+ int written = 0;
+ for (String address : addresses) {
+ addressesBuilder.append((written++ > 0 ? "," : "") + "\""
+ + address.toLowerCase() + "\"");
+ }
+ return String.format("{%s\"f\":\"%s\",\"a\":[%s],\"r\":%s}",
+ (nickname == null ? "" : "\"n\":\"" + nickname + "\","),
+ fingerprint, addressesBuilder.toString(), running);
+ }
+
+ private static String formatBridgeSummaryLine(NodeStatus entry) {
+ String nickname = !entry.getNickname().equals("Unnamed") ?
+ entry.getNickname() : null;
+ String hashedFingerprint = entry.getFingerprint();
+ String running = entry.getRunning() ? "true" : "false";
+ return String.format("{%s\"h\":\"%s\",\"r\":%s}",
+ (nickname == null ? "" : "\"n\":\"" + nickname + "\","),
+ hashedFingerprint, running);
+ }
+
+ public static long getLastModified() {
+ readSummaryFile();
+ return summaryFileLastModified;
+ }
+
+ private String resourceType;
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ private String type;
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ private String running;
+ public void setRunning(String running) {
+ this.running = running;
+ }
+
+ private String[] search;
+ public void setSearch(String[] search) {
+ this.search = new String[search.length];
+ System.arraycopy(search, 0, this.search, 0, search.length);
+ }
+
+ private String lookup;
+ public void setLookup(String lookup) {
+ this.lookup = lookup;
+ }
+
+ private String country;
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ private String as;
+ public void setAs(String as) {
+ this.as = as;
+ }
+
+ private String flag;
+ public void setFlag(String flag) {
+ this.flag = flag;
+ }
+
+ private String[] contact;
+ public void setContact(String[] contact) {
+ this.contact = new String[contact.length];
+ System.arraycopy(contact, 0, this.contact, 0, contact.length);
+ }
+
+ private String[] order;
+ public void setOrder(String[] order) {
+ this.order = new String[order.length];
+ System.arraycopy(order, 0, this.order, 0, order.length);
+ }
+
+ private String offset;
+ public void setOffset(String offset) {
+ this.offset = offset;
+ }
+
+ private String limit;
+ public void setLimit(String limit) {
+ this.limit = limit;
+ }
+
+ private int[] firstSeenDays;
+ public void setFirstSeenDays(int[] firstSeenDays) {
+ this.firstSeenDays = new int[firstSeenDays.length];
+ System.arraycopy(firstSeenDays, 0, this.firstSeenDays, 0,
+ firstSeenDays.length);
+ }
+
+ private int[] lastSeenDays;
+ public void setLastSeenDays(int[] lastSeenDays) {
+ this.lastSeenDays = new int[lastSeenDays.length];
+ System.arraycopy(lastSeenDays, 0, this.lastSeenDays, 0,
+ lastSeenDays.length);
+ }
+
+ private Map<String, String> filteredRelays =
+ new HashMap<String, String>();
+
+ private Map<String, String> filteredBridges =
+ new HashMap<String, String>();
+
+ public void handleRequest() {
+ this.filteredRelays.putAll(relayFingerprintSummaryLines);
+ this.filteredBridges.putAll(bridgeFingerprintSummaryLines);
+ this.filterByResourceType();
+ this.filterByType();
+ this.filterByRunning();
+ this.filterBySearchTerms();
+ this.filterByFingerprint();
+ this.filterByCountryCode();
+ this.filterByASNumber();
+ this.filterByFlag();
+ this.filterNodesByFirstSeenDays();
+ this.filterNodesByLastSeenDays();
+ this.filterByContact();
+ this.order();
+ this.offset();
+ this.limit();
+ }
+
+
+ private void filterByResourceType() {
+ if (this.resourceType.equals("clients")) {
+ this.filteredRelays.clear();
+ }
+ if (this.resourceType.equals("weights")) {
+ this.filteredBridges.clear();
+ }
+ }
+
+ private void filterByType() {
+ if (this.type == null) {
+ return;
+ } else if (this.type.equals("relay")) {
+ this.filteredBridges.clear();
+ } else {
+ this.filteredRelays.clear();
+ }
+ }
+
+ private void filterByRunning() {
+ if (this.running == null) {
+ return;
+ }
+ boolean runningRequested = this.running.equals("true");
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
+ if (e.getValue().contains("\"r\":true") != runningRequested) {
+ removeRelays.add(e.getKey());
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ Set<String> removeBridges = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
+ if (e.getValue().contains("\"r\":true") != runningRequested) {
+ removeBridges.add(e.getKey());
+ }
+ }
+ for (String fingerprint : removeBridges) {
+ this.filteredBridges.remove(fingerprint);
+ }
+ }
+
+ private void filterBySearchTerms() {
+ if (this.search == null) {
+ return;
+ }
+ for (String searchTerm : this.search) {
+ filterBySearchTerm(searchTerm);
+ }
+ }
+
+ private void filterBySearchTerm(String searchTerm) {
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
+ String fingerprint = e.getKey();
+ String line = e.getValue();
+ boolean lineMatches = false;
+ String nickname = "unnamed";
+ if (line.contains("\"n\":\"")) {
+ nickname = line.substring(line.indexOf("\"n\":\"") + 5).
+ split("\"")[0].toLowerCase();
+ }
+ if (searchTerm.startsWith("$")) {
+ /* Search is for $-prefixed fingerprint. */
+ if (fingerprint.startsWith(
+ searchTerm.substring(1).toUpperCase())) {
+ /* $-prefixed fingerprint matches. */
+ lineMatches = true;
+ }
+ } else if (nickname.contains(searchTerm.toLowerCase())) {
+ /* Nickname matches. */
+ lineMatches = true;
+ } else if (fingerprint.startsWith(searchTerm.toUpperCase())) {
+ /* Non-$-prefixed fingerprint matches. */
+ lineMatches = true;
+ } else if (line.substring(line.indexOf("\"a\":[")).contains("\""
+ + searchTerm.toLowerCase())) {
+ /* Address matches. */
+ lineMatches = true;
+ }
+ if (!lineMatches) {
+ removeRelays.add(e.getKey());
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ Set<String> removeBridges = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
+ String hashedFingerprint = e.getKey();
+ String line = e.getValue();
+ boolean lineMatches = false;
+ String nickname = "unnamed";
+ if (line.contains("\"n\":\"")) {
+ nickname = line.substring(line.indexOf("\"n\":\"") + 5).
+ split("\"")[0].toLowerCase();
+ }
+ if (searchTerm.startsWith("$")) {
+ /* Search is for $-prefixed hashed fingerprint. */
+ if (hashedFingerprint.startsWith(
+ searchTerm.substring(1).toUpperCase())) {
+ /* $-prefixed hashed fingerprint matches. */
+ lineMatches = true;
+ }
+ } else if (nickname.contains(searchTerm.toLowerCase())) {
+ /* Nickname matches. */
+ lineMatches = true;
+ } else if (hashedFingerprint.startsWith(searchTerm.toUpperCase())) {
+ /* Non-$-prefixed hashed fingerprint matches. */
+ lineMatches = true;
+ }
+ if (!lineMatches) {
+ removeBridges.add(e.getKey());
+ }
+ }
+ for (String fingerprint : removeBridges) {
+ this.filteredBridges.remove(fingerprint);
+ }
+ }
+
+ private void filterByFingerprint() {
+ if (this.lookup == null) {
+ return;
+ }
+ String fingerprint = this.lookup;
+ String relayLine = this.filteredRelays.get(fingerprint);
+ this.filteredRelays.clear();
+ if (relayLine != null) {
+ this.filteredRelays.put(fingerprint, relayLine);
+ }
+ String bridgeLine = this.filteredBridges.get(fingerprint);
+ this.filteredBridges.clear();
+ if (bridgeLine != null) {
+ this.filteredBridges.put(fingerprint, bridgeLine);
+ }
+ }
+
+ private void filterByCountryCode() {
+ if (this.country == null) {
+ return;
+ }
+ String countryCode = this.country.toLowerCase();
+ if (!relaysByCountryCode.containsKey(countryCode)) {
+ this.filteredRelays.clear();
+ } else {
+ Set<String> relaysWithCountryCode =
+ relaysByCountryCode.get(countryCode);
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : this.filteredRelays.entrySet()) {
+ String fingerprint = e.getKey();
+ if (!relaysWithCountryCode.contains(fingerprint)) {
+ removeRelays.add(fingerprint);
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ }
+ this.filteredBridges.clear();
+ }
+
+ private void filterByASNumber() {
+ if (this.as == null) {
+ return;
+ }
+ String aSNumber = this.as.toUpperCase();
+ if (!aSNumber.startsWith("AS")) {
+ aSNumber = "AS" + aSNumber;
+ }
+ if (!relaysByASNumber.containsKey(aSNumber)) {
+ this.filteredRelays.clear();
+ } else {
+ Set<String> relaysWithASNumber =
+ relaysByASNumber.get(aSNumber);
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : this.filteredRelays.entrySet()) {
+ String fingerprint = e.getKey();
+ if (!relaysWithASNumber.contains(fingerprint)) {
+ removeRelays.add(fingerprint);
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ }
+ this.filteredBridges.clear();
+ }
+
+ private void filterByFlag() {
+ if (this.flag == null) {
+ return;
+ }
+ String flag = this.flag.toLowerCase();
+ if (!relaysByFlag.containsKey(flag)) {
+ this.filteredRelays.clear();
+ } else {
+ Set<String> relaysWithFlag = relaysByFlag.get(flag);
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : this.filteredRelays.entrySet()) {
+ String fingerprint = e.getKey();
+ if (!relaysWithFlag.contains(fingerprint)) {
+ removeRelays.add(fingerprint);
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ }
+ if (!bridgesByFlag.containsKey(flag)) {
+ this.filteredBridges.clear();
+ } else {
+ Set<String> bridgesWithFlag = bridgesByFlag.get(flag);
+ Set<String> removeBridges = new HashSet<String>();
+ for (Map.Entry<String, String> e :
+ this.filteredBridges.entrySet()) {
+ String fingerprint = e.getKey();
+ if (!bridgesWithFlag.contains(fingerprint)) {
+ removeBridges.add(fingerprint);
+ }
+ }
+ for (String fingerprint : removeBridges) {
+ this.filteredBridges.remove(fingerprint);
+ }
+ }
+ }
+
+ private void filterNodesByFirstSeenDays() {
+ if (this.firstSeenDays == null) {
+ return;
+ }
+ filterNodesByDays(this.filteredRelays, relaysByFirstSeenDays,
+ this.firstSeenDays);
+ filterNodesByDays(this.filteredBridges, bridgesByFirstSeenDays,
+ this.firstSeenDays);
+ }
+
+ private void filterNodesByLastSeenDays() {
+ if (this.lastSeenDays == null) {
+ return;
+ }
+ filterNodesByDays(this.filteredRelays, relaysByLastSeenDays,
+ this.lastSeenDays);
+ filterNodesByDays(this.filteredBridges, bridgesByLastSeenDays,
+ this.lastSeenDays);
+ }
+
+ private void filterNodesByDays(Map<String, String> filteredNodes,
+ SortedMap<Integer, Set<String>> nodesByDays, int[] days) {
+ Set<String> removeNodes = new HashSet<String>();
+ for (Set<String> nodes : nodesByDays.headMap(days[0]).values()) {
+ removeNodes.addAll(nodes);
+ }
+ if (days[1] < Integer.MAX_VALUE) {
+ for (Set<String> nodes :
+ nodesByDays.tailMap(days[1] + 1).values()) {
+ removeNodes.addAll(nodes);
+ }
+ }
+ for (String fingerprint : removeNodes) {
+ filteredNodes.remove(fingerprint);
+ }
+ }
+
+ private void filterByContact() {
+ if (this.contact == null) {
+ return;
+ }
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, Set<String>> e : relaysByContact.entrySet()) {
+ String contact = e.getKey();
+ for (String contactPart : this.contact) {
+ if (contact == null ||
+ !contact.contains(contactPart.toLowerCase())) {
+ removeRelays.addAll(e.getValue());
+ break;
+ }
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ this.filteredBridges.clear();
+ }
+
+ private void order() {
+ if (this.order != null && this.order.length == 1) {
+ List<String> orderBy = new ArrayList<String>(
+ relaysByConsensusWeight);
+ if (this.order[0].startsWith("-")) {
+ Collections.reverse(orderBy);
+ }
+ for (String relay : orderBy) {
+ if (this.filteredRelays.containsKey(relay) &&
+ !this.orderedRelays.contains(filteredRelays.get(relay))) {
+ this.orderedRelays.add(this.filteredRelays.remove(relay));
+ }
+ }
+ for (String relay : this.filteredRelays.keySet()) {
+ if (!this.orderedRelays.contains(this.filteredRelays.get(relay))) {
+ this.orderedRelays.add(this.filteredRelays.remove(relay));
+ }
+ }
+ Set<String> uniqueBridges = new HashSet<String>(
+ this.filteredBridges.values());
+ this.orderedBridges.addAll(uniqueBridges);
+ } else {
+ Set<String> uniqueRelays = new HashSet<String>(
+ this.filteredRelays.values());
+ this.orderedRelays.addAll(uniqueRelays);
+ Set<String> uniqueBridges = new HashSet<String>(
+ this.filteredBridges.values());
+ this.orderedBridges.addAll(uniqueBridges);
+ }
+ }
+
+ private void offset() {
+ if (this.offset == null) {
+ return;
+ }
+ int offsetValue = Integer.parseInt(this.offset);
+ while (offsetValue-- > 0 &&
+ (!this.orderedRelays.isEmpty() ||
+ !this.orderedBridges.isEmpty())) {
+ if (!this.orderedRelays.isEmpty()) {
+ this.orderedRelays.remove(0);
+ } else {
+ this.orderedBridges.remove(0);
+ }
+ }
+ }
+
+ private void limit() {
+ if (this.limit == null) {
+ return;
+ }
+ int limitValue = Integer.parseInt(this.limit);
+ while (!this.orderedRelays.isEmpty() &&
+ limitValue < this.orderedRelays.size()) {
+ this.orderedRelays.remove(this.orderedRelays.size() - 1);
+ }
+ limitValue -= this.orderedRelays.size();
+ while (!this.orderedBridges.isEmpty() &&
+ limitValue < this.orderedBridges.size()) {
+ this.orderedBridges.remove(this.orderedBridges.size() - 1);
+ }
+ }
+
+ private List<String> orderedRelays = new ArrayList<String>();
+ public List<String> getOrderedRelays() {
+ return this.orderedRelays;
+ }
+
+ private List<String> orderedBridges = new ArrayList<String>();
+ public List<String> getOrderedBridges() {
+ return this.orderedBridges;
+ }
+
+ public String getRelaysPublishedString() {
+ return relaysPublishedString;
+ }
+
+ public String getBridgesPublishedString() {
+ return bridgesPublishedString;
+ }
+}
diff --git a/src/org/torproject/onionoo/ResourceServlet.java b/src/org/torproject/onionoo/ResourceServlet.java
index 27ff414..0c01d9f 100644
--- a/src/org/torproject/onionoo/ResourceServlet.java
+++ b/src/org/torproject/onionoo/ResourceServlet.java
@@ -42,7 +42,8 @@ public class ResourceServlet extends HttpServlet {
DocumentStore documentStore, Time time) {
this.maintenanceMode = maintenanceMode;
if (!maintenanceMode) {
- ResponseBuilder.initialize(documentStore, time);
+ RequestHandler.initialize(documentStore, time);
+ ResponseBuilder.initialize(documentStore);
}
}
@@ -50,7 +51,7 @@ public class ResourceServlet extends HttpServlet {
if (this.maintenanceMode) {
return super.getLastModified(request);
} else {
- return ResponseBuilder.getLastModified();
+ return RequestHandler.getLastModified();
}
}
@@ -109,12 +110,11 @@ public class ResourceServlet extends HttpServlet {
return;
}
- if (!ResponseBuilder.update()) {
+ if (!RequestHandler.update()) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
- ResponseBuilder rb = new ResponseBuilder();
String uri = request.getRequestURI();
if (uri.startsWith("/onionoo/")) {
uri = uri.substring("/onionoo".length());
@@ -136,7 +136,8 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setResourceType(resourceType);
+ RequestHandler rh = new RequestHandler();
+ rh.setResourceType(resourceType);
/* Extract parameters either from the old-style URI or from request
* parameters. */
@@ -170,7 +171,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setType(relaysRequested ? "relay" : "bridge");
+ rh.setType(relaysRequested ? "relay" : "bridge");
}
if (parameterMap.containsKey("running")) {
String runningParameterValue =
@@ -182,7 +183,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setRunning(runningRequested ? "true" : "false");
+ rh.setRunning(runningRequested ? "true" : "false");
}
if (parameterMap.containsKey("search")) {
String[] searchTerms = this.parseSearchParameters(
@@ -191,7 +192,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setSearch(searchTerms);
+ rh.setSearch(searchTerms);
}
if (parameterMap.containsKey("lookup")) {
String fingerprintParameter = this.parseFingerprintParameter(
@@ -201,7 +202,7 @@ public class ResourceServlet extends HttpServlet {
return;
}
String fingerprint = fingerprintParameter.toUpperCase();
- rb.setLookup(fingerprint);
+ rh.setLookup(fingerprint);
}
if (parameterMap.containsKey("country")) {
String countryCodeParameter = this.parseCountryCodeParameter(
@@ -210,7 +211,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setCountry(countryCodeParameter);
+ rh.setCountry(countryCodeParameter);
}
if (parameterMap.containsKey("as")) {
String aSNumberParameter = this.parseASNumberParameter(
@@ -219,7 +220,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setAs(aSNumberParameter);
+ rh.setAs(aSNumberParameter);
}
if (parameterMap.containsKey("flag")) {
String flagParameter = this.parseFlagParameter(
@@ -228,7 +229,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setFlag(flagParameter);
+ rh.setFlag(flagParameter);
}
if (parameterMap.containsKey("first_seen_days")) {
int[] days = this.parseDaysParameter(
@@ -237,7 +238,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setFirstSeenDays(days);
+ rh.setFirstSeenDays(days);
}
if (parameterMap.containsKey("last_seen_days")) {
int[] days = this.parseDaysParameter(
@@ -246,7 +247,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setLastSeenDays(days);
+ rh.setLastSeenDays(days);
}
if (parameterMap.containsKey("contact")) {
String[] contactParts = this.parseContactParameter(
@@ -255,10 +256,8 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setContact(contactParts);
+ rh.setContact(contactParts);
}
-
- /* Re-order and limit results. */
if (parameterMap.containsKey("order")) {
String orderParameter = parameterMap.get("order").toLowerCase();
String orderByField = orderParameter;
@@ -269,7 +268,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setOrder(new String[] { orderParameter });
+ rh.setOrder(new String[] { orderParameter });
}
if (parameterMap.containsKey("offset")) {
String offsetParameter = parameterMap.get("offset");
@@ -283,7 +282,7 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setOffset(offsetParameter);
+ rh.setOffset(offsetParameter);
}
if (parameterMap.containsKey("limit")) {
String limitParameter = parameterMap.get("limit");
@@ -297,11 +296,16 @@ public class ResourceServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rb.setLimit(limitParameter);
+ rh.setLimit(limitParameter);
}
+ rh.handleRequest();
- /* Possibly include only a subset of fields in the response
- * document. */
+ ResponseBuilder rb = new ResponseBuilder();
+ rb.setResourceType(resourceType);
+ rb.setRelaysPublishedString(rh.getRelaysPublishedString());
+ rb.setBridgesPublishedString(rh.getBridgesPublishedString());
+ rb.setOrderedRelays(rh.getOrderedRelays());
+ rb.setOrderedBridges(rh.getOrderedBridges());
String[] fields = null;
if (parameterMap.containsKey("fields")) {
fields = this.parseFieldsParameter(parameterMap.get("fields"));
@@ -312,7 +316,6 @@ public class ResourceServlet extends HttpServlet {
rb.setFields(fields);
}
- /* Set response headers and write the response. */
response.setHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
diff --git a/src/org/torproject/onionoo/ResponseBuilder.java b/src/org/torproject/onionoo/ResponseBuilder.java
index 080af52..69b5c62 100644
--- a/src/org/torproject/onionoo/ResponseBuilder.java
+++ b/src/org/torproject/onionoo/ResponseBuilder.java
@@ -4,743 +4,53 @@ package org.torproject.onionoo;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Scanner;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TreeMap;
public class ResponseBuilder {
- private static long summaryFileLastModified = -1L;
private static DocumentStore documentStore;
- private static Time time;
- private static boolean successfullyReadSummaryFile = false;
- private static String relaysPublishedString, bridgesPublishedString;
- private static List<String> relaysByConsensusWeight = null;
- private static Map<String, String> relayFingerprintSummaryLines = null,
- bridgeFingerprintSummaryLines = null;
- private static Map<String, Set<String>> relaysByCountryCode = null,
- relaysByASNumber = null, relaysByFlag = null, bridgesByFlag = null,
- relaysByContact = null;
- private static SortedMap<Integer, Set<String>>
- relaysByFirstSeenDays = null, bridgesByFirstSeenDays = null,
- relaysByLastSeenDays = null, bridgesByLastSeenDays = null;
- private static final long SUMMARY_MAX_AGE = DateTimeHelper.SIX_HOURS;
- public static void initialize(DocumentStore documentStoreParam,
- Time timeParam) {
+ public static void initialize(DocumentStore documentStoreParam) {
documentStore = documentStoreParam;
- time = timeParam;
- readSummaryFile();
}
- public static boolean update() {
- readSummaryFile();
- return successfullyReadSummaryFile;
+ private String resourceType;
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
}
- private static void readSummaryFile() {
- long newSummaryFileLastModified = -1L;
- UpdateStatus updateStatus = documentStore.retrieve(UpdateStatus.class,
- false);
- if (updateStatus != null &&
- updateStatus.getDocumentString() != null) {
- String updateString = updateStatus.getDocumentString();
- try {
- newSummaryFileLastModified = Long.parseLong(updateString.trim());
- } catch (NumberFormatException e) {
- /* Handle below. */
- }
- }
- if (newSummaryFileLastModified < 0L) {
- // TODO Does this actually solve anything? Should we instead
- // switch to a variant of the maintenance mode and re-check when
- // the next requests comes in that happens x seconds after this one?
- successfullyReadSummaryFile = false;
- return;
- }
- if (newSummaryFileLastModified + SUMMARY_MAX_AGE
- < time.currentTimeMillis()) {
- // TODO Does this actually solve anything? Should we instead
- // switch to a variant of the maintenance mode and re-check when
- // the next requests comes in that happens x seconds after this one?
- successfullyReadSummaryFile = false;
- return;
- }
- if (newSummaryFileLastModified > summaryFileLastModified) {
- List<String> newRelaysByConsensusWeight = new ArrayList<String>();
- Map<String, String>
- newRelayFingerprintSummaryLines = new HashMap<String, String>(),
- newBridgeFingerprintSummaryLines =
- new HashMap<String, String>();
- Map<String, Set<String>>
- newRelaysByCountryCode = new HashMap<String, Set<String>>(),
- newRelaysByASNumber = new HashMap<String, Set<String>>(),
- newRelaysByFlag = new HashMap<String, Set<String>>(),
- newBridgesByFlag = new HashMap<String, Set<String>>(),
- newRelaysByContact = new HashMap<String, Set<String>>();
- SortedMap<Integer, Set<String>>
- newRelaysByFirstSeenDays = new TreeMap<Integer, Set<String>>(),
- newBridgesByFirstSeenDays = new TreeMap<Integer, Set<String>>(),
- newRelaysByLastSeenDays = new TreeMap<Integer, Set<String>>(),
- newBridgesByLastSeenDays = new TreeMap<Integer, Set<String>>();
- long relaysLastValidAfterMillis = -1L,
- bridgesLastPublishedMillis = -1L;
- String newRelaysPublishedString, newBridgesPublishedString;
- Set<NodeStatus> currentRelays = new HashSet<NodeStatus>(),
- currentBridges = new HashSet<NodeStatus>();
- SortedSet<String> fingerprints = documentStore.list(
- NodeStatus.class, false);
- // TODO We should be able to learn if something goes wrong when
- // reading the summary file, rather than silently having an empty
- // list of fingerprints.
- for (String fingerprint : fingerprints) {
- NodeStatus node = documentStore.retrieve(NodeStatus.class, true,
- fingerprint);
- if (node.isRelay()) {
- relaysLastValidAfterMillis = Math.max(
- relaysLastValidAfterMillis, node.getLastSeenMillis());
- currentRelays.add(node);
- } else {
- bridgesLastPublishedMillis = Math.max(
- bridgesLastPublishedMillis, node.getLastSeenMillis());
- currentBridges.add(node);
- }
- }
- newRelaysPublishedString = DateTimeHelper.format(
- relaysLastValidAfterMillis);
- newBridgesPublishedString = DateTimeHelper.format(
- bridgesLastPublishedMillis);
- List<String> orderRelaysByConsensusWeight = new ArrayList<String>();
- for (NodeStatus entry : currentRelays) {
- String fingerprint = entry.getFingerprint().toUpperCase();
- String hashedFingerprint = entry.getHashedFingerprint().
- toUpperCase();
- entry.setRunning(entry.getLastSeenMillis() ==
- relaysLastValidAfterMillis);
- String line = formatRelaySummaryLine(entry);
- newRelayFingerprintSummaryLines.put(fingerprint, line);
- newRelayFingerprintSummaryLines.put(hashedFingerprint, line);
- long consensusWeight = entry.getConsensusWeight();
- orderRelaysByConsensusWeight.add(String.format("%020d %s",
- consensusWeight, fingerprint));
- orderRelaysByConsensusWeight.add(String.format("%020d %s",
- consensusWeight, hashedFingerprint));
- if (entry.getCountryCode() != null) {
- String countryCode = entry.getCountryCode();
- if (!newRelaysByCountryCode.containsKey(countryCode)) {
- newRelaysByCountryCode.put(countryCode,
- new HashSet<String>());
- }
- newRelaysByCountryCode.get(countryCode).add(fingerprint);
- newRelaysByCountryCode.get(countryCode).add(hashedFingerprint);
- }
- if (entry.getASNumber() != null) {
- String aSNumber = entry.getASNumber();
- if (!newRelaysByASNumber.containsKey(aSNumber)) {
- newRelaysByASNumber.put(aSNumber, new HashSet<String>());
- }
- newRelaysByASNumber.get(aSNumber).add(fingerprint);
- newRelaysByASNumber.get(aSNumber).add(hashedFingerprint);
- }
- for (String flag : entry.getRelayFlags()) {
- String flagLowerCase = flag.toLowerCase();
- if (!newRelaysByFlag.containsKey(flagLowerCase)) {
- newRelaysByFlag.put(flagLowerCase, new HashSet<String>());
- }
- newRelaysByFlag.get(flagLowerCase).add(fingerprint);
- newRelaysByFlag.get(flagLowerCase).add(hashedFingerprint);
- }
- int daysSinceFirstSeen = (int) ((newSummaryFileLastModified
- - entry.getFirstSeenMillis()) / 86400000L);
- if (!newRelaysByFirstSeenDays.containsKey(daysSinceFirstSeen)) {
- newRelaysByFirstSeenDays.put(daysSinceFirstSeen,
- new HashSet<String>());
- }
- newRelaysByFirstSeenDays.get(daysSinceFirstSeen).add(fingerprint);
- newRelaysByFirstSeenDays.get(daysSinceFirstSeen).add(
- hashedFingerprint);
- int daysSinceLastSeen = (int) ((newSummaryFileLastModified
- - entry.getLastSeenMillis()) / 86400000L);
- if (!newRelaysByLastSeenDays.containsKey(daysSinceLastSeen)) {
- newRelaysByLastSeenDays.put(daysSinceLastSeen,
- new HashSet<String>());
- }
- newRelaysByLastSeenDays.get(daysSinceLastSeen).add(fingerprint);
- newRelaysByLastSeenDays.get(daysSinceLastSeen).add(
- hashedFingerprint);
- String contact = entry.getContact();
- if (!newRelaysByContact.containsKey(contact)) {
- newRelaysByContact.put(contact, new HashSet<String>());
- }
- newRelaysByContact.get(contact).add(fingerprint);
- newRelaysByContact.get(contact).add(hashedFingerprint);
- }
- Collections.sort(orderRelaysByConsensusWeight);
- newRelaysByConsensusWeight = new ArrayList<String>();
- for (String relay : orderRelaysByConsensusWeight) {
- newRelaysByConsensusWeight.add(relay.split(" ")[1]);
- }
- for (NodeStatus entry : currentBridges) {
- String hashedFingerprint = entry.getFingerprint().toUpperCase();
- String hashedHashedFingerprint = entry.getHashedFingerprint().
- toUpperCase();
- entry.setRunning(entry.getRelayFlags().contains("Running") &&
- entry.getLastSeenMillis() == bridgesLastPublishedMillis);
- String line = formatBridgeSummaryLine(entry);
- newBridgeFingerprintSummaryLines.put(hashedFingerprint, line);
- newBridgeFingerprintSummaryLines.put(hashedHashedFingerprint,
- line);
- for (String flag : entry.getRelayFlags()) {
- String flagLowerCase = flag.toLowerCase();
- if (!newBridgesByFlag.containsKey(flagLowerCase)) {
- newBridgesByFlag.put(flagLowerCase, new HashSet<String>());
- }
- newBridgesByFlag.get(flagLowerCase).add(hashedFingerprint);
- newBridgesByFlag.get(flagLowerCase).add(
- hashedHashedFingerprint);
- }
- int daysSinceFirstSeen = (int) ((newSummaryFileLastModified
- - entry.getFirstSeenMillis()) / 86400000L);
- if (!newBridgesByFirstSeenDays.containsKey(daysSinceFirstSeen)) {
- newBridgesByFirstSeenDays.put(daysSinceFirstSeen,
- new HashSet<String>());
- }
- newBridgesByFirstSeenDays.get(daysSinceFirstSeen).add(
- hashedFingerprint);
- newBridgesByFirstSeenDays.get(daysSinceFirstSeen).add(
- hashedHashedFingerprint);
- int daysSinceLastSeen = (int) ((newSummaryFileLastModified
- - entry.getLastSeenMillis()) / 86400000L);
- if (!newBridgesByLastSeenDays.containsKey(daysSinceLastSeen)) {
- newBridgesByLastSeenDays.put(daysSinceLastSeen,
- new HashSet<String>());
- }
- newBridgesByLastSeenDays.get(daysSinceLastSeen).add(
- hashedFingerprint);
- newBridgesByLastSeenDays.get(daysSinceLastSeen).add(
- hashedHashedFingerprint);
- }
- relaysByConsensusWeight = newRelaysByConsensusWeight;
- relayFingerprintSummaryLines = newRelayFingerprintSummaryLines;
- bridgeFingerprintSummaryLines = newBridgeFingerprintSummaryLines;
- relaysByCountryCode = newRelaysByCountryCode;
- relaysByASNumber = newRelaysByASNumber;
- relaysByFlag = newRelaysByFlag;
- bridgesByFlag = newBridgesByFlag;
- relaysByContact = newRelaysByContact;
- relaysByFirstSeenDays = newRelaysByFirstSeenDays;
- relaysByLastSeenDays = newRelaysByLastSeenDays;
- bridgesByFirstSeenDays = newBridgesByFirstSeenDays;
- bridgesByLastSeenDays = newBridgesByLastSeenDays;
- relaysPublishedString = newRelaysPublishedString;
- bridgesPublishedString = newBridgesPublishedString;
- }
- summaryFileLastModified = newSummaryFileLastModified;
- successfullyReadSummaryFile = true;
+ private String relaysPublishedString;
+ public void setRelaysPublishedString(String relaysPublishedString) {
+ this.relaysPublishedString = relaysPublishedString;
}
- private static String formatRelaySummaryLine(NodeStatus entry) {
- String nickname = !entry.getNickname().equals("Unnamed") ?
- entry.getNickname() : null;
- String fingerprint = entry.getFingerprint();
- String running = entry.getRunning() ? "true" : "false";
- List<String> addresses = new ArrayList<String>();
- addresses.add(entry.getAddress());
- for (String orAddress : entry.getOrAddresses()) {
- addresses.add(orAddress);
- }
- for (String exitAddress : entry.getExitAddresses()) {
- if (!addresses.contains(exitAddress)) {
- addresses.add(exitAddress);
- }
- }
- StringBuilder addressesBuilder = new StringBuilder();
- int written = 0;
- for (String address : addresses) {
- addressesBuilder.append((written++ > 0 ? "," : "") + "\""
- + address.toLowerCase() + "\"");
- }
- return String.format("{%s\"f\":\"%s\",\"a\":[%s],\"r\":%s}",
- (nickname == null ? "" : "\"n\":\"" + nickname + "\","),
- fingerprint, addressesBuilder.toString(), running);
+ private String bridgesPublishedString;
+ public void setBridgesPublishedString(String bridgesPublishedString) {
+ this.bridgesPublishedString = bridgesPublishedString;
}
- private static String formatBridgeSummaryLine(NodeStatus entry) {
- String nickname = !entry.getNickname().equals("Unnamed") ?
- entry.getNickname() : null;
- String hashedFingerprint = entry.getFingerprint();
- String running = entry.getRunning() ? "true" : "false";
- return String.format("{%s\"h\":\"%s\",\"r\":%s}",
- (nickname == null ? "" : "\"n\":\"" + nickname + "\","),
- hashedFingerprint, running);
+ private List<String> orderedRelays = new ArrayList<String>();
+ public void setOrderedRelays(List<String> orderedRelays) {
+ this.orderedRelays = orderedRelays;
}
- public static long getLastModified() {
- readSummaryFile();
- return summaryFileLastModified;
+ private List<String> orderedBridges = new ArrayList<String>();
+ public void setOrderedBridges(List<String> orderedBridges) {
+ this.orderedBridges = orderedBridges;
}
- private String resourceType, type, running, search[], lookup, country,
- as, flag, contact[], fields[], order[], offset, limit;
- private int[] firstSeenDays, lastSeenDays;
-
- public void setResourceType(String resourceType) {
- this.resourceType = resourceType;
- }
- public void setType(String type) {
- this.type = type;
- }
- public void setRunning(String running) {
- this.running = running;
- }
- public void setSearch(String[] search) {
- this.search = new String[search.length];
- System.arraycopy(search, 0, this.search, 0, search.length);
- }
- public void setLookup(String lookup) {
- this.lookup = lookup;
- }
- public void setCountry(String country) {
- this.country = country;
- }
- public void setAs(String as) {
- this.as = as;
- }
- public void setFlag(String flag) {
- this.flag = flag;
- }
- public void setFirstSeenDays(int[] firstSeenDays) {
- this.firstSeenDays = new int[firstSeenDays.length];
- System.arraycopy(firstSeenDays, 0, this.firstSeenDays, 0,
- firstSeenDays.length);
- }
- public void setLastSeenDays(int[] lastSeenDays) {
- this.lastSeenDays = new int[lastSeenDays.length];
- System.arraycopy(lastSeenDays, 0, this.lastSeenDays, 0,
- lastSeenDays.length);
- }
- public void setContact(String[] contact) {
- this.contact = new String[contact.length];
- System.arraycopy(contact, 0, this.contact, 0, contact.length);
- }
+ private String[] fields;
public void setFields(String[] fields) {
this.fields = new String[fields.length];
System.arraycopy(fields, 0, this.fields, 0, fields.length);
}
- public void setOrder(String[] order) {
- this.order = new String[order.length];
- System.arraycopy(order, 0, this.order, 0, order.length);
- }
- public void setOffset(String offset) {
- this.offset = offset;
- }
- public void setLimit(String limit) {
- this.limit = limit;
- }
public void buildResponse(PrintWriter pw) {
-
- /* Filter relays and bridges matching the request. */
- Map<String, String> filteredRelays = new HashMap<String, String>(
- relayFingerprintSummaryLines);
- Map<String, String> filteredBridges = new HashMap<String, String>(
- bridgeFingerprintSummaryLines);
- filterByResourceType(filteredRelays, filteredBridges);
- filterByType(filteredRelays, filteredBridges);
- filterByRunning(filteredRelays, filteredBridges);
- filterBySearchTerms(filteredRelays, filteredBridges);
- filterByFingerprint(filteredRelays, filteredBridges);
- filterByCountryCode(filteredRelays, filteredBridges);
- filterByASNumber(filteredRelays, filteredBridges);
- filterByFlag(filteredRelays, filteredBridges);
- filterNodesByFirstSeenDays(filteredRelays, filteredBridges);
- filterNodesByLastSeenDays(filteredRelays, filteredBridges);
- filterByContact(filteredRelays, filteredBridges);
-
- /* Re-order and limit results. */
- List<String> orderedRelays = new ArrayList<String>();
- List<String> orderedBridges = new ArrayList<String>();
- order(filteredRelays, filteredBridges, orderedRelays, orderedBridges);
- offset(orderedRelays, orderedBridges);
- limit(orderedRelays, orderedBridges);
-
- /* Write the response. */
writeRelays(orderedRelays, pw);
writeBridges(orderedBridges, pw);
}
- private void filterByResourceType(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.resourceType.equals("clients")) {
- filteredRelays.clear();
- }
- if (this.resourceType.equals("weights")) {
- filteredBridges.clear();
- }
- }
-
- private void filterByType(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.type == null) {
- return;
- } else if (this.type.equals("relay")) {
- filteredBridges.clear();
- } else {
- filteredRelays.clear();
- }
- }
-
- private void filterByRunning(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.running == null) {
- return;
- }
- boolean runningRequested = this.running.equals("true");
- Set<String> removeRelays = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
- if (e.getValue().contains("\"r\":true") != runningRequested) {
- removeRelays.add(e.getKey());
- }
- }
- for (String fingerprint : removeRelays) {
- filteredRelays.remove(fingerprint);
- }
- Set<String> removeBridges = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
- if (e.getValue().contains("\"r\":true") != runningRequested) {
- removeBridges.add(e.getKey());
- }
- }
- for (String fingerprint : removeBridges) {
- filteredBridges.remove(fingerprint);
- }
- }
-
- private void filterBySearchTerms(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.search == null) {
- return;
- }
- for (String searchTerm : this.search) {
- filterBySearchTerm(filteredRelays, filteredBridges, searchTerm);
- }
- }
-
- private void filterBySearchTerm(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges, String searchTerm) {
- Set<String> removeRelays = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
- String fingerprint = e.getKey();
- String line = e.getValue();
- boolean lineMatches = false;
- String nickname = "unnamed";
- if (line.contains("\"n\":\"")) {
- nickname = line.substring(line.indexOf("\"n\":\"") + 5).
- split("\"")[0].toLowerCase();
- }
- if (searchTerm.startsWith("$")) {
- /* Search is for $-prefixed fingerprint. */
- if (fingerprint.startsWith(
- searchTerm.substring(1).toUpperCase())) {
- /* $-prefixed fingerprint matches. */
- lineMatches = true;
- }
- } else if (nickname.contains(searchTerm.toLowerCase())) {
- /* Nickname matches. */
- lineMatches = true;
- } else if (fingerprint.startsWith(searchTerm.toUpperCase())) {
- /* Non-$-prefixed fingerprint matches. */
- lineMatches = true;
- } else if (line.substring(line.indexOf("\"a\":[")).contains("\""
- + searchTerm.toLowerCase())) {
- /* Address matches. */
- lineMatches = true;
- }
- if (!lineMatches) {
- removeRelays.add(e.getKey());
- }
- }
- for (String fingerprint : removeRelays) {
- filteredRelays.remove(fingerprint);
- }
- Set<String> removeBridges = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
- String hashedFingerprint = e.getKey();
- String line = e.getValue();
- boolean lineMatches = false;
- String nickname = "unnamed";
- if (line.contains("\"n\":\"")) {
- nickname = line.substring(line.indexOf("\"n\":\"") + 5).
- split("\"")[0].toLowerCase();
- }
- if (searchTerm.startsWith("$")) {
- /* Search is for $-prefixed hashed fingerprint. */
- if (hashedFingerprint.startsWith(
- searchTerm.substring(1).toUpperCase())) {
- /* $-prefixed hashed fingerprint matches. */
- lineMatches = true;
- }
- } else if (nickname.contains(searchTerm.toLowerCase())) {
- /* Nickname matches. */
- lineMatches = true;
- } else if (hashedFingerprint.startsWith(searchTerm.toUpperCase())) {
- /* Non-$-prefixed hashed fingerprint matches. */
- lineMatches = true;
- }
- if (!lineMatches) {
- removeBridges.add(e.getKey());
- }
- }
- for (String fingerprint : removeBridges) {
- filteredBridges.remove(fingerprint);
- }
- }
-
- private void filterByFingerprint(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.lookup == null) {
- return;
- }
- String fingerprint = this.lookup;
- String relayLine = filteredRelays.get(fingerprint);
- filteredRelays.clear();
- if (relayLine != null) {
- filteredRelays.put(fingerprint, relayLine);
- }
- String bridgeLine = filteredBridges.get(fingerprint);
- filteredBridges.clear();
- if (bridgeLine != null) {
- filteredBridges.put(fingerprint, bridgeLine);
- }
- }
-
- private void filterByCountryCode(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.country == null) {
- return;
- }
- String countryCode = this.country.toLowerCase();
- if (!relaysByCountryCode.containsKey(countryCode)) {
- filteredRelays.clear();
- } else {
- Set<String> relaysWithCountryCode =
- relaysByCountryCode.get(countryCode);
- Set<String> removeRelays = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
- String fingerprint = e.getKey();
- if (!relaysWithCountryCode.contains(fingerprint)) {
- removeRelays.add(fingerprint);
- }
- }
- for (String fingerprint : removeRelays) {
- filteredRelays.remove(fingerprint);
- }
- }
- filteredBridges.clear();
- }
-
- private void filterByASNumber(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.as == null) {
- return;
- }
- String aSNumber = this.as.toUpperCase();
- if (!aSNumber.startsWith("AS")) {
- aSNumber = "AS" + aSNumber;
- }
- if (!relaysByASNumber.containsKey(aSNumber)) {
- filteredRelays.clear();
- } else {
- Set<String> relaysWithASNumber =
- relaysByASNumber.get(aSNumber);
- Set<String> removeRelays = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
- String fingerprint = e.getKey();
- if (!relaysWithASNumber.contains(fingerprint)) {
- removeRelays.add(fingerprint);
- }
- }
- for (String fingerprint : removeRelays) {
- filteredRelays.remove(fingerprint);
- }
- }
- filteredBridges.clear();
- }
-
- private void filterByFlag(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.flag == null) {
- return;
- }
- String flag = this.flag.toLowerCase();
- if (!relaysByFlag.containsKey(flag)) {
- filteredRelays.clear();
- } else {
- Set<String> relaysWithFlag = relaysByFlag.get(flag);
- Set<String> removeRelays = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
- String fingerprint = e.getKey();
- if (!relaysWithFlag.contains(fingerprint)) {
- removeRelays.add(fingerprint);
- }
- }
- for (String fingerprint : removeRelays) {
- filteredRelays.remove(fingerprint);
- }
- }
- if (!bridgesByFlag.containsKey(flag)) {
- filteredBridges.clear();
- } else {
- Set<String> bridgesWithFlag = bridgesByFlag.get(flag);
- Set<String> removeBridges = new HashSet<String>();
- for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
- String fingerprint = e.getKey();
- if (!bridgesWithFlag.contains(fingerprint)) {
- removeBridges.add(fingerprint);
- }
- }
- for (String fingerprint : removeBridges) {
- filteredBridges.remove(fingerprint);
- }
- }
- }
-
- private void filterNodesByFirstSeenDays(
- Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.firstSeenDays == null) {
- return;
- }
- filterNodesByDays(filteredRelays, relaysByFirstSeenDays,
- this.firstSeenDays);
- filterNodesByDays(filteredBridges, bridgesByFirstSeenDays,
- this.firstSeenDays);
- }
-
- private void filterNodesByLastSeenDays(
- Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.lastSeenDays == null) {
- return;
- }
- filterNodesByDays(filteredRelays, relaysByLastSeenDays,
- this.lastSeenDays);
- filterNodesByDays(filteredBridges, bridgesByLastSeenDays,
- this.lastSeenDays);
- }
-
- private void filterNodesByDays(Map<String, String> filteredNodes,
- SortedMap<Integer, Set<String>> nodesByDays, int[] days) {
- Set<String> removeNodes = new HashSet<String>();
- for (Set<String> nodes : nodesByDays.headMap(days[0]).values()) {
- removeNodes.addAll(nodes);
- }
- if (days[1] < Integer.MAX_VALUE) {
- for (Set<String> nodes :
- nodesByDays.tailMap(days[1] + 1).values()) {
- removeNodes.addAll(nodes);
- }
- }
- for (String fingerprint : removeNodes) {
- filteredNodes.remove(fingerprint);
- }
- }
-
- private void filterByContact(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges) {
- if (this.contact == null) {
- return;
- }
- Set<String> removeRelays = new HashSet<String>();
- for (Map.Entry<String, Set<String>> e : relaysByContact.entrySet()) {
- String contact = e.getKey();
- for (String contactPart : this.contact) {
- if (contact == null ||
- !contact.contains(contactPart.toLowerCase())) {
- removeRelays.addAll(e.getValue());
- break;
- }
- }
- }
- for (String fingerprint : removeRelays) {
- filteredRelays.remove(fingerprint);
- }
- filteredBridges.clear();
- }
-
- private void order(Map<String, String> filteredRelays,
- Map<String, String> filteredBridges, List<String> orderedRelays,
- List<String> orderedBridges) {
- if (this.order != null && this.order.length == 1) {
- List<String> orderBy = new ArrayList<String>(
- relaysByConsensusWeight);
- if (this.order[0].startsWith("-")) {
- Collections.reverse(orderBy);
- }
- for (String relay : orderBy) {
- if (filteredRelays.containsKey(relay) &&
- !orderedRelays.contains(filteredRelays.get(relay))) {
- orderedRelays.add(filteredRelays.remove(relay));
- }
- }
- for (String relay : filteredRelays.keySet()) {
- if (!orderedRelays.contains(filteredRelays.get(relay))) {
- orderedRelays.add(filteredRelays.remove(relay));
- }
- }
- Set<String> uniqueBridges = new HashSet<String>(
- filteredBridges.values());
- orderedBridges.addAll(uniqueBridges);
- } else {
- Set<String> uniqueRelays = new HashSet<String>(
- filteredRelays.values());
- orderedRelays.addAll(uniqueRelays);
- Set<String> uniqueBridges = new HashSet<String>(
- filteredBridges.values());
- orderedBridges.addAll(uniqueBridges);
- }
- }
-
- private void offset(List<String> orderedRelays,
- List<String> orderedBridges) {
- if (offset == null) {
- return;
- }
- int offsetValue = Integer.parseInt(offset);
- while (offsetValue-- > 0 &&
- (!orderedRelays.isEmpty() || !orderedBridges.isEmpty())) {
- if (!orderedRelays.isEmpty()) {
- orderedRelays.remove(0);
- } else {
- orderedBridges.remove(0);
- }
- }
- }
-
- private void limit(List<String> orderedRelays,
- List<String> orderedBridges) {
- if (limit == null) {
- return;
- }
- int limitValue = Integer.parseInt(limit);
- while (!orderedRelays.isEmpty() &&
- limitValue < orderedRelays.size()) {
- orderedRelays.remove(orderedRelays.size() - 1);
- }
- limitValue -= orderedRelays.size();
- while (!orderedBridges.isEmpty() &&
- limitValue < orderedBridges.size()) {
- orderedBridges.remove(orderedBridges.size() - 1);
- }
- }
-
private void writeRelays(List<String> relays, PrintWriter pw) {
pw.write("{\"relays_published\":\"" + relaysPublishedString
+ "\",\n\"relays\":[");
1
0

14 Apr '14
commit 1635812bdd5326c265eb4cdeae751b29d8deae95
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Apr 8 23:41:50 2014 +0200
Reduce visibility of attributes to private.
Suggested by SonarQube.
---
.../onionoo/BandwidthDocumentWriter.java | 5 +-
src/org/torproject/onionoo/BandwidthStatus.java | 18 +-
.../torproject/onionoo/BandwidthStatusUpdater.java | 8 +-
.../torproject/onionoo/ClientsDocumentWriter.java | 22 +-
src/org/torproject/onionoo/ClientsStatus.java | 39 +-
.../torproject/onionoo/ClientsStatusUpdater.java | 27 +-
src/org/torproject/onionoo/DescriptorSource.java | 28 +-
.../torproject/onionoo/DetailsDocumentWriter.java | 15 +-
src/org/torproject/onionoo/Document.java | 8 +-
src/org/torproject/onionoo/DocumentStore.java | 12 +-
src/org/torproject/onionoo/LookupService.java | 104 +++--
.../onionoo/NodeDetailsStatusUpdater.java | 31 +-
src/org/torproject/onionoo/NodeStatus.java | 456 +++++++++++---------
src/org/torproject/onionoo/ResponseBuilder.java | 25 +-
.../onionoo/ReverseDomainNameResolver.java | 6 +-
.../torproject/onionoo/UptimeDocumentWriter.java | 42 +-
src/org/torproject/onionoo/UptimeStatus.java | 23 +-
.../torproject/onionoo/UptimeStatusUpdater.java | 22 +-
.../torproject/onionoo/WeightsDocumentWriter.java | 6 +-
src/org/torproject/onionoo/WeightsStatus.java | 15 +-
.../torproject/onionoo/WeightsStatusUpdater.java | 12 +-
.../org/torproject/onionoo/DummyDocumentStore.java | 2 +-
test/org/torproject/onionoo/LookupServiceTest.java | 33 +-
23 files changed, 567 insertions(+), 392 deletions(-)
diff --git a/src/org/torproject/onionoo/BandwidthDocumentWriter.java b/src/org/torproject/onionoo/BandwidthDocumentWriter.java
index 0c7308e..8e9b93c 100644
--- a/src/org/torproject/onionoo/BandwidthDocumentWriter.java
+++ b/src/org/torproject/onionoo/BandwidthDocumentWriter.java
@@ -49,7 +49,8 @@ public class BandwidthDocumentWriter implements FingerprintListener,
continue;
}
this.writeBandwidthDataFileToDisk(fingerprint,
- bandwidthStatus.writeHistory, bandwidthStatus.readHistory);
+ bandwidthStatus.getWriteHistory(),
+ bandwidthStatus.getReadHistory());
}
Logger.printStatusTime("Wrote bandwidth document files");
}
@@ -64,7 +65,7 @@ public class BandwidthDocumentWriter implements FingerprintListener,
+ "\"write_history\":{\n" + writeHistoryString + "},\n"
+ "\"read_history\":{\n" + readHistoryString + "}}\n");
BandwidthDocument bandwidthDocument = new BandwidthDocument();
- bandwidthDocument.documentString = sb.toString();
+ bandwidthDocument.setDocumentString(sb.toString());
this.documentStore.store(bandwidthDocument, fingerprint);
}
diff --git a/src/org/torproject/onionoo/BandwidthStatus.java b/src/org/torproject/onionoo/BandwidthStatus.java
index 00e8ca8..37bbc8d 100644
--- a/src/org/torproject/onionoo/BandwidthStatus.java
+++ b/src/org/torproject/onionoo/BandwidthStatus.java
@@ -8,9 +8,23 @@ import java.util.TreeMap;
class BandwidthStatus extends Document {
- SortedMap<Long, long[]> writeHistory = new TreeMap<Long, long[]>();
+ private SortedMap<Long, long[]> writeHistory =
+ new TreeMap<Long, long[]>();
+ public void setWriteHistory(SortedMap<Long, long[]> writeHistory) {
+ this.writeHistory = writeHistory;
+ }
+ public SortedMap<Long, long[]> getWriteHistory() {
+ return this.writeHistory;
+ }
- SortedMap<Long, long[]> readHistory = new TreeMap<Long, long[]>();
+ private SortedMap<Long, long[]> readHistory =
+ new TreeMap<Long, long[]>();
+ public void setReadHistory(SortedMap<Long, long[]> readHistory) {
+ this.readHistory = readHistory;
+ }
+ public SortedMap<Long, long[]> getReadHistory() {
+ return this.readHistory;
+ }
public void fromDocumentString(String documentString) {
Scanner s = new Scanner(documentString);
diff --git a/src/org/torproject/onionoo/BandwidthStatusUpdater.java b/src/org/torproject/onionoo/BandwidthStatusUpdater.java
index 6aff25d..7633e9f 100644
--- a/src/org/torproject/onionoo/BandwidthStatusUpdater.java
+++ b/src/org/torproject/onionoo/BandwidthStatusUpdater.java
@@ -51,14 +51,14 @@ public class BandwidthStatusUpdater implements DescriptorListener,
}
if (descriptor.getWriteHistory() != null) {
parseHistoryLine(descriptor.getWriteHistory().getLine(),
- bandwidthStatus.writeHistory);
+ bandwidthStatus.getWriteHistory());
}
if (descriptor.getReadHistory() != null) {
parseHistoryLine(descriptor.getReadHistory().getLine(),
- bandwidthStatus.readHistory);
+ bandwidthStatus.getReadHistory());
}
- this.compressHistory(bandwidthStatus.writeHistory);
- this.compressHistory(bandwidthStatus.readHistory);
+ this.compressHistory(bandwidthStatus.getWriteHistory());
+ this.compressHistory(bandwidthStatus.getReadHistory());
this.documentStore.store(bandwidthStatus, fingerprint);
}
diff --git a/src/org/torproject/onionoo/ClientsDocumentWriter.java b/src/org/torproject/onionoo/ClientsDocumentWriter.java
index d9ff02d..34047b5 100644
--- a/src/org/torproject/onionoo/ClientsDocumentWriter.java
+++ b/src/org/torproject/onionoo/ClientsDocumentWriter.java
@@ -74,10 +74,10 @@ public class ClientsDocumentWriter implements FingerprintListener,
if (clientsStatus == null) {
continue;
}
- SortedSet<ClientsHistory> history = clientsStatus.history;
+ SortedSet<ClientsHistory> history = clientsStatus.getHistory();
ClientsDocument clientsDocument = new ClientsDocument();
- clientsDocument.documentString = this.formatHistoryString(
- hashedFingerprint, history);
+ clientsDocument.setDocumentString(this.formatHistoryString(
+ hashedFingerprint, history));
this.documentStore.store(clientsDocument, hashedFingerprint);
this.writtenDocuments++;
}
@@ -140,11 +140,11 @@ public class ClientsDocumentWriter implements FingerprintListener,
totalResponsesByTransport = new TreeMap<String, Double>(),
totalResponsesByVersion = new TreeMap<String, Double>();
for (ClientsHistory hist : history) {
- if (hist.endMillis < intervalStartMillis) {
+ if (hist.getEndMillis() < intervalStartMillis) {
continue;
}
while ((intervalStartMillis / dataPointInterval) !=
- (hist.endMillis / dataPointInterval)) {
+ (hist.getEndMillis() / dataPointInterval)) {
dataPoints.add(millis * 2L < dataPointInterval
? -1.0 : responses * ((double) DateTimeHelper.ONE_DAY)
/ (((double) millis) * 10.0));
@@ -152,10 +152,10 @@ public class ClientsDocumentWriter implements FingerprintListener,
millis = 0L;
intervalStartMillis += dataPointInterval;
}
- responses += hist.totalResponses;
- totalResponses += hist.totalResponses;
+ responses += hist.getTotalResponses();
+ totalResponses += hist.getTotalResponses();
for (Map.Entry<String, Double> e :
- hist.responsesByCountry.entrySet()) {
+ hist.getResponsesByCountry().entrySet()) {
if (!totalResponsesByCountry.containsKey(e.getKey())) {
totalResponsesByCountry.put(e.getKey(), 0.0);
}
@@ -163,7 +163,7 @@ public class ClientsDocumentWriter implements FingerprintListener,
+ totalResponsesByCountry.get(e.getKey()));
}
for (Map.Entry<String, Double> e :
- hist.responsesByTransport.entrySet()) {
+ hist.getResponsesByTransport().entrySet()) {
if (!totalResponsesByTransport.containsKey(e.getKey())) {
totalResponsesByTransport.put(e.getKey(), 0.0);
}
@@ -171,14 +171,14 @@ public class ClientsDocumentWriter implements FingerprintListener,
+ totalResponsesByTransport.get(e.getKey()));
}
for (Map.Entry<String, Double> e :
- hist.responsesByVersion.entrySet()) {
+ hist.getResponsesByVersion().entrySet()) {
if (!totalResponsesByVersion.containsKey(e.getKey())) {
totalResponsesByVersion.put(e.getKey(), 0.0);
}
totalResponsesByVersion.put(e.getKey(), e.getValue()
+ totalResponsesByVersion.get(e.getKey()));
}
- millis += (hist.endMillis - hist.startMillis);
+ millis += (hist.getEndMillis() - hist.getStartMillis());
}
dataPoints.add(millis * 2L < dataPointInterval
? -1.0 : responses * ((double) DateTimeHelper.ONE_DAY)
diff --git a/src/org/torproject/onionoo/ClientsStatus.java b/src/org/torproject/onionoo/ClientsStatus.java
index 26f9eab..8bf0998 100644
--- a/src/org/torproject/onionoo/ClientsStatus.java
+++ b/src/org/torproject/onionoo/ClientsStatus.java
@@ -11,17 +11,35 @@ import java.util.TreeSet;
class ClientsHistory implements Comparable<ClientsHistory> {
- long startMillis;
+ private long startMillis;
+ public long getStartMillis() {
+ return this.startMillis;
+ }
- long endMillis;
+ private long endMillis;
+ public long getEndMillis() {
+ return this.endMillis;
+ }
- double totalResponses;
+ private double totalResponses;
+ public double getTotalResponses() {
+ return this.totalResponses;
+ }
- SortedMap<String, Double> responsesByCountry;
+ private SortedMap<String, Double> responsesByCountry;
+ public SortedMap<String, Double> getResponsesByCountry() {
+ return this.responsesByCountry;
+ }
- SortedMap<String, Double> responsesByTransport;
+ private SortedMap<String, Double> responsesByTransport;
+ public SortedMap<String, Double> getResponsesByTransport() {
+ return this.responsesByTransport;
+ }
- SortedMap<String, Double> responsesByVersion;
+ private SortedMap<String, Double> responsesByVersion;
+ public SortedMap<String, Double> getResponsesByVersion() {
+ return this.responsesByVersion;
+ }
ClientsHistory(long startMillis, long endMillis,
double totalResponses,
@@ -158,7 +176,14 @@ class ClientsHistory implements Comparable<ClientsHistory> {
class ClientsStatus extends Document {
- SortedSet<ClientsHistory> history = new TreeSet<ClientsHistory>();
+ private SortedSet<ClientsHistory> history =
+ new TreeSet<ClientsHistory>();
+ public void setHistory(SortedSet<ClientsHistory> history) {
+ this.history = history;
+ }
+ public SortedSet<ClientsHistory> getHistory() {
+ return this.history;
+ }
public void fromDocumentString(String documentString) {
Scanner s = new Scanner(documentString);
diff --git a/src/org/torproject/onionoo/ClientsStatusUpdater.java b/src/org/torproject/onionoo/ClientsStatusUpdater.java
index 8a98ccf..56803d4 100644
--- a/src/org/torproject/onionoo/ClientsStatusUpdater.java
+++ b/src/org/torproject/onionoo/ClientsStatusUpdater.java
@@ -155,42 +155,43 @@ public class ClientsStatusUpdater implements DescriptorListener,
private void addToHistory(ClientsStatus clientsStatus,
SortedSet<ClientsHistory> newIntervals) {
- SortedSet<ClientsHistory> history = clientsStatus.history;
+ SortedSet<ClientsHistory> history = clientsStatus.getHistory();
for (ClientsHistory interval : newIntervals) {
if ((history.headSet(interval).isEmpty() ||
- history.headSet(interval).last().endMillis <=
- interval.startMillis) &&
+ history.headSet(interval).last().getEndMillis() <=
+ interval.getStartMillis()) &&
(history.tailSet(interval).isEmpty() ||
- history.tailSet(interval).first().startMillis >=
- interval.endMillis)) {
+ history.tailSet(interval).first().getStartMillis() >=
+ interval.getEndMillis())) {
history.add(interval);
}
}
}
private void compressHistory(ClientsStatus clientsStatus) {
- SortedSet<ClientsHistory> history = clientsStatus.history;
+ SortedSet<ClientsHistory> history = clientsStatus.getHistory();
SortedSet<ClientsHistory> compressedHistory =
new TreeSet<ClientsHistory>();
ClientsHistory lastResponses = null;
String lastMonthString = "1970-01";
for (ClientsHistory responses : history) {
long intervalLengthMillis;
- if (this.now - responses.endMillis <=
+ if (this.now - responses.getEndMillis() <=
DateTimeHelper.ROUGHLY_THREE_MONTHS) {
intervalLengthMillis = DateTimeHelper.ONE_DAY;
- } else if (this.now - responses.endMillis <=
+ } else if (this.now - responses.getEndMillis() <=
DateTimeHelper.ROUGHLY_ONE_YEAR) {
intervalLengthMillis = DateTimeHelper.TWO_DAYS;
} else {
intervalLengthMillis = DateTimeHelper.TEN_DAYS;
}
- String monthString = DateTimeHelper.format(responses.startMillis,
+ String monthString = DateTimeHelper.format(
+ responses.getStartMillis(),
DateTimeHelper.ISO_YEARMONTH_FORMAT);
if (lastResponses != null &&
- lastResponses.endMillis == responses.startMillis &&
- ((lastResponses.endMillis - 1L) / intervalLengthMillis) ==
- ((responses.endMillis - 1L) / intervalLengthMillis) &&
+ lastResponses.getEndMillis() == responses.getStartMillis() &&
+ ((lastResponses.getEndMillis() - 1L) / intervalLengthMillis) ==
+ ((responses.getEndMillis() - 1L) / intervalLengthMillis) &&
lastMonthString.equals(monthString)) {
lastResponses.addResponses(responses);
} else {
@@ -204,7 +205,7 @@ public class ClientsStatusUpdater implements DescriptorListener,
if (lastResponses != null) {
compressedHistory.add(lastResponses);
}
- clientsStatus.history = compressedHistory;
+ clientsStatus.setHistory(compressedHistory);
}
public String getStatsString() {
diff --git a/src/org/torproject/onionoo/DescriptorSource.java b/src/org/torproject/onionoo/DescriptorSource.java
index c72e8ce..86fba25 100644
--- a/src/org/torproject/onionoo/DescriptorSource.java
+++ b/src/org/torproject/onionoo/DescriptorSource.java
@@ -77,13 +77,25 @@ class DescriptorQueue {
private List<Descriptor> descriptors;
- int historySizeBefore;
+ private int historySizeBefore;
+ public int getHistorySizeBefore() {
+ return this.historySizeBefore;
+ }
- int historySizeAfter;
+ private int historySizeAfter;
+ public int getHistorySizeAfter() {
+ return this.historySizeAfter;
+ }
- long returnedDescriptors = 0L;
+ private long returnedDescriptors = 0L;
+ public long getReturnedDescriptors() {
+ return this.returnedDescriptors;
+ }
- long returnedBytes = 0L;
+ private long returnedBytes = 0L;
+ public long getReturnedBytes() {
+ return this.returnedBytes;
+ }
public DescriptorQueue(File inDir, File statusDir) {
this.inDir = inDir;
@@ -424,10 +436,10 @@ public class DescriptorSource {
int historySizeBefore = 0, historySizeAfter = 0;
long descriptors = 0L, bytes = 0L;
for (DescriptorQueue descriptorQueue : descriptorQueues) {
- historySizeBefore += descriptorQueue.historySizeBefore;
- historySizeAfter += descriptorQueue.historySizeAfter;
- descriptors += descriptorQueue.returnedDescriptors;
- bytes += descriptorQueue.returnedBytes;
+ historySizeBefore += descriptorQueue.getHistorySizeBefore();
+ historySizeAfter += descriptorQueue.getHistorySizeAfter();
+ descriptors += descriptorQueue.getReturnedDescriptors();
+ bytes += descriptorQueue.getReturnedBytes();
}
sb.append(" " + Logger.formatDecimalNumber(historySizeBefore)
+ " descriptors excluded from this execution\n");
diff --git a/src/org/torproject/onionoo/DetailsDocumentWriter.java b/src/org/torproject/onionoo/DetailsDocumentWriter.java
index 57d0877..cea6ba3 100644
--- a/src/org/torproject/onionoo/DetailsDocumentWriter.java
+++ b/src/org/torproject/onionoo/DetailsDocumentWriter.java
@@ -263,13 +263,14 @@ public class DetailsDocumentWriter implements DescriptorListener,
/* Append descriptor-specific part from details status file, and
* update contact in node status. */
+ /* TODO Updating the contact here seems like a pretty bad hack. */
DetailsStatus detailsStatus = this.documentStore.retrieve(
DetailsStatus.class, false, fingerprint);
if (detailsStatus != null &&
- detailsStatus.documentString.length() > 0) {
- sb.append(",\n" + detailsStatus.documentString);
+ detailsStatus.getDocumentString().length() > 0) {
+ sb.append(",\n" + detailsStatus.getDocumentString());
String contact = null;
- Scanner s = new Scanner(detailsStatus.documentString);
+ Scanner s = new Scanner(detailsStatus.getDocumentString());
while (s.hasNextLine()) {
String line = s.nextLine();
if (!line.startsWith("\"contact\":")) {
@@ -291,7 +292,7 @@ public class DetailsDocumentWriter implements DescriptorListener,
/* Write details file to disk. */
DetailsDocument detailsDocument = new DetailsDocument();
- detailsDocument.documentString = sb.toString();
+ detailsDocument.setDocumentString(sb.toString());
this.documentStore.store(detailsDocument, fingerprint);
}
}
@@ -343,8 +344,8 @@ public class DetailsDocumentWriter implements DescriptorListener,
DetailsStatus detailsStatus = this.documentStore.retrieve(
DetailsStatus.class, false, fingerprint);
if (detailsStatus != null &&
- detailsStatus.documentString.length() > 0) {
- sb.append(",\n" + detailsStatus.documentString);
+ detailsStatus.getDocumentString().length() > 0) {
+ sb.append(",\n" + detailsStatus.getDocumentString());
}
/* Finish details string. */
@@ -352,7 +353,7 @@ public class DetailsDocumentWriter implements DescriptorListener,
/* Write details file to disk. */
DetailsDocument detailsDocument = new DetailsDocument();
- detailsDocument.documentString = sb.toString();
+ detailsDocument.setDocumentString(sb.toString());
this.documentStore.store(detailsDocument, fingerprint);
}
}
diff --git a/src/org/torproject/onionoo/Document.java b/src/org/torproject/onionoo/Document.java
index f0fac2c..bea0794 100644
--- a/src/org/torproject/onionoo/Document.java
+++ b/src/org/torproject/onionoo/Document.java
@@ -4,7 +4,13 @@ package org.torproject.onionoo;
abstract class Document {
- transient String documentString;
+ private transient String documentString;
+ public void setDocumentString(String documentString) {
+ this.documentString = documentString;
+ }
+ public String getDocumentString() {
+ return this.documentString;
+ }
public void fromDocumentString(String documentString) {
/* Subclasses may override this method to parse documentString. */
diff --git a/src/org/torproject/onionoo/DocumentStore.java b/src/org/torproject/onionoo/DocumentStore.java
index 46b5d98..fa0e98c 100644
--- a/src/org/torproject/onionoo/DocumentStore.java
+++ b/src/org/torproject/onionoo/DocumentStore.java
@@ -35,10 +35,10 @@ public class DocumentStore {
private Time time;
- boolean listedArchivedNodeStatuses = false,
+ private boolean listedArchivedNodeStatuses = false,
listedCurrentNodeStatuses = false;
- long listOperations = 0L, listedFiles = 0L, storedFiles = 0L,
+ private long listOperations = 0L, listedFiles = 0L, storedFiles = 0L,
storedBytes = 0L, retrievedFiles = 0L, retrievedBytes = 0L,
removedFiles = 0L;
@@ -187,8 +187,8 @@ public class DocumentStore {
return false;
}
String documentString;
- if (document.documentString != null) {
- documentString = document.documentString;
+ if (document.getDocumentString() != null) {
+ documentString = document.getDocumentString();
} else if (document instanceof DetailsDocument ||
document instanceof BandwidthDocument ||
document instanceof WeightsDocument ||
@@ -329,7 +329,7 @@ public class DocumentStore {
Gson gson = new Gson();
try {
result = gson.fromJson(documentString, documentType);
- result.documentString = documentString;
+ result.setDocumentString(documentString);
} catch (JsonParseException e) {
/* Handle below. */
e.printStackTrace();
@@ -346,7 +346,7 @@ public class DocumentStore {
T result = null;
try {
result = documentType.newInstance();
- result.documentString = documentString;
+ result.setDocumentString(documentString);
} catch (InstantiationException e) {
/* Handle below. */
e.printStackTrace();
diff --git a/src/org/torproject/onionoo/LookupService.java b/src/org/torproject/onionoo/LookupService.java
index 39f4e2e..a950f02 100644
--- a/src/org/torproject/onionoo/LookupService.java
+++ b/src/org/torproject/onionoo/LookupService.java
@@ -17,12 +17,79 @@ import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
+class LookupResult {
+
+ private String countryCode;
+ public void setCountryCode(String countryCode) {
+ this.countryCode = countryCode;
+ }
+ public String getCountryCode() {
+ return this.countryCode;
+ }
+
+ private String countryName;
+ public void setCountryName(String countryName) {
+ this.countryName = countryName;
+ }
+ public String getCountryName() {
+ return this.countryName;
+ }
+
+ private String regionName;
+ public void setRegionName(String regionName) {
+ this.regionName = regionName;
+ }
+ public String getRegionName() {
+ return this.regionName;
+ }
+
+ private String cityName;
+ public void setCityName(String cityName) {
+ this.cityName = cityName;
+ }
+ public String getCityName() {
+ return this.cityName;
+ }
+
+ private String latitude;
+ public void setLatitude(String latitude) {
+ this.latitude = latitude;
+ }
+ public String getLatitude() {
+ return this.latitude;
+ }
+
+ private String longitude;
+ public void setLongitude(String longitude) {
+ this.longitude = longitude;
+ }
+ public String getLongitude() {
+ return this.longitude;
+ }
+
+ private String asNumber;
+ public void setAsNumber(String asNumber) {
+ this.asNumber = asNumber;
+ }
+ public String getAsNumber() {
+ return this.asNumber;
+ }
+
+ private String asName;
+ public void setAsName(String asName) {
+ this.asName = asName;
+ }
+ public String getAsName() {
+ return this.asName;
+ }
+}
+
public class LookupService {
- File geoipDir;
- File geoLite2CityBlocksCsvFile;
- File geoLite2CityLocationsCsvFile;
- File geoIPASNum2CsvFile;
+ private File geoipDir;
+ private File geoLite2CityBlocksCsvFile;
+ private File geoLite2CityLocationsCsvFile;
+ private File geoIPASNum2CsvFile;
private boolean hasAllFiles = false;
public LookupService(File geoipDir) {
this.geoipDir = geoipDir;
@@ -294,28 +361,28 @@ public class LookupService {
if (blockLocations.containsKey(blockNumber)) {
String[] parts = blockLocations.get(blockNumber).
replaceAll("\"", "").split(",", -1);
- lookupResult.countryCode = parts[3].toLowerCase();
+ lookupResult.setCountryCode(parts[3].toLowerCase());
if (parts[4].length() > 0) {
- lookupResult.countryName = parts[4];
+ lookupResult.setCountryName(parts[4]);
}
if (parts[6].length() > 0) {
- lookupResult.regionName = parts[6];
+ lookupResult.setRegionName(parts[6]);
}
if (parts[7].length() > 0) {
- lookupResult.cityName = parts[7];
+ lookupResult.setCityName(parts[7]);
}
}
}
if (addressNumberLatLong.containsKey(addressNumber)) {
String[] latLong = addressNumberLatLong.get(addressNumber);
- lookupResult.latitude = latLong[0];
- lookupResult.longitude = latLong[1];
+ lookupResult.setLatitude(latLong[0]);
+ lookupResult.setLongitude(latLong[1]);
}
if (addressNumberASN.containsKey(addressNumber)) {
String[] parts = addressNumberASN.get(addressNumber).split(" ",
2);
- lookupResult.aSNumber = parts[0];
- lookupResult.aSName = parts[1];
+ lookupResult.setAsNumber(parts[0]);
+ lookupResult.setAsName(parts[1]);
}
lookupResults.put(addressString, lookupResult);
}
@@ -327,18 +394,7 @@ public class LookupService {
return lookupResults;
}
- class LookupResult {
- String countryCode;
- String countryName;
- String regionName;
- String cityName;
- String latitude;
- String longitude;
- String aSNumber;
- String aSName;
- }
-
- int addressesLookedUp = 0, addressesResolved = 0;
+ private int addressesLookedUp = 0, addressesResolved = 0;
public String getStatsString() {
StringBuilder sb = new StringBuilder();
diff --git a/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java b/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java
index d6cd2ec..2cf5061 100644
--- a/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java
+++ b/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java
@@ -20,7 +20,6 @@ import org.torproject.descriptor.Descriptor;
import org.torproject.descriptor.NetworkStatusEntry;
import org.torproject.descriptor.RelayNetworkStatusConsensus;
import org.torproject.descriptor.ServerDescriptor;
-import org.torproject.onionoo.LookupService.LookupResult;
public class NodeDetailsStatusUpdater implements DescriptorListener,
StatusUpdater {
@@ -245,14 +244,14 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
String addressString = node.getAddress();
if (lookupResults.containsKey(addressString)) {
LookupResult lookupResult = lookupResults.get(addressString);
- node.setCountryCode(lookupResult.countryCode);
- node.setCountryName(lookupResult.countryName);
- node.setRegionName(lookupResult.regionName);
- node.setCityName(lookupResult.cityName);
- node.setLatitude(lookupResult.latitude);
- node.setLongitude(lookupResult.longitude);
- node.setASNumber(lookupResult.aSNumber);
- node.setASName(lookupResult.aSName);
+ node.setCountryCode(lookupResult.getCountryCode());
+ node.setCountryName(lookupResult.getCountryName());
+ node.setRegionName(lookupResult.getRegionName());
+ node.setCityName(lookupResult.getCityName());
+ node.setLatitude(lookupResult.getLatitude());
+ node.setLongitude(lookupResult.getLongitude());
+ node.setASNumber(lookupResult.getAsNumber());
+ node.setASName(lookupResult.getAsName());
}
}
}
@@ -290,7 +289,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
String publishedDateTime =
DateTimeHelper.format(descriptor.getPublishedMillis());
if (detailsStatus != null) {
- String detailsString = detailsStatus.documentString;
+ String detailsString = detailsStatus.getDocumentString();
String descPublishedLine = "\"desc_published\":\""
+ publishedDateTime + "\",";
Scanner s = new Scanner(detailsString);
@@ -363,7 +362,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
sb.append(",\n\"hibernating\":true");
}
detailsStatus = new DetailsStatus();
- detailsStatus.documentString = sb.toString();
+ detailsStatus.setDocumentString(sb.toString());
this.documentStore.store(detailsStatus, fingerprint);
}
@@ -376,7 +375,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
DateTimeHelper.format(descriptor.getPublishedMillis());
String poolAssignmentLine = null;
if (detailsStatus != null) {
- String detailsString = detailsStatus.documentString;
+ String detailsString = detailsStatus.getDocumentString();
String descPublishedLine = "\"desc_published\":\""
+ publishedDateTime + "\",";
Scanner s = new Scanner(detailsString);
@@ -407,7 +406,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
sb.append(",\n" + poolAssignmentLine);
}
detailsStatus = new DetailsStatus();
- detailsStatus.documentString = sb.toString();
+ detailsStatus.setDocumentString(sb.toString());
this.documentStore.store(detailsStatus, fingerprint);
}
@@ -425,7 +424,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
DetailsStatus detailsStatus = this.documentStore.retrieve(
DetailsStatus.class, false, fingerprint);
if (detailsStatus != null) {
- String detailsString = detailsStatus.documentString;
+ String detailsString = detailsStatus.getDocumentString();
Scanner s = new Scanner(detailsString);
int linesWritten = 0;
boolean endsWithComma = false;
@@ -443,7 +442,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
}
sb.append("\"pool_assignment\":\"" + details + "\"");
detailsStatus = new DetailsStatus();
- detailsStatus.documentString = sb.toString();
+ detailsStatus.setDocumentString(sb.toString());
this.documentStore.store(detailsStatus, fingerprint);
}
}
@@ -535,7 +534,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
DetailsStatus.class, false, fingerprint);
if (detailsStatus != null) {
double advertisedBandwidth = -1.0;
- String detailsString = detailsStatus.documentString;
+ String detailsString = detailsStatus.getDocumentString();
Scanner s = new Scanner(detailsString);
while (s.hasNextLine()) {
String line = s.nextLine();
diff --git a/src/org/torproject/onionoo/NodeStatus.java b/src/org/torproject/onionoo/NodeStatus.java
index da39a5b..8e89682 100644
--- a/src/org/torproject/onionoo/NodeStatus.java
+++ b/src/org/torproject/onionoo/NodeStatus.java
@@ -19,41 +19,285 @@ import org.apache.commons.codec.digest.DigestUtils;
/* Store search data of a single relay that was running in the past seven
* days. */
public class NodeStatus extends Document {
+
private boolean isRelay;
+ public boolean isRelay() {
+ return this.isRelay;
+ }
+
private String fingerprint;
+ public String getFingerprint() {
+ return this.fingerprint;
+ }
+
private String hashedFingerprint;
+ public String getHashedFingerprint() {
+ return this.hashedFingerprint;
+ }
+
private String nickname;
+ public String getNickname() {
+ return this.nickname;
+ }
+
private String address;
+ public String getAddress() {
+ return this.address;
+ }
+
private SortedSet<String> orAddresses;
private SortedSet<String> orAddressesAndPorts;
+ public SortedSet<String> getOrAddresses() {
+ return new TreeSet<String>(this.orAddresses);
+ }
+ public void addOrAddressAndPort(String orAddressAndPort) {
+ if (!orAddressAndPort.contains(":")) {
+ System.err.println("Illegal OR address:port '" + orAddressAndPort
+ + "'. Exiting.");
+ System.exit(1);
+ } else if (orAddressAndPort.length() > 0) {
+ String orAddress = orAddressAndPort.substring(0,
+ orAddressAndPort.lastIndexOf(':'));
+ if (this.exitAddresses.contains(orAddress)) {
+ this.exitAddresses.remove(orAddress);
+ }
+ this.orAddresses.add(orAddress);
+ this.orAddressesAndPorts.add(orAddressAndPort);
+ }
+ }
+ public SortedSet<String> getOrAddressesAndPorts() {
+ return new TreeSet<String>(this.orAddressesAndPorts);
+ }
+
private SortedSet<String> exitAddresses;
+ public void addExitAddress(String exitAddress) {
+ if (exitAddress.length() > 0 && !this.address.equals(exitAddress) &&
+ !this.orAddresses.contains(exitAddress)) {
+ this.exitAddresses.add(exitAddress);
+ }
+ }
+ public SortedSet<String> getExitAddresses() {
+ return new TreeSet<String>(this.exitAddresses);
+ }
+
private String latitude;
+ public void setLatitude(String latitude) {
+ this.latitude = latitude;
+ }
+ public String getLatitude() {
+ return this.latitude;
+ }
+
private String longitude;
+ public void setLongitude(String longitude) {
+ this.longitude = longitude;
+ }
+ public String getLongitude() {
+ return this.longitude;
+ }
+
private String countryCode;
+ public void setCountryCode(String countryCode) {
+ this.countryCode = countryCode;
+ }
+ public String getCountryCode() {
+ return this.countryCode;
+ }
+
private String countryName;
+ public void setCountryName(String countryName) {
+ this.countryName = countryName;
+ }
+ public String getCountryName() {
+ return this.countryName;
+ }
+
private String regionName;
+ public void setRegionName(String regionName) {
+ this.regionName = regionName;
+ }
+ public String getRegionName() {
+ return this.regionName;
+ }
+
private String cityName;
+ public void setCityName(String cityName) {
+ this.cityName = cityName;
+ }
+ public String getCityName() {
+ return this.cityName;
+ }
+
private String aSName;
+ public void setASName(String aSName) {
+ this.aSName = aSName;
+ }
+ public String getASName() {
+ return this.aSName;
+ }
+
private String aSNumber;
+ public void setASNumber(String aSNumber) {
+ this.aSNumber = aSNumber;
+ }
+ public String getASNumber() {
+ return this.aSNumber;
+ }
+
private long firstSeenMillis;
+ public long getFirstSeenMillis() {
+ return this.firstSeenMillis;
+ }
+
private long lastSeenMillis;
+ public long getLastSeenMillis() {
+ return this.lastSeenMillis;
+ }
+
private int orPort;
+ public int getOrPort() {
+ return this.orPort;
+ }
+
private int dirPort;
+ public int getDirPort() {
+ return this.dirPort;
+ }
+
private SortedSet<String> relayFlags;
+ public SortedSet<String> getRelayFlags() {
+ return this.relayFlags;
+ }
+
private long consensusWeight;
+ public long getConsensusWeight() {
+ return this.consensusWeight;
+ }
+
private boolean running;
+ public void setRunning(boolean running) {
+ this.running = running;
+ }
+ public boolean getRunning() {
+ return this.running;
+ }
+
private String hostName;
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+ public String getHostName() {
+ return this.hostName;
+ }
+
private long lastRdnsLookup = -1L;
+ public void setLastRdnsLookup(long lastRdnsLookup) {
+ this.lastRdnsLookup = lastRdnsLookup;
+ }
+ public long getLastRdnsLookup() {
+ return this.lastRdnsLookup;
+ }
+
private double advertisedBandwidthFraction = -1.0;
+ public void setAdvertisedBandwidthFraction(
+ double advertisedBandwidthFraction) {
+ this.advertisedBandwidthFraction = advertisedBandwidthFraction;
+ }
+ public double getAdvertisedBandwidthFraction() {
+ return this.advertisedBandwidthFraction;
+ }
+
private double consensusWeightFraction = -1.0;
+ public void setConsensusWeightFraction(double consensusWeightFraction) {
+ this.consensusWeightFraction = consensusWeightFraction;
+ }
+ public double getConsensusWeightFraction() {
+ return this.consensusWeightFraction;
+ }
+
private double guardProbability = -1.0;
+ public void setGuardProbability(double guardProbability) {
+ this.guardProbability = guardProbability;
+ }
+ public double getGuardProbability() {
+ return this.guardProbability;
+ }
+
private double middleProbability = -1.0;
+ public void setMiddleProbability(double middleProbability) {
+ this.middleProbability = middleProbability;
+ }
+ public double getMiddleProbability() {
+ return this.middleProbability;
+ }
+
private double exitProbability = -1.0;
+ public void setExitProbability(double exitProbability) {
+ this.exitProbability = exitProbability;
+ }
+ public double getExitProbability() {
+ return this.exitProbability;
+ }
+
private String defaultPolicy;
+ public String getDefaultPolicy() {
+ return this.defaultPolicy;
+ }
+
private String portList;
+ public String getPortList() {
+ return this.portList;
+ }
+
private SortedMap<Long, Set<String>> lastAddresses;
+ public SortedMap<Long, Set<String>> getLastAddresses() {
+ return this.lastAddresses == null ? null :
+ new TreeMap<Long, Set<String>>(this.lastAddresses);
+ }
+ public long getLastChangedOrAddress() {
+ long lastChangedAddressesMillis = -1L;
+ if (this.lastAddresses != null) {
+ Set<String> lastAddresses = null;
+ for (Map.Entry<Long, Set<String>> e : this.lastAddresses.entrySet()) {
+ if (lastAddresses != null) {
+ for (String address : e.getValue()) {
+ if (!lastAddresses.contains(address)) {
+ return lastChangedAddressesMillis;
+ }
+ }
+ }
+ lastChangedAddressesMillis = e.getKey();
+ lastAddresses = e.getValue();
+ }
+ }
+ return lastChangedAddressesMillis;
+ }
+
private String contact;
+ public void setContact(String contact) {
+ if (contact == null) {
+ this.contact = null;
+ } else {
+ StringBuilder sb = new StringBuilder();
+ for (char c : contact.toLowerCase().toCharArray()) {
+ if (c >= 32 && c < 127) {
+ sb.append(c);
+ } else {
+ sb.append(" ");
+ }
+ }
+ this.contact = sb.toString();
+ }
+ }
+ public String getContact() {
+ return this.contact;
+ }
+
private Boolean recommendedVersion;
+ public Boolean getRecommendedVersion() {
+ return this.recommendedVersion;
+ }
+
public NodeStatus(boolean isRelay, String nickname, String fingerprint,
String address, SortedSet<String> orAddressesAndPorts,
SortedSet<String> exitAddresses, long lastSeenMillis, int orPort,
@@ -259,7 +503,7 @@ public class NodeStatus extends Document {
this.lastAddresses.putAll(newNodeStatus.lastAddresses);
}
this.firstSeenMillis = Math.min(newNodeStatus.firstSeenMillis,
- this.getFirstSeenMillis());
+ this.firstSeenMillis);
}
public String toString() {
@@ -315,215 +559,5 @@ public class NodeStatus extends Document {
this.recommendedVersion ? "true" : "false"));
return sb.toString();
}
-
- public boolean isRelay() {
- return this.isRelay;
- }
- public String getFingerprint() {
- return this.fingerprint;
- }
- public String getHashedFingerprint() {
- return this.hashedFingerprint;
- }
- public String getNickname() {
- return this.nickname;
- }
- public String getAddress() {
- return this.address;
- }
- public SortedSet<String> getOrAddresses() {
- return new TreeSet<String>(this.orAddresses);
- }
- public void addOrAddressAndPort(String orAddressAndPort) {
- if (!orAddressAndPort.contains(":")) {
- System.err.println("Illegal OR address:port '" + orAddressAndPort
- + "'. Exiting.");
- System.exit(1);
- } else if (orAddressAndPort.length() > 0) {
- String orAddress = orAddressAndPort.substring(0,
- orAddressAndPort.lastIndexOf(':'));
- if (this.exitAddresses.contains(orAddress)) {
- this.exitAddresses.remove(orAddress);
- }
- this.orAddresses.add(orAddress);
- this.orAddressesAndPorts.add(orAddressAndPort);
- }
- }
- public SortedSet<String> getOrAddressesAndPorts() {
- return new TreeSet<String>(this.orAddressesAndPorts);
- }
- public void addExitAddress(String exitAddress) {
- if (exitAddress.length() > 0 && !this.address.equals(exitAddress) &&
- !this.orAddresses.contains(exitAddress)) {
- this.exitAddresses.add(exitAddress);
- }
- }
- public SortedSet<String> getExitAddresses() {
- return new TreeSet<String>(this.exitAddresses);
- }
- public void setLatitude(String latitude) {
- this.latitude = latitude;
- }
- public String getLatitude() {
- return this.latitude;
- }
- public void setLongitude(String longitude) {
- this.longitude = longitude;
- }
- public String getLongitude() {
- return this.longitude;
- }
- public void setCountryCode(String countryCode) {
- this.countryCode = countryCode;
- }
- public String getCountryCode() {
- return this.countryCode;
- }
- public void setCountryName(String countryName) {
- this.countryName = countryName;
- }
- public String getCountryName() {
- return this.countryName;
- }
- public void setRegionName(String regionName) {
- this.regionName = regionName;
- }
- public String getRegionName() {
- return this.regionName;
- }
- public void setCityName(String cityName) {
- this.cityName = cityName;
- }
- public String getCityName() {
- return this.cityName;
- }
- public void setASNumber(String aSNumber) {
- this.aSNumber = aSNumber;
- }
- public String getASNumber() {
- return this.aSNumber;
- }
- public void setASName(String aSName) {
- this.aSName = aSName;
- }
- public String getASName() {
- return this.aSName;
- }
- public long getFirstSeenMillis() {
- return this.firstSeenMillis;
- }
- public long getLastSeenMillis() {
- return this.lastSeenMillis;
- }
- public int getOrPort() {
- return this.orPort;
- }
- public int getDirPort() {
- return this.dirPort;
- }
- public SortedSet<String> getRelayFlags() {
- return this.relayFlags;
- }
- public long getConsensusWeight() {
- return this.consensusWeight;
- }
- public void setRunning(boolean running) {
- this.running = running;
- }
- public boolean getRunning() {
- return this.running;
- }
- public void setHostName(String hostName) {
- this.hostName = hostName;
- }
- public String getHostName() {
- return this.hostName;
- }
- public void setLastRdnsLookup(long lastRdnsLookup) {
- this.lastRdnsLookup = lastRdnsLookup;
- }
- public long getLastRdnsLookup() {
- return this.lastRdnsLookup;
- }
- public void setAdvertisedBandwidthFraction(
- double advertisedBandwidthFraction) {
- this.advertisedBandwidthFraction = advertisedBandwidthFraction;
- }
- public double getAdvertisedBandwidthFraction() {
- return this.advertisedBandwidthFraction;
- }
- public void setConsensusWeightFraction(double consensusWeightFraction) {
- this.consensusWeightFraction = consensusWeightFraction;
- }
- public double getConsensusWeightFraction() {
- return this.consensusWeightFraction;
- }
- public void setGuardProbability(double guardProbability) {
- this.guardProbability = guardProbability;
- }
- public double getGuardProbability() {
- return this.guardProbability;
- }
- public void setMiddleProbability(double middleProbability) {
- this.middleProbability = middleProbability;
- }
- public double getMiddleProbability() {
- return this.middleProbability;
- }
- public void setExitProbability(double exitProbability) {
- this.exitProbability = exitProbability;
- }
- public double getExitProbability() {
- return this.exitProbability;
- }
- public String getDefaultPolicy() {
- return this.defaultPolicy;
- }
- public String getPortList() {
- return this.portList;
- }
- public SortedMap<Long, Set<String>> getLastAddresses() {
- return this.lastAddresses == null ? null :
- new TreeMap<Long, Set<String>>(this.lastAddresses);
- }
- public long getLastChangedOrAddress() {
- long lastChangedAddressesMillis = -1L;
- if (this.lastAddresses != null) {
- Set<String> lastAddresses = null;
- for (Map.Entry<Long, Set<String>> e : this.lastAddresses.entrySet()) {
- if (lastAddresses != null) {
- for (String address : e.getValue()) {
- if (!lastAddresses.contains(address)) {
- return lastChangedAddressesMillis;
- }
- }
- }
- lastChangedAddressesMillis = e.getKey();
- lastAddresses = e.getValue();
- }
- }
- return lastChangedAddressesMillis;
- }
- public void setContact(String contact) {
- if (contact == null) {
- this.contact = null;
- } else {
- StringBuilder sb = new StringBuilder();
- for (char c : contact.toLowerCase().toCharArray()) {
- if (c >= 32 && c < 127) {
- sb.append(c);
- } else {
- sb.append(" ");
- }
- }
- this.contact = sb.toString();
- }
- }
- public String getContact() {
- return this.contact;
- }
- public Boolean getRecommendedVersion() {
- return this.recommendedVersion;
- }
}
diff --git a/src/org/torproject/onionoo/ResponseBuilder.java b/src/org/torproject/onionoo/ResponseBuilder.java
index bde8961..080af52 100644
--- a/src/org/torproject/onionoo/ResponseBuilder.java
+++ b/src/org/torproject/onionoo/ResponseBuilder.java
@@ -49,8 +49,9 @@ public class ResponseBuilder {
long newSummaryFileLastModified = -1L;
UpdateStatus updateStatus = documentStore.retrieve(UpdateStatus.class,
false);
- if (updateStatus != null && updateStatus.documentString != null) {
- String updateString = updateStatus.documentString;
+ if (updateStatus != null &&
+ updateStatus.getDocumentString() != null) {
+ String updateString = updateStatus.getDocumentString();
try {
newSummaryFileLastModified = Long.parseLong(updateString.trim());
} catch (NumberFormatException e) {
@@ -806,9 +807,9 @@ public class ResponseBuilder {
DetailsDocument detailsDocument = documentStore.retrieve(
DetailsDocument.class, false, fingerprint);
if (detailsDocument != null &&
- detailsDocument.documentString != null) {
+ detailsDocument.getDocumentString() != null) {
StringBuilder sb = new StringBuilder();
- Scanner s = new Scanner(detailsDocument.documentString);
+ Scanner s = new Scanner(detailsDocument.getDocumentString());
sb.append("{");
if (s.hasNextLine()) {
/* Skip version line. */
@@ -876,8 +877,8 @@ public class ResponseBuilder {
BandwidthDocument bandwidthDocument = documentStore.retrieve(
BandwidthDocument.class, false, fingerprint);
if (bandwidthDocument != null &&
- bandwidthDocument.documentString != null) {
- String bandwidthLines = bandwidthDocument.documentString;
+ bandwidthDocument.getDocumentString() != null) {
+ String bandwidthLines = bandwidthDocument.getDocumentString();
bandwidthLines = bandwidthLines.substring(0,
bandwidthLines.length() - 1);
return bandwidthLines;
@@ -900,8 +901,8 @@ public class ResponseBuilder {
WeightsDocument weightsDocument = documentStore.retrieve(
WeightsDocument.class, false, fingerprint);
if (weightsDocument != null &&
- weightsDocument.documentString != null) {
- String weightsLines = weightsDocument.documentString;
+ weightsDocument.getDocumentString() != null) {
+ String weightsLines = weightsDocument.getDocumentString();
weightsLines = weightsLines.substring(0, weightsLines.length() - 1);
return weightsLines;
} else {
@@ -923,8 +924,8 @@ public class ResponseBuilder {
ClientsDocument clientsDocument = documentStore.retrieve(
ClientsDocument.class, false, fingerprint);
if (clientsDocument != null &&
- clientsDocument.documentString != null) {
- String clientsLines = clientsDocument.documentString;
+ clientsDocument.getDocumentString() != null) {
+ String clientsLines = clientsDocument.getDocumentString();
clientsLines = clientsLines.substring(0, clientsLines.length() - 1);
return clientsLines;
} else {
@@ -949,8 +950,8 @@ public class ResponseBuilder {
UptimeDocument uptimeDocument = documentStore.retrieve(
UptimeDocument.class, false, fingerprint);
if (uptimeDocument != null &&
- uptimeDocument.documentString != null) {
- String uptimeLines = uptimeDocument.documentString;
+ uptimeDocument.getDocumentString() != null) {
+ String uptimeLines = uptimeDocument.getDocumentString();
uptimeLines = uptimeLines.substring(0, uptimeLines.length() - 1);
return uptimeLines;
} else {
diff --git a/src/org/torproject/onionoo/ReverseDomainNameResolver.java b/src/org/torproject/onionoo/ReverseDomainNameResolver.java
index 7f14460..e762811 100644
--- a/src/org/torproject/onionoo/ReverseDomainNameResolver.java
+++ b/src/org/torproject/onionoo/ReverseDomainNameResolver.java
@@ -55,9 +55,9 @@ public class ReverseDomainNameResolver {
}
private class RdnsLookupRequest extends Thread {
- RdnsLookupWorker parent;
- String address, hostName;
- long lookupStartedMillis = -1L, lookupCompletedMillis = -1L;
+ private RdnsLookupWorker parent;
+ private String address, hostName;
+ private long lookupStartedMillis = -1L, lookupCompletedMillis = -1L;
public RdnsLookupRequest(RdnsLookupWorker parent, String address) {
this.parent = parent;
this.address = address;
diff --git a/src/org/torproject/onionoo/UptimeDocumentWriter.java b/src/org/torproject/onionoo/UptimeDocumentWriter.java
index 06fde0f..a7b1bba 100644
--- a/src/org/torproject/onionoo/UptimeDocumentWriter.java
+++ b/src/org/torproject/onionoo/UptimeDocumentWriter.java
@@ -53,9 +53,9 @@ public class UptimeDocumentWriter implements FingerprintListener,
if (uptimeStatus == null) {
return;
}
- SortedSet<UptimeHistory> knownStatuses = uptimeStatus.history;
+ SortedSet<UptimeHistory> knownStatuses = uptimeStatus.getHistory();
for (UptimeHistory status : knownStatuses) {
- if (status.relay) {
+ if (status.isRelay()) {
knownRelayStatuses.add(status);
} else {
knownBridgeStatuses.add(status);
@@ -77,10 +77,10 @@ public class UptimeDocumentWriter implements FingerprintListener,
UptimeStatus uptimeStatus = this.documentStore.retrieve(
UptimeStatus.class, true, fingerprint);
if (uptimeStatus != null) {
- SortedSet<UptimeHistory> history = uptimeStatus.history;
+ SortedSet<UptimeHistory> history = uptimeStatus.getHistory();
UptimeDocument uptimeDocument = new UptimeDocument();
- uptimeDocument.documentString = this.formatHistoryString(relay,
- fingerprint, history, knownStatuses);
+ uptimeDocument.setDocumentString(this.formatHistoryString(relay,
+ fingerprint, history, knownStatuses));
this.documentStore.store(uptimeDocument, fingerprint);
this.writtenDocuments++;
}
@@ -142,15 +142,15 @@ public class UptimeDocumentWriter implements FingerprintListener,
/ dataPointInterval) * dataPointInterval;
int statusHours = 0;
for (UptimeHistory hist : knownStatuses) {
- if (hist.relay != relay) {
+ if (hist.isRelay() != relay) {
continue;
}
- long histEndMillis = hist.startMillis + DateTimeHelper.ONE_HOUR
- * hist.uptimeHours;
+ long histEndMillis = hist.getStartMillis() + DateTimeHelper.ONE_HOUR
+ * hist.getUptimeHours();
if (histEndMillis < intervalStartMillis) {
continue;
}
- while (hist.startMillis >= intervalStartMillis
+ while (hist.getStartMillis() >= intervalStartMillis
+ dataPointInterval) {
statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
? statusHours : -1);
@@ -159,15 +159,16 @@ public class UptimeDocumentWriter implements FingerprintListener,
}
while (histEndMillis >= intervalStartMillis + dataPointInterval) {
statusHours += (int) ((intervalStartMillis + dataPointInterval
- - Math.max(hist.startMillis, intervalStartMillis))
+ - Math.max(hist.getStartMillis(), intervalStartMillis))
/ DateTimeHelper.ONE_HOUR);
statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
? statusHours : -1);
statusHours = 0;
intervalStartMillis += dataPointInterval;
}
- statusHours += (int) ((histEndMillis - Math.max(hist.startMillis,
- intervalStartMillis)) / DateTimeHelper.ONE_HOUR);
+ statusHours += (int) ((histEndMillis - Math.max(
+ hist.getStartMillis(), intervalStartMillis))
+ / DateTimeHelper.ONE_HOUR);
}
statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
? statusHours : -1);
@@ -177,18 +178,18 @@ public class UptimeDocumentWriter implements FingerprintListener,
int uptimeHours = 0;
long firstStatusStartMillis = -1L;
for (UptimeHistory hist : history) {
- if (hist.relay != relay) {
+ if (hist.isRelay() != relay) {
continue;
}
if (firstStatusStartMillis < 0L) {
- firstStatusStartMillis = hist.startMillis;
+ firstStatusStartMillis = hist.getStartMillis();
}
- long histEndMillis = hist.startMillis + DateTimeHelper.ONE_HOUR
- * hist.uptimeHours;
+ long histEndMillis = hist.getStartMillis() + DateTimeHelper.ONE_HOUR
+ * hist.getUptimeHours();
if (histEndMillis < intervalStartMillis) {
continue;
}
- while (hist.startMillis >= intervalStartMillis
+ while (hist.getStartMillis() >= intervalStartMillis
+ dataPointInterval) {
if (firstStatusStartMillis < intervalStartMillis
+ dataPointInterval) {
@@ -201,14 +202,15 @@ public class UptimeDocumentWriter implements FingerprintListener,
}
while (histEndMillis >= intervalStartMillis + dataPointInterval) {
uptimeHours += (int) ((intervalStartMillis + dataPointInterval
- - Math.max(hist.startMillis, intervalStartMillis))
+ - Math.max(hist.getStartMillis(), intervalStartMillis))
/ DateTimeHelper.ONE_HOUR);
uptimeDataPoints.add(uptimeHours);
uptimeHours = 0;
intervalStartMillis += dataPointInterval;
}
- uptimeHours += (int) ((histEndMillis - Math.max(hist.startMillis,
- intervalStartMillis)) / DateTimeHelper.ONE_HOUR);
+ uptimeHours += (int) ((histEndMillis - Math.max(
+ hist.getStartMillis(), intervalStartMillis))
+ / DateTimeHelper.ONE_HOUR);
}
uptimeDataPoints.add(uptimeHours);
List<Double> dataPoints = new ArrayList<Double>();
diff --git a/src/org/torproject/onionoo/UptimeStatus.java b/src/org/torproject/onionoo/UptimeStatus.java
index 0eb9dde..2e688b8 100644
--- a/src/org/torproject/onionoo/UptimeStatus.java
+++ b/src/org/torproject/onionoo/UptimeStatus.java
@@ -9,11 +9,20 @@ import java.util.TreeSet;
class UptimeHistory
implements Comparable<UptimeHistory> {
- boolean relay;
+ private boolean relay;
+ public boolean isRelay() {
+ return this.relay;
+ }
- long startMillis;
+ private long startMillis;
+ public long getStartMillis() {
+ return this.startMillis;
+ }
- int uptimeHours;
+ private int uptimeHours;
+ public int getUptimeHours() {
+ return this.uptimeHours;
+ }
UptimeHistory(boolean relay, long startMillis,
int uptimeHours) {
@@ -86,7 +95,13 @@ class UptimeHistory
class UptimeStatus extends Document {
- SortedSet<UptimeHistory> history = new TreeSet<UptimeHistory>();
+ private SortedSet<UptimeHistory> history = new TreeSet<UptimeHistory>();
+ public void setHistory(SortedSet<UptimeHistory> history) {
+ this.history = history;
+ }
+ public SortedSet<UptimeHistory> getHistory() {
+ return this.history;
+ }
public void fromDocumentString(String documentString) {
Scanner s = new Scanner(documentString);
diff --git a/src/org/torproject/onionoo/UptimeStatusUpdater.java b/src/org/torproject/onionoo/UptimeStatusUpdater.java
index 7bf20e5..f524ea3 100644
--- a/src/org/torproject/onionoo/UptimeStatusUpdater.java
+++ b/src/org/torproject/onionoo/UptimeStatusUpdater.java
@@ -126,21 +126,21 @@ public class UptimeStatusUpdater implements DescriptorListener,
private void addToHistory(UptimeStatus uptimeStatus, boolean relay,
SortedSet<Long> newIntervals) {
- SortedSet<UptimeHistory> history = uptimeStatus.history;
+ SortedSet<UptimeHistory> history = uptimeStatus.getHistory();
for (long startMillis : newIntervals) {
UptimeHistory interval = new UptimeHistory(relay, startMillis, 1);
if (!history.headSet(interval).isEmpty()) {
UptimeHistory prev = history.headSet(interval).last();
- if (prev.relay == interval.relay &&
- prev.startMillis + DateTimeHelper.ONE_HOUR
- * prev.uptimeHours > interval.startMillis) {
+ if (prev.isRelay() == interval.isRelay() &&
+ prev.getStartMillis() + DateTimeHelper.ONE_HOUR
+ * prev.getUptimeHours() > interval.getStartMillis()) {
continue;
}
}
if (!history.tailSet(interval).isEmpty()) {
UptimeHistory next = history.tailSet(interval).first();
- if (next.relay == interval.relay &&
- next.startMillis < interval.startMillis
+ if (next.isRelay() == interval.isRelay() &&
+ next.getStartMillis() < interval.getStartMillis()
+ DateTimeHelper.ONE_HOUR) {
continue;
}
@@ -150,15 +150,15 @@ public class UptimeStatusUpdater implements DescriptorListener,
}
private void compressHistory(UptimeStatus uptimeStatus) {
- SortedSet<UptimeHistory> history = uptimeStatus.history;
+ SortedSet<UptimeHistory> history = uptimeStatus.getHistory();
SortedSet<UptimeHistory> compressedHistory =
new TreeSet<UptimeHistory>();
UptimeHistory lastInterval = null;
for (UptimeHistory interval : history) {
if (lastInterval != null &&
- lastInterval.startMillis + DateTimeHelper.ONE_HOUR
- * lastInterval.uptimeHours == interval.startMillis &&
- lastInterval.relay == interval.relay) {
+ lastInterval.getStartMillis() + DateTimeHelper.ONE_HOUR
+ * lastInterval.getUptimeHours() == interval.getStartMillis() &&
+ lastInterval.isRelay() == interval.isRelay()) {
lastInterval.addUptime(interval);
} else {
if (lastInterval != null) {
@@ -170,7 +170,7 @@ public class UptimeStatusUpdater implements DescriptorListener,
if (lastInterval != null) {
compressedHistory.add(lastInterval);
}
- uptimeStatus.history = compressedHistory;
+ uptimeStatus.setHistory(compressedHistory);
}
private void writeHistory(String fingerprint,
diff --git a/src/org/torproject/onionoo/WeightsDocumentWriter.java b/src/org/torproject/onionoo/WeightsDocumentWriter.java
index 83fe872..8dcca0a 100644
--- a/src/org/torproject/onionoo/WeightsDocumentWriter.java
+++ b/src/org/torproject/onionoo/WeightsDocumentWriter.java
@@ -56,10 +56,10 @@ public class WeightsDocumentWriter implements FingerprintListener,
if (weightsStatus == null) {
continue;
}
- SortedMap<long[], double[]> history = weightsStatus.history;
+ SortedMap<long[], double[]> history = weightsStatus.getHistory();
WeightsDocument weightsDocument = new WeightsDocument();
- weightsDocument.documentString = this.formatHistoryString(
- fingerprint, history);
+ weightsDocument.setDocumentString(this.formatHistoryString(
+ fingerprint, history));
this.documentStore.store(weightsDocument, fingerprint);
}
}
diff --git a/src/org/torproject/onionoo/WeightsStatus.java b/src/org/torproject/onionoo/WeightsStatus.java
index 93f3087..872fd00 100644
--- a/src/org/torproject/onionoo/WeightsStatus.java
+++ b/src/org/torproject/onionoo/WeightsStatus.java
@@ -9,15 +9,24 @@ import java.util.TreeMap;
class WeightsStatus extends Document {
- SortedMap<long[], double[]> history = new TreeMap<long[], double[]>(
- new Comparator<long[]>() {
+ private SortedMap<long[], double[]> history =
+ new TreeMap<long[], double[]>(new Comparator<long[]>() {
public int compare(long[] a, long[] b) {
return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
}
});
+ public void setHistory(SortedMap<long[], double[]> history) {
+ this.history = history;
+ }
+ public SortedMap<long[], double[]> getHistory() {
+ return this.history;
+ }
- Map<String, Integer> advertisedBandwidths =
+ private Map<String, Integer> advertisedBandwidths =
new HashMap<String, Integer>();
+ public Map<String, Integer> getAdvertisedBandwidths() {
+ return this.advertisedBandwidths;
+ }
public void fromDocumentString(String documentString) {
Scanner s = new Scanner(documentString);
diff --git a/src/org/torproject/onionoo/WeightsStatusUpdater.java b/src/org/torproject/onionoo/WeightsStatusUpdater.java
index fce1c3e..1e5d559 100644
--- a/src/org/torproject/onionoo/WeightsStatusUpdater.java
+++ b/src/org/torproject/onionoo/WeightsStatusUpdater.java
@@ -179,9 +179,9 @@ public class WeightsStatusUpdater implements DescriptorListener,
new HashSet<String>());
}
this.descriptorDigestsByFingerprint.get(fingerprint).addAll(
- weightsStatus.advertisedBandwidths.keySet());
+ weightsStatus.getAdvertisedBandwidths().keySet());
this.advertisedBandwidths.putAll(
- weightsStatus.advertisedBandwidths);
+ weightsStatus.getAdvertisedBandwidths());
}
}
if (this.advertisedBandwidths.containsKey(
@@ -245,7 +245,7 @@ public class WeightsStatusUpdater implements DescriptorListener,
if (weightsStatus == null) {
weightsStatus = new WeightsStatus();
}
- SortedMap<long[], double[]> history = weightsStatus.history;
+ SortedMap<long[], double[]> history = weightsStatus.getHistory();
long[] interval = new long[] { validAfterMillis, freshUntilMillis };
if ((history.headMap(interval).isEmpty() ||
history.headMap(interval).lastKey()[1] <= validAfterMillis) &&
@@ -267,7 +267,7 @@ public class WeightsStatusUpdater implements DescriptorListener,
if (this.advertisedBandwidths.containsKey(descriptorDigest)) {
int advertisedBandwidth =
this.advertisedBandwidths.get(descriptorDigest);
- weightsStatus.advertisedBandwidths.put(descriptorDigest,
+ weightsStatus.getAdvertisedBandwidths().put(descriptorDigest,
advertisedBandwidth);
}
}
@@ -275,7 +275,7 @@ public class WeightsStatusUpdater implements DescriptorListener,
}
private void compressHistory(WeightsStatus weightsStatus) {
- SortedMap<long[], double[]> history = weightsStatus.history;
+ SortedMap<long[], double[]> history = weightsStatus.getHistory();
SortedMap<long[], double[]> compressedHistory =
new TreeMap<long[], double[]>(history.comparator());
long lastStartMillis = 0L, lastEndMillis = 0L;
@@ -332,7 +332,7 @@ public class WeightsStatusUpdater implements DescriptorListener,
compressedHistory.put(new long[] { lastStartMillis, lastEndMillis },
lastWeights);
}
- weightsStatus.history = compressedHistory;
+ weightsStatus.setHistory(compressedHistory);
}
private void updateWeightsStatuses() {
diff --git a/test/org/torproject/onionoo/DummyDocumentStore.java b/test/org/torproject/onionoo/DummyDocumentStore.java
index 0fce5d9..2f32833 100644
--- a/test/org/torproject/onionoo/DummyDocumentStore.java
+++ b/test/org/torproject/onionoo/DummyDocumentStore.java
@@ -51,7 +51,7 @@ public class DummyDocumentStore extends DocumentStore {
boolean parse) {
if (documentType.equals(UpdateStatus.class)) {
UpdateStatus updateStatus = new UpdateStatus();
- updateStatus.documentString = String.valueOf(this.lastModified);
+ updateStatus.setDocumentString(String.valueOf(this.lastModified));
return documentType.cast(updateStatus);
}
throw new RuntimeException("Not implemented.");
diff --git a/test/org/torproject/onionoo/LookupServiceTest.java b/test/org/torproject/onionoo/LookupServiceTest.java
index ae220f8..e12ab2a 100644
--- a/test/org/torproject/onionoo/LookupServiceTest.java
+++ b/test/org/torproject/onionoo/LookupServiceTest.java
@@ -22,7 +22,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.torproject.onionoo.LookupService.LookupResult;
public class LookupServiceTest {
@@ -121,59 +120,59 @@ public class LookupServiceTest {
this.performLookups();
if (countryCode == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).countryCode == null);
+ this.lookupResults.get(addressString).getCountryCode() == null);
} else {
assertEquals(countryCode,
- this.lookupResults.get(addressString).countryCode);
+ this.lookupResults.get(addressString).getCountryCode());
}
if (countryName == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).countryName == null);
+ this.lookupResults.get(addressString).getCountryName() == null);
} else {
assertEquals(countryName,
- this.lookupResults.get(addressString).countryName);
+ this.lookupResults.get(addressString).getCountryName());
}
if (regionName == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).regionName == null);
+ this.lookupResults.get(addressString).getRegionName() == null);
} else {
assertEquals(regionName,
- this.lookupResults.get(addressString).regionName);
+ this.lookupResults.get(addressString).getRegionName());
}
if (cityName == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).cityName == null);
+ this.lookupResults.get(addressString).getCityName() == null);
} else {
assertEquals(cityName,
- this.lookupResults.get(addressString).cityName);
+ this.lookupResults.get(addressString).getCityName());
}
if (latitude == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).latitude == null);
+ this.lookupResults.get(addressString).getLatitude() == null);
} else {
assertEquals(latitude,
- this.lookupResults.get(addressString).latitude);
+ this.lookupResults.get(addressString).getLatitude());
}
if (longitude == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).longitude == null);
+ this.lookupResults.get(addressString).getLongitude() == null);
} else {
assertEquals(longitude,
- this.lookupResults.get(addressString).longitude);
+ this.lookupResults.get(addressString).getLongitude());
}
if (aSNumber == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).aSNumber == null);
+ this.lookupResults.get(addressString).getAsNumber() == null);
} else {
assertEquals(aSNumber,
- this.lookupResults.get(addressString).aSNumber);
+ this.lookupResults.get(addressString).getAsNumber());
}
if (aSName == null) {
assertTrue(!this.lookupResults.containsKey(addressString) ||
- this.lookupResults.get(addressString).aSName == null);
+ this.lookupResults.get(addressString).getAsName() == null);
} else {
assertEquals(aSName,
- this.lookupResults.get(addressString).aSName);
+ this.lookupResults.get(addressString).getAsName());
}
}
1
0

14 Apr '14
commit 87514a284d57f02091aab8d27ddb5731ffa237e1
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Apr 8 23:39:19 2014 +0200
Make UptimeStatus smarter about itself.
---
src/org/torproject/onionoo/UptimeStatus.java | 46 +++++++++++++
.../torproject/onionoo/UptimeStatusUpdater.java | 68 ++------------------
2 files changed, 51 insertions(+), 63 deletions(-)
diff --git a/src/org/torproject/onionoo/UptimeStatus.java b/src/org/torproject/onionoo/UptimeStatus.java
index 2e688b8..61b4fe0 100644
--- a/src/org/torproject/onionoo/UptimeStatus.java
+++ b/src/org/torproject/onionoo/UptimeStatus.java
@@ -118,6 +118,52 @@ class UptimeStatus extends Document {
s.close();
}
+ public void addToHistory(boolean relay, SortedSet<Long> newIntervals) {
+ for (long startMillis : newIntervals) {
+ UptimeHistory interval = new UptimeHistory(relay, startMillis, 1);
+ if (!this.history.headSet(interval).isEmpty()) {
+ UptimeHistory prev = this.history.headSet(interval).last();
+ if (prev.isRelay() == interval.isRelay() &&
+ prev.getStartMillis() + DateTimeHelper.ONE_HOUR
+ * prev.getUptimeHours() > interval.getStartMillis()) {
+ continue;
+ }
+ }
+ if (!this.history.tailSet(interval).isEmpty()) {
+ UptimeHistory next = this.history.tailSet(interval).first();
+ if (next.isRelay() == interval.isRelay() &&
+ next.getStartMillis() < interval.getStartMillis()
+ + DateTimeHelper.ONE_HOUR) {
+ continue;
+ }
+ }
+ this.history.add(interval);
+ }
+ }
+
+ public void compressHistory() {
+ SortedSet<UptimeHistory> compressedHistory =
+ new TreeSet<UptimeHistory>();
+ UptimeHistory lastInterval = null;
+ for (UptimeHistory interval : history) {
+ if (lastInterval != null &&
+ lastInterval.getStartMillis() + DateTimeHelper.ONE_HOUR
+ * lastInterval.getUptimeHours() == interval.getStartMillis() &&
+ lastInterval.isRelay() == interval.isRelay()) {
+ lastInterval.addUptime(interval);
+ } else {
+ if (lastInterval != null) {
+ compressedHistory.add(lastInterval);
+ }
+ lastInterval = interval;
+ }
+ }
+ if (lastInterval != null) {
+ compressedHistory.add(lastInterval);
+ }
+ this.history = compressedHistory;
+ }
+
public String toDocumentString() {
StringBuilder sb = new StringBuilder();
for (UptimeHistory interval : this.history) {
diff --git a/src/org/torproject/onionoo/UptimeStatusUpdater.java b/src/org/torproject/onionoo/UptimeStatusUpdater.java
index f524ea3..97a6be1 100644
--- a/src/org/torproject/onionoo/UptimeStatusUpdater.java
+++ b/src/org/torproject/onionoo/UptimeStatusUpdater.java
@@ -109,72 +109,14 @@ public class UptimeStatusUpdater implements DescriptorListener,
private void updateStatus(boolean relay, String fingerprint,
SortedSet<Long> newUptimeHours) {
- UptimeStatus uptimeStatus = this.readHistory(fingerprint);
- if (uptimeStatus == null) {
- uptimeStatus = new UptimeStatus();
- }
- this.addToHistory(uptimeStatus, relay, newUptimeHours);
- this.compressHistory(uptimeStatus);
- this.writeHistory(fingerprint, uptimeStatus);
- }
-
- private UptimeStatus readHistory(String fingerprint) {
- return fingerprint == null ?
+ UptimeStatus uptimeStatus = fingerprint == null ?
documentStore.retrieve(UptimeStatus.class, true) :
documentStore.retrieve(UptimeStatus.class, true, fingerprint);
- }
-
- private void addToHistory(UptimeStatus uptimeStatus, boolean relay,
- SortedSet<Long> newIntervals) {
- SortedSet<UptimeHistory> history = uptimeStatus.getHistory();
- for (long startMillis : newIntervals) {
- UptimeHistory interval = new UptimeHistory(relay, startMillis, 1);
- if (!history.headSet(interval).isEmpty()) {
- UptimeHistory prev = history.headSet(interval).last();
- if (prev.isRelay() == interval.isRelay() &&
- prev.getStartMillis() + DateTimeHelper.ONE_HOUR
- * prev.getUptimeHours() > interval.getStartMillis()) {
- continue;
- }
- }
- if (!history.tailSet(interval).isEmpty()) {
- UptimeHistory next = history.tailSet(interval).first();
- if (next.isRelay() == interval.isRelay() &&
- next.getStartMillis() < interval.getStartMillis()
- + DateTimeHelper.ONE_HOUR) {
- continue;
- }
- }
- history.add(interval);
- }
- }
-
- private void compressHistory(UptimeStatus uptimeStatus) {
- SortedSet<UptimeHistory> history = uptimeStatus.getHistory();
- SortedSet<UptimeHistory> compressedHistory =
- new TreeSet<UptimeHistory>();
- UptimeHistory lastInterval = null;
- for (UptimeHistory interval : history) {
- if (lastInterval != null &&
- lastInterval.getStartMillis() + DateTimeHelper.ONE_HOUR
- * lastInterval.getUptimeHours() == interval.getStartMillis() &&
- lastInterval.isRelay() == interval.isRelay()) {
- lastInterval.addUptime(interval);
- } else {
- if (lastInterval != null) {
- compressedHistory.add(lastInterval);
- }
- lastInterval = interval;
- }
- }
- if (lastInterval != null) {
- compressedHistory.add(lastInterval);
+ if (uptimeStatus == null) {
+ uptimeStatus = new UptimeStatus();
}
- uptimeStatus.setHistory(compressedHistory);
- }
-
- private void writeHistory(String fingerprint,
- UptimeStatus uptimeStatus) {
+ uptimeStatus.addToHistory(relay, newUptimeHours);
+ uptimeStatus.compressHistory();
if (fingerprint == null) {
this.documentStore.store(uptimeStatus);
} else {
1
0

14 Apr '14
commit 8e96d945e7d1c42fe7810f696a43d31ab74ddec1
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Fri Mar 21 20:44:34 2014 +0100
Move DummyTime to its own source file.
---
test/org/torproject/onionoo/DummyTime.java | 14 ++++++++++++++
test/org/torproject/onionoo/ResourceServletTest.java | 12 +-----------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/test/org/torproject/onionoo/DummyTime.java b/test/org/torproject/onionoo/DummyTime.java
new file mode 100644
index 0000000..7178ed1
--- /dev/null
+++ b/test/org/torproject/onionoo/DummyTime.java
@@ -0,0 +1,14 @@
+/* Copyright 2014 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.onionoo;
+
+public class DummyTime extends Time {
+ private long currentTimeMillis;
+ public DummyTime(long currentTimeMillis) {
+ this.currentTimeMillis = currentTimeMillis;
+ }
+ public long currentTimeMillis() {
+ return this.currentTimeMillis;
+ }
+}
+
diff --git a/test/org/torproject/onionoo/ResourceServletTest.java b/test/org/torproject/onionoo/ResourceServletTest.java
index 3b8b5ae..e2a6a7e 100644
--- a/test/org/torproject/onionoo/ResourceServletTest.java
+++ b/test/org/torproject/onionoo/ResourceServletTest.java
@@ -37,16 +37,6 @@ public class ResourceServletTest {
private long currentTimeMillis = 1366806142000L;
- private class TestingTime extends Time {
- private long currentTimeMillis;
- public TestingTime(long currentTimeMillis) {
- this.currentTimeMillis = currentTimeMillis;
- }
- public long currentTimeMillis() {
- return this.currentTimeMillis;
- }
- }
-
private boolean maintenanceMode = false;
private class TestingHttpServletRequestWrapper
@@ -165,7 +155,7 @@ public class ResourceServletTest {
}
private void createDummyTime() {
- Time dummyTime = new TestingTime(this.currentTimeMillis);
+ Time dummyTime = new DummyTime(this.currentTimeMillis);
ApplicationFactory.setTime(dummyTime);
}
1
0
commit 234efb3cdd573b39c5275e3239eb6532affcc1ff
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Apr 8 07:04:31 2014 +0200
Fix serialization using Gson.
We never hit this bug, because so far we never serialized anything using
Gson.
---
src/org/torproject/onionoo/DocumentStore.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/org/torproject/onionoo/DocumentStore.java b/src/org/torproject/onionoo/DocumentStore.java
index fa0e98c..95f8f93 100644
--- a/src/org/torproject/onionoo/DocumentStore.java
+++ b/src/org/torproject/onionoo/DocumentStore.java
@@ -195,7 +195,7 @@ public class DocumentStore {
document instanceof ClientsDocument ||
document instanceof UptimeDocument) {
Gson gson = new Gson();
- documentString = gson.toJson(this);
+ documentString = gson.toJson(document);
} else if (document instanceof BandwidthStatus ||
document instanceof WeightsStatus ||
document instanceof ClientsStatus ||
1
0

[onionoo/master] Add UptimeStatusTest and improve test dummies.
by karsten@torproject.org 14 Apr '14
by karsten@torproject.org 14 Apr '14
14 Apr '14
commit 9748e432b8d750112f52c82bbf788dd3f130c9a7
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Sat Apr 12 18:32:11 2014 +0200
Add UptimeStatusTest and improve test dummies.
---
src/org/torproject/onionoo/DateTimeHelper.java | 2 +-
src/org/torproject/onionoo/UptimeStatus.java | 4 +-
.../org/torproject/onionoo/DummyDocumentStore.java | 85 ++++---
.../torproject/onionoo/ResourceServletTest.java | 68 +++---
test/org/torproject/onionoo/UptimeStatusTest.java | 238 ++++++++++++++++++++
5 files changed, 335 insertions(+), 62 deletions(-)
diff --git a/src/org/torproject/onionoo/DateTimeHelper.java b/src/org/torproject/onionoo/DateTimeHelper.java
index fb0c00d..ff61423 100644
--- a/src/org/torproject/onionoo/DateTimeHelper.java
+++ b/src/org/torproject/onionoo/DateTimeHelper.java
@@ -40,7 +40,7 @@ public class DateTimeHelper {
public static final String ISO_YEARMONTH_FORMAT = "yyyy-MM";
- public static final String YEARHOUR_NOSPACE_FORMAT = "yyyy-MM-dd-HH";
+ public static final String DATEHOUR_NOSPACE_FORMAT = "yyyy-MM-dd-HH";
private static Map<String, DateFormat> dateFormats =
new HashMap<String, DateFormat>();
diff --git a/src/org/torproject/onionoo/UptimeStatus.java b/src/org/torproject/onionoo/UptimeStatus.java
index 1a222b0..02b83ee 100644
--- a/src/org/torproject/onionoo/UptimeStatus.java
+++ b/src/org/torproject/onionoo/UptimeStatus.java
@@ -43,7 +43,7 @@ class UptimeHistory
return null;
}
long startMillis = DateTimeHelper.parse(parts[1],
- DateTimeHelper.YEARHOUR_NOSPACE_FORMAT);
+ DateTimeHelper.DATEHOUR_NOSPACE_FORMAT);
if (startMillis < 0L) {
return null;
}
@@ -60,7 +60,7 @@ class UptimeHistory
StringBuilder sb = new StringBuilder();
sb.append(this.relay ? "r" : "b");
sb.append(" " + DateTimeHelper.format(this.startMillis,
- DateTimeHelper.YEARHOUR_NOSPACE_FORMAT));
+ DateTimeHelper.DATEHOUR_NOSPACE_FORMAT));
sb.append(" " + String.format("%d", this.uptimeHours));
return sb.toString();
}
diff --git a/test/org/torproject/onionoo/DummyDocumentStore.java b/test/org/torproject/onionoo/DummyDocumentStore.java
index c7ca7ff..05723d0 100644
--- a/test/org/torproject/onionoo/DummyDocumentStore.java
+++ b/test/org/torproject/onionoo/DummyDocumentStore.java
@@ -1,5 +1,7 @@
package org.torproject.onionoo;
+import java.util.HashMap;
+import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
@@ -7,69 +9,96 @@ import java.util.TreeSet;
public class DummyDocumentStore extends DocumentStore {
- private long lastModified;
+ private Map<Class<? extends Document>, SortedMap<String, Document>>
+ storedDocuments = new HashMap<Class<? extends Document>,
+ SortedMap<String, Document>>();
- public DummyDocumentStore(long lastModified) {
- this.lastModified = lastModified;
+ private static final String FINGERPRINT_NULL = "";
+
+ private <T extends Document> SortedMap<String, Document>
+ getStoredDocumentsByClass(Class<T> documentType) {
+ if (!this.storedDocuments.containsKey(documentType)) {
+ this.storedDocuments.put(documentType,
+ new TreeMap<String, Document>());
+ }
+ return this.storedDocuments.get(documentType);
}
- private SortedMap<String, NodeStatus> nodeStatuses =
- new TreeMap<String, NodeStatus>();
- void addNodeStatus(String nodeStatusString) {
- NodeStatus nodeStatus = NodeStatus.fromString(nodeStatusString);
- this.nodeStatuses.put(nodeStatus.getFingerprint(), nodeStatus);
+ public <T extends Document> void addDocument(T document,
+ String fingerprint) {
+ this.getStoredDocumentsByClass(document.getClass()).put(
+ fingerprint == null ? FINGERPRINT_NULL : fingerprint, document);
}
public void flushDocumentCache() {
- throw new RuntimeException("Not implemented.");
+ /* Nothing to do. */
}
public String getStatsString() {
- throw new RuntimeException("Not implemented.");
+ /* No statistics to return. */
+ return null;
+ }
+
+ private int performedListOperations = 0;
+ public int getPerformedListOperations() {
+ return this.performedListOperations;
}
public <T extends Document> SortedSet<String> list(
Class<T> documentType, boolean includeArchive) {
- if (documentType.equals(NodeStatus.class)) {
- return new TreeSet<String>(this.nodeStatuses.keySet());
- }
- throw new RuntimeException("Not implemented.");
+ this.performedListOperations++;
+ return new TreeSet<String>(this.getStoredDocumentsByClass(
+ documentType).keySet());
+ }
+
+ private int performedRemoveOperations = 0;
+ public int getPerformedRemoveOperations() {
+ return this.performedRemoveOperations;
}
public <T extends Document> boolean remove(Class<T> documentType) {
- throw new RuntimeException("Not implemented.");
+ return this.remove(documentType, null);
}
public <T extends Document> boolean remove(Class<T> documentType,
String fingerprint) {
- throw new RuntimeException("Not implemented.");
+ this.performedRemoveOperations++;
+ return this.getStoredDocumentsByClass(documentType).remove(
+ fingerprint) != null;
+ }
+
+ private int performedRetrieveOperations = 0;
+ public int getPerformedRetrieveOperations() {
+ return this.performedRetrieveOperations;
}
public <T extends Document> T retrieve(Class<T> documentType,
boolean parse) {
- if (documentType.equals(UpdateStatus.class)) {
- UpdateStatus updateStatus = new UpdateStatus();
- updateStatus.setDocumentString(String.valueOf(this.lastModified));
- return documentType.cast(updateStatus);
- }
- throw new RuntimeException("Not implemented.");
+ return this.retrieve(documentType, parse, null);
}
public <T extends Document> T retrieve(Class<T> documentType,
boolean parse, String fingerprint) {
- if (documentType.equals(NodeStatus.class)) {
- return documentType.cast(this.nodeStatuses.get(fingerprint));
- }
- throw new RuntimeException("Not implemented.");
+ this.performedRetrieveOperations++;
+ return documentType.cast(this.getStoredDocumentsByClass(documentType).
+ get(fingerprint == null ? FINGERPRINT_NULL : fingerprint));
+ }
+
+ private int performedStoreOperations = 0;
+ public int getPerformedStoreOperations() {
+ return this.performedStoreOperations;
}
public <T extends Document> boolean store(T document) {
- throw new RuntimeException("Not implemented.");
+ return this.store(document, null);
}
public <T extends Document> boolean store(T document,
String fingerprint) {
- throw new RuntimeException("Not implemented.");
+ this.performedStoreOperations++;
+ this.getStoredDocumentsByClass(document.getClass()).put(
+ fingerprint == null ? FINGERPRINT_NULL : fingerprint, document);
+ return true;
}
}
diff --git a/test/org/torproject/onionoo/ResourceServletTest.java b/test/org/torproject/onionoo/ResourceServletTest.java
index e2a6a7e..cbe787c 100644
--- a/test/org/torproject/onionoo/ResourceServletTest.java
+++ b/test/org/torproject/onionoo/ResourceServletTest.java
@@ -104,42 +104,44 @@ public class ResourceServletTest {
@Before
public void createSampleRelaysAndBridges() {
this.relays = new TreeMap<String, String>();
- this.relays.put("000C5F55", "r\tTorkaZ\t"
- + "000C5F55BD4814B917CC474BD537F1A3B33CCE2A\t"
+ this.relays.put("000C5F55BD4814B917CC474BD537F1A3B33CCE2A",
+ "r\tTorkaZ\t000C5F55BD4814B917CC474BD537F1A3B33CCE2A\t"
+ "62.216.201.221;;62.216.201.222+62.216.201.223\t"
+ "2013-04-19\t05:00:00\t9001\t0\tRunning,Valid\t20\tde\tnull\t"
+ "-1\treject\t1-65535\t2013-04-18\t05:00:00\t"
+ "2013-04-19\t05:00:00\tAS8767\ttorkaz <klaus dot zufall at "
+ "gmx dot de> <fb-token:np5_g_83jmf=>");
- this.relays.put("001C13B3", "r\tFerrari458\t"
- + "001C13B3A55A71B977CA65EC85539D79C653A3FC\t"
+ this.relays.put("001C13B3A55A71B977CA65EC85539D79C653A3FC",
+ "r\tFerrari458\t001C13B3A55A71B977CA65EC85539D79C653A3FC\t"
+ "68.38.171.200;[2001:4f8:3:2e::51]:9001;\t"
+ "2013-04-24\t12:00:00\t9001\t9030\t"
+ "Fast,Named,Running,V2Dir,Valid\t1140\tus\t"
+ "c-68-38-171-200.hsd1.pa.comcast.net\t1366805763009\treject\t"
+ "1-65535\t2013-02-12\t16:00:00\t2013-02-26\t18:00:00\t"
+ "AS7922\t");
- this.relays.put("0025C136", "r\tTimMayTribute\t"
- + "0025C136C1F3A9EEFE2AE3F918F03BFA21B5070B\t89.69.68.246;;\t"
- + "2013-04-22\t20:00:00\t9001\t9030\t"
+ this.relays.put("0025C136C1F3A9EEFE2AE3F918F03BFA21B5070B",
+ "r\tTimMayTribute\t0025C136C1F3A9EEFE2AE3F918F03BFA21B5070B\t"
+ + "89.69.68.246;;\t2013-04-22\t20:00:00\t9001\t9030\t"
+ "Fast,Running,Unnamed,V2Dir,Valid\t63\ta1\tnull\t-1\treject\t"
+ "1-65535\t2013-04-16\t18:00:00\t2013-04-16\t18:00:00\t"
+ "AS6830\t1024D/51E2A1C7 steven j. murdoch "
+ "<tor+steven.murdoch(a)cl.cam.ac.uk> <fb-token:5sr_k_zs2wm=>");
this.bridges = new TreeMap<String, String>();
- this.bridges.put("0000831B", "b\tec2bridgercc7f31fe\t"
+ this.bridges.put("0000831B236DFF73D409AD17B40E2A728A53994F",
+ "b\tec2bridgercc7f31fe\t"
+ "0000831B236DFF73D409AD17B40E2A728A53994F\t10.199.7.176;;\t"
+ "2013-04-21\t18:07:03\t443\t0\tValid\t-1\t??\tnull\t-1\t"
+ "null\tnull\t2013-04-20\t15:37:04\tnull\tnull\tnull\tnull");
- this.bridges.put("0002D9BD", "b\tUnnamed\t"
- + "0002D9BDBBC230BD9C78FF502A16E0033EF87E0C\t10.0.52.84;;\t"
- + "2013-04-20\t17:37:04\t443\t0\tValid\t-1\t??\tnull\t-1\t"
- + "null\tnull\t2013-04-14\t07:07:05\tnull\tnull\tnull\tnull");
- this.bridges.put("0010D49C", "b\tgummy\t"
- + "1FEDE50ED8DBA1DD9F9165F78C8131E4A44AB756\t10.63.169.98;;\t"
- + "2013-04-24\t01:07:04\t9001\t0\tRunning,Valid\t-1\t??\tnull\t"
- + "-1\tnull\tnull\t2013-01-16\t21:07:04\tnull\tnull\tnull\t"
+ this.bridges.put("0002D9BDBBC230BD9C78FF502A16E0033EF87E0C",
+ "b\tUnnamed\t0002D9BDBBC230BD9C78FF502A16E0033EF87E0C\t"
+ + "10.0.52.84;;\t2013-04-20\t17:37:04\t443\t0\tValid\t-1\t??\t"
+ + "null\t-1\tnull\tnull\t2013-04-14\t07:07:05\tnull\tnull\tnull\t"
+ "null");
+ this.bridges.put("1FEDE50ED8DBA1DD9F9165F78C8131E4A44AB756",
+ "b\tgummy\t1FEDE50ED8DBA1DD9F9165F78C8131E4A44AB756\t"
+ + "10.63.169.98;;\t2013-04-24\t01:07:04\t9001\t0\tRunning,Valid\t"
+ + "-1\t??\tnull\t-1\tnull\tnull\t2013-01-16\t21:07:04\tnull\t"
+ + "null\tnull\tnull");
}
private void runTest(String requestURI,
@@ -164,13 +166,17 @@ public class ResourceServletTest {
* ResponseBuilder to read state from the newly created DocumentStore.
* Otherwise, ResponseBuilder would use data from the previous test
* run. This is bad design and should be fixed. */
- DummyDocumentStore documentStore = new DummyDocumentStore(
- lastModified++);
- for (String relay : relays.values()) {
- documentStore.addNodeStatus(relay);
+ DummyDocumentStore documentStore = new DummyDocumentStore();
+ UpdateStatus updateStatus = new UpdateStatus();
+ updateStatus.setDocumentString(String.valueOf(lastModified++));
+ documentStore.addDocument(updateStatus, null);
+ for (Map.Entry<String, String> e : relays.entrySet()) {
+ documentStore.addDocument(NodeStatus.fromString(e.getValue()),
+ e.getKey());
}
- for (String bridge : bridges.values()) {
- documentStore.addNodeStatus(bridge);
+ for (Map.Entry<String, String> e : bridges.entrySet()) {
+ documentStore.addDocument(NodeStatus.fromString(e.getValue()),
+ e.getKey());
}
ApplicationFactory.setDocumentStore(documentStore);
}
@@ -278,11 +284,11 @@ public class ResourceServletTest {
@Test()
public void testValidSummaryRelay() throws IOException {
this.relays.clear();
- this.relays.put("000C5F55", "r TorkaZ "
- + "000C5F55BD4814B917CC474BD537F1A3B33CCE2A 62.216.201.221;; "
- + "2013-04-19 05:00:00 9001 0 Running,Valid 20 de null -1 "
- + "reject 1-65535 2013-04-18 05:00:00 2013-04-19 05:00:00 "
- + "AS8767");
+ this.relays.put("000C5F55BD4814B917CC474BD537F1A3B33CCE2A",
+ "r TorkaZ 000C5F55BD4814B917CC474BD537F1A3B33CCE2A "
+ + "62.216.201.221;; 2013-04-19 05:00:00 9001 0 Running,Valid 20 "
+ + "de null -1 reject 1-65535 2013-04-18 05:00:00 2013-04-19 "
+ + "05:00:00 AS8767");
this.runTest("/summary", null);
assertEquals("2013-04-19 05:00:00",
this.summaryDocument.relays_published);
@@ -298,10 +304,10 @@ public class ResourceServletTest {
@Test()
public void testValidSummaryBridge() {
this.bridges.clear();
- this.bridges.put("0000831", "b ec2bridgercc7f31fe "
- + "0000831B236DFF73D409AD17B40E2A728A53994F 10.199.7.176;; "
- + "2013-04-21 18:07:03 443 0 Valid -1 ?? null -1 null null "
- + "2013-04-20 15:37:04 null null null");
+ this.bridges.put("0000831B236DFF73D409AD17B40E2A728A53994F",
+ "b ec2bridgercc7f31fe 0000831B236DFF73D409AD17B40E2A728A53994F "
+ + "10.199.7.176;; 2013-04-21 18:07:03 443 0 Valid -1 ?? null -1 "
+ + "null null 2013-04-20 15:37:04 null null null");
this.runTest("/summary", null);
assertEquals("2013-04-21 18:07:03",
this.summaryDocument.bridges_published);
diff --git a/test/org/torproject/onionoo/UptimeStatusTest.java b/test/org/torproject/onionoo/UptimeStatusTest.java
new file mode 100644
index 0000000..fab48e6
--- /dev/null
+++ b/test/org/torproject/onionoo/UptimeStatusTest.java
@@ -0,0 +1,238 @@
+/* Copyright 2014 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.onionoo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class UptimeStatusTest {
+
+ private DummyDocumentStore documentStore;
+
+ @Before
+ public void createDummyDocumentStore() {
+ this.documentStore = new DummyDocumentStore();
+ ApplicationFactory.setDocumentStore(this.documentStore);
+ }
+
+ private static final String MORIA1_FINGERPRINT =
+ "9695DFC35FFEB861329B9F1AB04C46397020CE31";
+
+ @Test()
+ public void testEmptyStatusNoWriteToDisk() {
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ MORIA1_FINGERPRINT);
+ uptimeStatus.storeIfChanged();
+ assertEquals("Should make one retrieve attempt.", 1,
+ this.documentStore.getPerformedRetrieveOperations());
+ assertEquals("Newly created uptime status with empty history should "
+ + "not be written to disk.", 0,
+ this.documentStore.getPerformedStoreOperations());
+ }
+
+ @Test()
+ public void testSingleHourWriteToDisk() {
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ MORIA1_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-12-20 00:00:00") })));
+ uptimeStatus.storeIfChanged();
+ assertEquals("History must contain single entry.", 1,
+ uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("History not for relay.", true,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not same as provided.",
+ DateTimeHelper.parse("2013-12-20 00:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 1.", 1,
+ newUptimeHistory.getUptimeHours());
+ assertEquals("Newly created uptime status with non-empty history "
+ + "must be written to disk.", 1,
+ this.documentStore.getPerformedStoreOperations());
+ }
+
+ @Test()
+ public void testTwoConsecutiveHours() {
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ MORIA1_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-12-20 00:00:00"),
+ DateTimeHelper.parse("2013-12-20 01:00:00") })));
+ uptimeStatus.storeIfChanged();
+ assertEquals("History must contain single entry.", 1,
+ uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("History not for relay.", true,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not same as provided.",
+ DateTimeHelper.parse("2013-12-20 00:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 2.", 2,
+ newUptimeHistory.getUptimeHours());
+ }
+
+ private static final String GABELMOO_FINGERPRINT =
+ "F2044413DAC2E02E3D6BCF4735A19BCA1DE97281";
+
+ private static final String GABELMOO_UPTIME_SAMPLE =
+ "r 2013-07-22-17 1161\n" /* ends 2013-09-09 02:00:00 */
+ + "r 2013-09-09-03 2445\n" /* ends 2013-12-20 00:00:00 */
+ + "r 2013-12-20-01 2203\n"; /* ends 2014-03-21 20:00:00 */
+
+ private void addGabelmooUptimeSample() {
+ UptimeStatus uptimeStatus = new UptimeStatus();
+ uptimeStatus.fromDocumentString(GABELMOO_UPTIME_SAMPLE);
+ this.documentStore.addDocument(uptimeStatus, GABELMOO_FINGERPRINT);
+ }
+
+ @Test()
+ public void testGabelmooFillInGaps() {
+ this.addGabelmooUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ GABELMOO_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-09-09 02:00:00"),
+ DateTimeHelper.parse("2013-12-20 00:00:00") })));
+ assertEquals("Uncompressed history must contain five entries.", 5,
+ uptimeStatus.getHistory().size());
+ uptimeStatus.storeIfChanged();
+ assertEquals("Compressed history must contain one entry.", 1,
+ uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("History not for relay.", true,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not as expected.",
+ DateTimeHelper.parse("2013-07-22 17:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 1161+1+2445+1+2203=5811.",
+ 5811, newUptimeHistory.getUptimeHours());
+ }
+
+ @Test()
+ public void testAddExistingHourToIntervalStart() {
+ this.addGabelmooUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ GABELMOO_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-07-22 17:00:00") })));
+ uptimeStatus.storeIfChanged();
+ assertEquals("Unchanged history should not be written to disk.", 0,
+ this.documentStore.getPerformedStoreOperations());
+ }
+
+ @Test()
+ public void testAddExistingHourToIntervalEnd() {
+ this.addGabelmooUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ GABELMOO_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-09-09 01:00:00") })));
+ uptimeStatus.storeIfChanged();
+ assertEquals("Unchanged history should not be written to disk.", 0,
+ this.documentStore.getPerformedStoreOperations());
+ }
+
+ @Test()
+ public void testTwoHoursOverlappingWithIntervalStart() {
+ this.addGabelmooUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ GABELMOO_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-07-22 16:00:00"),
+ DateTimeHelper.parse("2013-07-22 17:00:00")})));
+ uptimeStatus.storeIfChanged();
+ assertEquals("Compressed history must still contain three entries.",
+ 3, uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("History not for relay.", true,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not as expected.",
+ DateTimeHelper.parse("2013-07-22 16:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 1+1161=1162.", 1162,
+ newUptimeHistory.getUptimeHours());
+ }
+
+ @Test()
+ public void testTwoHoursOverlappingWithIntervalEnd() {
+ this.addGabelmooUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ GABELMOO_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-09-09 01:00:00"),
+ DateTimeHelper.parse("2013-09-09 02:00:00")})));
+ uptimeStatus.storeIfChanged();
+ assertEquals("Compressed history must now contain two entries.",
+ 2, uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("History not for relay.", true,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not as expected.",
+ DateTimeHelper.parse("2013-07-22 17:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 1161+1+2445=3607.", 3607,
+ newUptimeHistory.getUptimeHours());
+ }
+
+ private static final String ALL_RELAYS_AND_BRIDGES_FINGERPRINT = null;
+
+ private static final String ALL_RELAYS_AND_BRIDGES_UPTIME_SAMPLE =
+ "r 2013-07-22-17 5811\n" /* ends 2014-03-21 20:00:00 */
+ + "b 2013-07-22-17 5811\n"; /* ends 2014-03-21 20:00:00 */
+
+ private void addAllRelaysAndBridgesUptimeSample() {
+ UptimeStatus uptimeStatus = new UptimeStatus();
+ uptimeStatus.fromDocumentString(ALL_RELAYS_AND_BRIDGES_UPTIME_SAMPLE);
+ this.documentStore.addDocument(uptimeStatus,
+ ALL_RELAYS_AND_BRIDGES_FINGERPRINT);
+ }
+
+ @Test()
+ public void testAddRelayUptimeHours() {
+ this.addAllRelaysAndBridgesUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ ALL_RELAYS_AND_BRIDGES_FINGERPRINT);
+ uptimeStatus.addToHistory(true, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-07-22 16:00:00"),
+ DateTimeHelper.parse("2014-03-21 20:00:00")})));
+ uptimeStatus.storeIfChanged();
+ assertEquals("Compressed history must still contain two entries.",
+ 2, uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("History not for relay.", true,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not as expected.",
+ DateTimeHelper.parse("2013-07-22 16:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 1+5811+1=5813.", 5813,
+ newUptimeHistory.getUptimeHours());
+ }
+
+ @Test()
+ public void testAddBridgeUptimeHours() {
+ this.addAllRelaysAndBridgesUptimeSample();
+ UptimeStatus uptimeStatus = UptimeStatus.loadOrCreate(
+ ALL_RELAYS_AND_BRIDGES_FINGERPRINT);
+ uptimeStatus.addToHistory(false, new TreeSet<Long>(Arrays.asList(
+ new Long[] { DateTimeHelper.parse("2013-07-22 16:00:00"),
+ DateTimeHelper.parse("2014-03-21 20:00:00")})));
+ uptimeStatus.storeIfChanged();
+ assertEquals("Compressed history must still contain two entries.",
+ 2, uptimeStatus.getHistory().size());
+ UptimeHistory newUptimeHistory = uptimeStatus.getHistory().last();
+ assertEquals("History not for bridge.", false,
+ newUptimeHistory.isRelay());
+ assertEquals("History start millis not as expected.",
+ DateTimeHelper.parse("2013-07-22 16:00:00"),
+ newUptimeHistory.getStartMillis());
+ assertEquals("History uptime hours not 1+5811+1=5813.", 5813,
+ newUptimeHistory.getUptimeHours());
+ }
+}
+
1
0

14 Apr '14
commit fecc396fbc7857c7a59d7f6ad944411241b261eb
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Mar 24 08:45:34 2014 +0100
Refactor storing histories in UptimeStatus.
---
.../torproject/onionoo/UptimeDocumentWriter.java | 21 +++----
src/org/torproject/onionoo/UptimeStatus.java | 60 +++++++++++++-------
test/org/torproject/onionoo/UptimeStatusTest.java | 41 +++++++------
.../onionoo/UptimeStatusUpdaterTest.java | 24 ++++----
4 files changed, 83 insertions(+), 63 deletions(-)
diff --git a/src/org/torproject/onionoo/UptimeDocumentWriter.java b/src/org/torproject/onionoo/UptimeDocumentWriter.java
index 6b44b24..60ca311 100644
--- a/src/org/torproject/onionoo/UptimeDocumentWriter.java
+++ b/src/org/torproject/onionoo/UptimeDocumentWriter.java
@@ -44,27 +44,18 @@ public class UptimeDocumentWriter implements FingerprintListener,
}
public void writeDocuments() {
- SortedSet<UptimeHistory>
- knownRelayStatuses = new TreeSet<UptimeHistory>(),
- knownBridgeStatuses = new TreeSet<UptimeHistory>();
UptimeStatus uptimeStatus = this.documentStore.retrieve(
UptimeStatus.class, true);
if (uptimeStatus == null) {
return;
}
- SortedSet<UptimeHistory> knownStatuses = uptimeStatus.getHistory();
- for (UptimeHistory status : knownStatuses) {
- if (status.isRelay()) {
- knownRelayStatuses.add(status);
- } else {
- knownBridgeStatuses.add(status);
- }
- }
for (String fingerprint : this.newRelayFingerprints) {
- this.updateDocument(true, fingerprint, knownRelayStatuses);
+ this.updateDocument(true, fingerprint,
+ uptimeStatus.getRelayHistory());
}
for (String fingerprint : this.newBridgeFingerprints) {
- this.updateDocument(false, fingerprint, knownBridgeStatuses);
+ this.updateDocument(false, fingerprint,
+ uptimeStatus.getBridgeHistory());
}
Logger.printStatusTime("Wrote uptime document files");
}
@@ -76,7 +67,9 @@ public class UptimeDocumentWriter implements FingerprintListener,
UptimeStatus uptimeStatus = this.documentStore.retrieve(
UptimeStatus.class, true, fingerprint);
if (uptimeStatus != null) {
- SortedSet<UptimeHistory> history = uptimeStatus.getHistory();
+ SortedSet<UptimeHistory> history = relay
+ ? uptimeStatus.getRelayHistory()
+ : uptimeStatus.getBridgeHistory();
UptimeDocument uptimeDocument = new UptimeDocument();
uptimeDocument.setDocumentString(this.formatHistoryString(relay,
fingerprint, history, knownStatuses));
diff --git a/src/org/torproject/onionoo/UptimeStatus.java b/src/org/torproject/onionoo/UptimeStatus.java
index 02b83ee..4cf71c6 100644
--- a/src/org/torproject/onionoo/UptimeStatus.java
+++ b/src/org/torproject/onionoo/UptimeStatus.java
@@ -99,12 +99,22 @@ class UptimeStatus extends Document {
private transient boolean isDirty = false;
- private SortedSet<UptimeHistory> history = new TreeSet<UptimeHistory>();
- public void setHistory(SortedSet<UptimeHistory> history) {
- this.history = history;
+ private SortedSet<UptimeHistory> relayHistory =
+ new TreeSet<UptimeHistory>();
+ public void setRelayHistory(SortedSet<UptimeHistory> relayHistory) {
+ this.relayHistory = relayHistory;
}
- public SortedSet<UptimeHistory> getHistory() {
- return this.history;
+ public SortedSet<UptimeHistory> getRelayHistory() {
+ return this.relayHistory;
+ }
+
+ private SortedSet<UptimeHistory> bridgeHistory =
+ new TreeSet<UptimeHistory>();
+ public void setBridgeHistory(SortedSet<UptimeHistory> bridgeHistory) {
+ this.bridgeHistory = bridgeHistory;
+ }
+ public SortedSet<UptimeHistory> getBridgeHistory() {
+ return this.bridgeHistory;
}
public static UptimeStatus loadOrCreate(String fingerprint) {
@@ -126,7 +136,11 @@ class UptimeStatus extends Document {
String line = s.nextLine();
UptimeHistory parsedLine = UptimeHistory.fromString(line);
if (parsedLine != null) {
- this.history.add(parsedLine);
+ if (parsedLine.isRelay()) {
+ this.relayHistory.add(parsedLine);
+ } else {
+ this.bridgeHistory.add(parsedLine);
+ }
} else {
System.err.println("Could not parse uptime history line '"
+ line + "'. Skipping.");
@@ -137,31 +151,34 @@ class UptimeStatus extends Document {
public void addToHistory(boolean relay, SortedSet<Long> newIntervals) {
for (long startMillis : newIntervals) {
+ SortedSet<UptimeHistory> history = relay ? this.relayHistory
+ : this.bridgeHistory;
UptimeHistory interval = new UptimeHistory(relay, startMillis, 1);
- if (!this.history.headSet(interval).isEmpty()) {
- UptimeHistory prev = this.history.headSet(interval).last();
+ if (!history.headSet(interval).isEmpty()) {
+ UptimeHistory prev = history.headSet(interval).last();
if (prev.isRelay() == interval.isRelay() &&
prev.getStartMillis() + DateTimeHelper.ONE_HOUR
* prev.getUptimeHours() > interval.getStartMillis()) {
continue;
}
}
- if (!this.history.tailSet(interval).isEmpty()) {
- UptimeHistory next = this.history.tailSet(interval).first();
+ if (!history.tailSet(interval).isEmpty()) {
+ UptimeHistory next = history.tailSet(interval).first();
if (next.isRelay() == interval.isRelay() &&
next.getStartMillis() < interval.getStartMillis()
+ DateTimeHelper.ONE_HOUR) {
continue;
}
}
- this.history.add(interval);
+ history.add(interval);
this.isDirty = true;
}
}
public void storeIfChanged() {
if (this.isDirty) {
- this.compressHistory();
+ this.compressHistory(this.relayHistory);
+ this.compressHistory(this.bridgeHistory);
if (fingerprint == null) {
ApplicationFactory.getDocumentStore().store(this);
} else {
@@ -172,11 +189,12 @@ class UptimeStatus extends Document {
}
}
- private void compressHistory() {
- SortedSet<UptimeHistory> compressedHistory =
- new TreeSet<UptimeHistory>();
+ private void compressHistory(SortedSet<UptimeHistory> history) {
+ SortedSet<UptimeHistory> uncompressedHistory =
+ new TreeSet<UptimeHistory>(history);
+ history.clear();
UptimeHistory lastInterval = null;
- for (UptimeHistory interval : history) {
+ for (UptimeHistory interval : uncompressedHistory) {
if (lastInterval != null &&
lastInterval.getStartMillis() + DateTimeHelper.ONE_HOUR
* lastInterval.getUptimeHours() == interval.getStartMillis() &&
@@ -184,20 +202,22 @@ class UptimeStatus extends Document {
lastInterval.addUptime(interval);
} else {
if (lastInterval != null) {
- compressedHistory.add(lastInterval);
+ history.add(lastInterval);
}
lastInterval = interval;
}
}
if (lastInterval != null) {
- compressedHistory.add(lastInterval);
+ history.add(lastInterval);
}
- this.history = compressedHistory;
}
public String toDocumentString() {
StringBuilder sb = new StringBuilder();
- for (UptimeHistory interval : this.history) {
+ for (UptimeHistory interval : this.relayHistory) {
+ sb.append(interval.toString() + "\n");
+ }
+ for (UptimeHistory interval : this.bridgeHistory) {
sb.append(interval.toString() + "\n");
}
return sb.toString();
diff --git a/test/org/torproject/onionoo/UptimeStatusTest.java b/test/org/torproject/onionoo/UptimeStatusTest.java
index fab48e6..884ccc5 100644
--- a/test/org/torproject/onionoo/UptimeStatusTest.java
+++ b/test/org/torproject/onionoo/UptimeStatusTest.java
@@ -43,8 +43,9 @@ public class UptimeStatusTest {
new Long[] { DateTimeHelper.parse("2013-12-20 00:00:00") })));
uptimeStatus.storeIfChanged();
assertEquals("History must contain single entry.", 1,
- uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ uptimeStatus.getRelayHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getRelayHistory().first();
assertEquals("History not for relay.", true,
newUptimeHistory.isRelay());
assertEquals("History start millis not same as provided.",
@@ -66,8 +67,9 @@ public class UptimeStatusTest {
DateTimeHelper.parse("2013-12-20 01:00:00") })));
uptimeStatus.storeIfChanged();
assertEquals("History must contain single entry.", 1,
- uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ uptimeStatus.getRelayHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getRelayHistory().first();
assertEquals("History not for relay.", true,
newUptimeHistory.isRelay());
assertEquals("History start millis not same as provided.",
@@ -100,11 +102,12 @@ public class UptimeStatusTest {
new Long[] { DateTimeHelper.parse("2013-09-09 02:00:00"),
DateTimeHelper.parse("2013-12-20 00:00:00") })));
assertEquals("Uncompressed history must contain five entries.", 5,
- uptimeStatus.getHistory().size());
+ uptimeStatus.getRelayHistory().size());
uptimeStatus.storeIfChanged();
assertEquals("Compressed history must contain one entry.", 1,
- uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ uptimeStatus.getRelayHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getRelayHistory().first();
assertEquals("History not for relay.", true,
newUptimeHistory.isRelay());
assertEquals("History start millis not as expected.",
@@ -148,8 +151,9 @@ public class UptimeStatusTest {
DateTimeHelper.parse("2013-07-22 17:00:00")})));
uptimeStatus.storeIfChanged();
assertEquals("Compressed history must still contain three entries.",
- 3, uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ 3, uptimeStatus.getRelayHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getRelayHistory().first();
assertEquals("History not for relay.", true,
newUptimeHistory.isRelay());
assertEquals("History start millis not as expected.",
@@ -169,8 +173,9 @@ public class UptimeStatusTest {
DateTimeHelper.parse("2013-09-09 02:00:00")})));
uptimeStatus.storeIfChanged();
assertEquals("Compressed history must now contain two entries.",
- 2, uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ 2, uptimeStatus.getRelayHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getRelayHistory().first();
assertEquals("History not for relay.", true,
newUptimeHistory.isRelay());
assertEquals("History start millis not as expected.",
@@ -202,9 +207,10 @@ public class UptimeStatusTest {
new Long[] { DateTimeHelper.parse("2013-07-22 16:00:00"),
DateTimeHelper.parse("2014-03-21 20:00:00")})));
uptimeStatus.storeIfChanged();
- assertEquals("Compressed history must still contain two entries.",
- 2, uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().first();
+ assertEquals("Compressed relay history must still contain one entry.",
+ 1, uptimeStatus.getRelayHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getRelayHistory().first();
assertEquals("History not for relay.", true,
newUptimeHistory.isRelay());
assertEquals("History start millis not as expected.",
@@ -223,9 +229,10 @@ public class UptimeStatusTest {
new Long[] { DateTimeHelper.parse("2013-07-22 16:00:00"),
DateTimeHelper.parse("2014-03-21 20:00:00")})));
uptimeStatus.storeIfChanged();
- assertEquals("Compressed history must still contain two entries.",
- 2, uptimeStatus.getHistory().size());
- UptimeHistory newUptimeHistory = uptimeStatus.getHistory().last();
+ assertEquals("Compressed bridge history must still contain one "
+ + "entry.", 1, uptimeStatus.getBridgeHistory().size());
+ UptimeHistory newUptimeHistory =
+ uptimeStatus.getBridgeHistory().last();
assertEquals("History not for bridge.", false,
newUptimeHistory.isRelay());
assertEquals("History start millis not as expected.",
diff --git a/test/org/torproject/onionoo/UptimeStatusUpdaterTest.java b/test/org/torproject/onionoo/UptimeStatusUpdaterTest.java
index 4ca2245..a34292b 100644
--- a/test/org/torproject/onionoo/UptimeStatusUpdaterTest.java
+++ b/test/org/torproject/onionoo/UptimeStatusUpdaterTest.java
@@ -64,9 +64,9 @@ public class UptimeStatusUpdaterTest {
null }) {
UptimeStatus status = this.documentStore.getDocument(
UptimeStatus.class, fingerprint);
- UptimeHistory history = status.getHistory().first();
+ UptimeHistory history = status.getRelayHistory().first();
assertEquals("History must contain one entry.", 1,
- status.getHistory().size());
+ status.getRelayHistory().size());
assertEquals("History not for relay.", true, history.isRelay());
assertEquals("History start millis not as expected.",
VALID_AFTER_SAMPLE, history.getStartMillis());
@@ -99,9 +99,9 @@ public class UptimeStatusUpdaterTest {
2, this.documentStore.getPerformedStoreOperations());
UptimeStatus status = this.documentStore.getDocument(
UptimeStatus.class, ALL_RELAYS_AND_BRIDGES_FINGERPRINT);
- assertEquals("History must contain two entries.", 2,
- status.getHistory().size());
- UptimeHistory history = status.getHistory().first();
+ assertEquals("Relay history must contain one entry", 1,
+ status.getRelayHistory().size());
+ UptimeHistory history = status.getRelayHistory().first();
assertEquals("History not for relay.", true, history.isRelay());
assertEquals("History start millis not as expected.",
DateTimeHelper.parse("2013-07-22 17:00:00"),
@@ -139,9 +139,9 @@ public class UptimeStatusUpdaterTest {
null }) {
UptimeStatus status = this.documentStore.getDocument(
UptimeStatus.class, fingerprint);
- UptimeHistory history = status.getHistory().first();
- assertEquals("History must contain one entry.", 1,
- status.getHistory().size());
+ UptimeHistory history = status.getBridgeHistory().first();
+ assertEquals("Bridge history must contain one entry.", 1,
+ status.getBridgeHistory().size());
assertEquals("History not for bridge.", false, history.isRelay());
assertEquals("History start millis not as expected.",
DateTimeHelper.parse("2014-03-21 20:00:00"),
@@ -162,10 +162,10 @@ public class UptimeStatusUpdaterTest {
2, this.documentStore.getPerformedStoreOperations());
UptimeStatus status = this.documentStore.getDocument(
UptimeStatus.class, ALL_RELAYS_AND_BRIDGES_FINGERPRINT);
- assertEquals("History must contain two entries.", 2,
- status.getHistory().size());
- UptimeHistory history = status.getHistory().last();
- assertEquals("History not for relay.", false, history.isRelay());
+ assertEquals("Bridge history must contain one entry.", 1,
+ status.getBridgeHistory().size());
+ UptimeHistory history = status.getBridgeHistory().last();
+ assertEquals("History not for bridge.", false, history.isRelay());
assertEquals("History start millis not as expected.",
DateTimeHelper.parse("2013-07-22 17:00:00"),
history.getStartMillis());
1
0

[onionoo/master] Use factory instead of passing around references.
by karsten@torproject.org 14 Apr '14
by karsten@torproject.org 14 Apr '14
14 Apr '14
commit f2e453070bd5e7bf2023a639178734adb5d8b022
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Fri Mar 21 20:41:33 2014 +0100
Use factory instead of passing around references.
---
src/org/torproject/onionoo/ApplicationFactory.java | 40 ++++++++++++++++++++
.../onionoo/BandwidthDocumentWriter.java | 9 ++---
.../torproject/onionoo/BandwidthStatusUpdater.java | 9 ++---
.../torproject/onionoo/ClientsDocumentWriter.java | 9 ++---
.../torproject/onionoo/ClientsStatusUpdater.java | 9 ++---
src/org/torproject/onionoo/DescriptorSource.java | 8 ++--
.../torproject/onionoo/DetailsDocumentWriter.java | 9 ++---
src/org/torproject/onionoo/DocumentStore.java | 21 +++++-----
src/org/torproject/onionoo/LockFile.java | 12 ++----
src/org/torproject/onionoo/Logger.java | 4 +-
src/org/torproject/onionoo/Main.java | 35 ++++++++---------
.../onionoo/NodeDetailsStatusUpdater.java | 11 +++---
src/org/torproject/onionoo/RequestHandler.java | 7 ++--
src/org/torproject/onionoo/ResourceServlet.java | 13 +++----
src/org/torproject/onionoo/ResponseBuilder.java | 4 +-
.../onionoo/ReverseDomainNameResolver.java | 4 +-
.../torproject/onionoo/UptimeDocumentWriter.java | 9 ++---
.../torproject/onionoo/UptimeStatusUpdater.java | 7 ++--
.../torproject/onionoo/WeightsDocumentWriter.java | 9 ++---
.../torproject/onionoo/WeightsStatusUpdater.java | 9 ++---
.../org/torproject/onionoo/DummyDocumentStore.java | 4 +-
.../torproject/onionoo/ResourceServletTest.java | 23 +++++++----
22 files changed, 142 insertions(+), 123 deletions(-)
diff --git a/src/org/torproject/onionoo/ApplicationFactory.java b/src/org/torproject/onionoo/ApplicationFactory.java
new file mode 100644
index 0000000..98952df
--- /dev/null
+++ b/src/org/torproject/onionoo/ApplicationFactory.java
@@ -0,0 +1,40 @@
+/* Copyright 2014 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.onionoo;
+
+public class ApplicationFactory {
+
+ private static Time timeInstance;
+ public static void setTime(Time time) {
+ timeInstance = time;
+ }
+ public static Time getTime() {
+ if (timeInstance == null) {
+ timeInstance = new Time();
+ }
+ return timeInstance;
+ }
+
+ private static DescriptorSource descriptorSourceInstance;
+ public static void setDescriptorSource(
+ DescriptorSource descriptorSource) {
+ descriptorSourceInstance = descriptorSource;
+ }
+ public static DescriptorSource getDescriptorSource() {
+ if (descriptorSourceInstance == null) {
+ descriptorSourceInstance = new DescriptorSource();
+ }
+ return descriptorSourceInstance;
+ }
+
+ private static DocumentStore documentStoreInstance;
+ public static void setDocumentStore(DocumentStore documentStore) {
+ documentStoreInstance = documentStore;
+ }
+ public static DocumentStore getDocumentStore() {
+ if (documentStoreInstance == null) {
+ documentStoreInstance = new DocumentStore();
+ }
+ return documentStoreInstance;
+ }
+}
diff --git a/src/org/torproject/onionoo/BandwidthDocumentWriter.java b/src/org/torproject/onionoo/BandwidthDocumentWriter.java
index 8e9b93c..0bc8387 100644
--- a/src/org/torproject/onionoo/BandwidthDocumentWriter.java
+++ b/src/org/torproject/onionoo/BandwidthDocumentWriter.java
@@ -19,11 +19,10 @@ public class BandwidthDocumentWriter implements FingerprintListener,
private long now;
- public BandwidthDocumentWriter(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public BandwidthDocumentWriter() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerFingerprintListeners();
}
diff --git a/src/org/torproject/onionoo/BandwidthStatusUpdater.java b/src/org/torproject/onionoo/BandwidthStatusUpdater.java
index 7633e9f..6320f6e 100644
--- a/src/org/torproject/onionoo/BandwidthStatusUpdater.java
+++ b/src/org/torproject/onionoo/BandwidthStatusUpdater.java
@@ -17,11 +17,10 @@ public class BandwidthStatusUpdater implements DescriptorListener,
private long now;
- public BandwidthStatusUpdater(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public BandwidthStatusUpdater() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerDescriptorListeners();
}
diff --git a/src/org/torproject/onionoo/ClientsDocumentWriter.java b/src/org/torproject/onionoo/ClientsDocumentWriter.java
index 34047b5..bab78e9 100644
--- a/src/org/torproject/onionoo/ClientsDocumentWriter.java
+++ b/src/org/torproject/onionoo/ClientsDocumentWriter.java
@@ -43,11 +43,10 @@ public class ClientsDocumentWriter implements FingerprintListener,
private long now;
- public ClientsDocumentWriter(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public ClientsDocumentWriter() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerFingerprintListeners();
}
diff --git a/src/org/torproject/onionoo/ClientsStatusUpdater.java b/src/org/torproject/onionoo/ClientsStatusUpdater.java
index 56803d4..ed4390e 100644
--- a/src/org/torproject/onionoo/ClientsStatusUpdater.java
+++ b/src/org/torproject/onionoo/ClientsStatusUpdater.java
@@ -38,11 +38,10 @@ public class ClientsStatusUpdater implements DescriptorListener,
private long now;
- public ClientsStatusUpdater(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public ClientsStatusUpdater() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerDescriptorListeners();
}
diff --git a/src/org/torproject/onionoo/DescriptorSource.java b/src/org/torproject/onionoo/DescriptorSource.java
index 86fba25..f5adf56 100644
--- a/src/org/torproject/onionoo/DescriptorSource.java
+++ b/src/org/torproject/onionoo/DescriptorSource.java
@@ -267,15 +267,13 @@ class DescriptorQueue {
public class DescriptorSource {
- private File inDir;
+ private final File inDir = new File("in");
- private File statusDir;
+ private final File statusDir = new File("status");
private List<DescriptorQueue> descriptorQueues;
- public DescriptorSource(File inDir, File statusDir) {
- this.inDir = inDir;
- this.statusDir = statusDir;
+ public DescriptorSource() {
this.descriptorQueues = new ArrayList<DescriptorQueue>();
this.descriptorListeners =
new HashMap<DescriptorType, Set<DescriptorListener>>();
diff --git a/src/org/torproject/onionoo/DetailsDocumentWriter.java b/src/org/torproject/onionoo/DetailsDocumentWriter.java
index 309b80d..c1ae9d0 100644
--- a/src/org/torproject/onionoo/DetailsDocumentWriter.java
+++ b/src/org/torproject/onionoo/DetailsDocumentWriter.java
@@ -24,11 +24,10 @@ public class DetailsDocumentWriter implements DescriptorListener,
private long now;
- public DetailsDocumentWriter(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public DetailsDocumentWriter() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerDescriptorListeners();
this.registerFingerprintListeners();
}
diff --git a/src/org/torproject/onionoo/DocumentStore.java b/src/org/torproject/onionoo/DocumentStore.java
index 95f8f93..e8b35b5 100644
--- a/src/org/torproject/onionoo/DocumentStore.java
+++ b/src/org/torproject/onionoo/DocumentStore.java
@@ -29,12 +29,19 @@ import com.google.gson.JsonParseException;
// TODO Also look into simple key-value stores instead of real databases.
public class DocumentStore {
- private File statusDir;
+ private final File statusDir = new File("status");
- private File outDir;
+ private File outDir = new File("out");
+ public void setOutDir(File outDir) {
+ this.outDir = outDir;
+ }
private Time time;
+ public DocumentStore() {
+ this.time = ApplicationFactory.getTime();
+ }
+
private boolean listedArchivedNodeStatuses = false,
listedCurrentNodeStatuses = false;
@@ -48,16 +55,6 @@ public class DocumentStore {
* operations depend on which NodeStatus documents were listed. */
private SortedMap<String, NodeStatus> cachedNodeStatuses;
- public DocumentStore(File outDir, Time time) {
- this(null, outDir, time);
- }
-
- public DocumentStore(File statusDir, File outDir, Time time) {
- this.statusDir = statusDir;
- this.outDir = outDir;
- this.time = time;
- }
-
public <T extends Document> SortedSet<String> list(
Class<T> documentType, boolean includeArchive) {
if (documentType.equals(NodeStatus.class)) {
diff --git a/src/org/torproject/onionoo/LockFile.java b/src/org/torproject/onionoo/LockFile.java
index acf2dc2..768db53 100644
--- a/src/org/torproject/onionoo/LockFile.java
+++ b/src/org/torproject/onionoo/LockFile.java
@@ -9,16 +9,10 @@ import java.io.IOException;
public class LockFile {
- private File lockFile;
-
- private Time time;
-
- public LockFile(File lockFile, Time time) {
- this.lockFile = lockFile;
- this.time = time;
- }
+ private final File lockFile = new File("lock");
public boolean acquireLock() {
+ Time time = ApplicationFactory.getTime();
try {
if (this.lockFile.exists()) {
return false;
@@ -28,7 +22,7 @@ public class LockFile {
}
BufferedWriter bw = new BufferedWriter(new FileWriter(
this.lockFile));
- bw.append("" + this.time.currentTimeMillis() + "\n");
+ bw.append("" + time.currentTimeMillis() + "\n");
bw.close();
return true;
} catch (IOException e) {
diff --git a/src/org/torproject/onionoo/Logger.java b/src/org/torproject/onionoo/Logger.java
index 5ae9be1..d84adf2 100644
--- a/src/org/torproject/onionoo/Logger.java
+++ b/src/org/torproject/onionoo/Logger.java
@@ -11,8 +11,8 @@ public class Logger {
private static Time time;
- public static void setTime(Time timeParam) {
- time = timeParam;
+ public static void setTime() {
+ time = ApplicationFactory.getTime();
}
private static long currentTimeMillis() {
diff --git a/src/org/torproject/onionoo/Main.java b/src/org/torproject/onionoo/Main.java
index a4e2d92..141e44b 100644
--- a/src/org/torproject/onionoo/Main.java
+++ b/src/org/torproject/onionoo/Main.java
@@ -12,9 +12,8 @@ public class Main {
public static void main(String[] args) {
- Time t = new Time();
- LockFile lf = new LockFile(new File("lock"), t);
- Logger.setTime(t);
+ LockFile lf = new LockFile();
+ Logger.setTime();
Logger.printStatus("Initializing.");
if (lf.acquireLock()) {
Logger.printStatusTime("Acquired lock");
@@ -24,39 +23,37 @@ public class Main {
return;
}
- DescriptorSource dso = new DescriptorSource(new File("in"),
- new File("status"));
+ DescriptorSource dso = ApplicationFactory.getDescriptorSource();
Logger.printStatusTime("Initialized descriptor source");
- DocumentStore ds = new DocumentStore(new File("status"),
- new File("out"), t);
+ DocumentStore ds = ApplicationFactory.getDocumentStore();
Logger.printStatusTime("Initialized document store");
LookupService ls = new LookupService(new File("geoip"));
Logger.printStatusTime("Initialized Geoip lookup service");
- ReverseDomainNameResolver rdnr = new ReverseDomainNameResolver(t);
+ ReverseDomainNameResolver rdnr = new ReverseDomainNameResolver();
Logger.printStatusTime("Initialized reverse domain name resolver");
- NodeDetailsStatusUpdater ndsu = new NodeDetailsStatusUpdater(dso,
- rdnr, ls, ds, t);
+ NodeDetailsStatusUpdater ndsu = new NodeDetailsStatusUpdater(rdnr,
+ ls);
Logger.printStatusTime("Initialized node data writer");
- BandwidthStatusUpdater bsu = new BandwidthStatusUpdater(dso, ds, t);
+ BandwidthStatusUpdater bsu = new BandwidthStatusUpdater();
Logger.printStatusTime("Initialized bandwidth status updater");
- WeightsStatusUpdater wsu = new WeightsStatusUpdater(dso, ds, t);
+ WeightsStatusUpdater wsu = new WeightsStatusUpdater();
Logger.printStatusTime("Initialized weights status updater");
- ClientsStatusUpdater csu = new ClientsStatusUpdater(dso, ds, t);
+ ClientsStatusUpdater csu = new ClientsStatusUpdater();
Logger.printStatusTime("Initialized clients status updater");
- UptimeStatusUpdater usu = new UptimeStatusUpdater(dso, ds);
+ UptimeStatusUpdater usu = new UptimeStatusUpdater();
Logger.printStatusTime("Initialized uptime status updater");
StatusUpdater[] sus = new StatusUpdater[] { ndsu, bsu, wsu, csu,
usu };
- DetailsDocumentWriter ddw = new DetailsDocumentWriter(dso, ds, t);
+ DetailsDocumentWriter ddw = new DetailsDocumentWriter();
Logger.printStatusTime("Initialized details document writer");
- BandwidthDocumentWriter bdw = new BandwidthDocumentWriter(dso, ds, t);
+ BandwidthDocumentWriter bdw = new BandwidthDocumentWriter();
Logger.printStatusTime("Initialized bandwidth document writer");
- WeightsDocumentWriter wdw = new WeightsDocumentWriter(dso, ds, t);
+ WeightsDocumentWriter wdw = new WeightsDocumentWriter();
Logger.printStatusTime("Initialized weights document writer");
- ClientsDocumentWriter cdw = new ClientsDocumentWriter(dso, ds, t);
+ ClientsDocumentWriter cdw = new ClientsDocumentWriter();
Logger.printStatusTime("Initialized clients document writer");
- UptimeDocumentWriter udw = new UptimeDocumentWriter(dso, ds, t);
+ UptimeDocumentWriter udw = new UptimeDocumentWriter();
Logger.printStatusTime("Initialized uptime document writer");
DocumentWriter[] dws = new DocumentWriter[] { ddw, bdw, wdw, cdw,
udw };
diff --git a/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java b/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java
index 2cf5061..4d32b2c 100644
--- a/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java
+++ b/src/org/torproject/onionoo/NodeDetailsStatusUpdater.java
@@ -49,15 +49,14 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
private int relayConsensusesProcessed = 0, bridgeStatusesProcessed = 0;
- public NodeDetailsStatusUpdater(DescriptorSource descriptorSource,
+ public NodeDetailsStatusUpdater(
ReverseDomainNameResolver reverseDomainNameResolver,
- LookupService lookupService, DocumentStore documentStore,
- Time time) {
- this.descriptorSource = descriptorSource;
+ LookupService lookupService) {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
this.reverseDomainNameResolver = reverseDomainNameResolver;
this.lookupService = lookupService;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerDescriptorListeners();
}
diff --git a/src/org/torproject/onionoo/RequestHandler.java b/src/org/torproject/onionoo/RequestHandler.java
index 6a25549..89871ae 100644
--- a/src/org/torproject/onionoo/RequestHandler.java
+++ b/src/org/torproject/onionoo/RequestHandler.java
@@ -31,10 +31,9 @@ public class RequestHandler {
relaysByLastSeenDays = null, bridgesByLastSeenDays = null;
private static final long SUMMARY_MAX_AGE = DateTimeHelper.SIX_HOURS;
- public static void initialize(DocumentStore documentStoreParam,
- Time timeParam) {
- documentStore = documentStoreParam;
- time = timeParam;
+ public static void initialize() {
+ documentStore = ApplicationFactory.getDocumentStore();
+ time = ApplicationFactory.getTime();
readSummaryFile();
}
diff --git a/src/org/torproject/onionoo/ResourceServlet.java b/src/org/torproject/onionoo/ResourceServlet.java
index 0c01d9f..dcfefc5 100644
--- a/src/org/torproject/onionoo/ResourceServlet.java
+++ b/src/org/torproject/onionoo/ResourceServlet.java
@@ -31,19 +31,18 @@ public class ResourceServlet extends HttpServlet {
config.getInitParameter("maintenance") != null
&& config.getInitParameter("maintenance").equals("1");
File outDir = new File(config.getInitParameter("outDir"));
- Time time = new Time();
- DocumentStore documentStore = new DocumentStore(outDir, time);
- this.init(maintenanceMode, documentStore, time);
+ DocumentStore documentStore = ApplicationFactory.getDocumentStore();
+ documentStore.setOutDir(outDir);
+ this.init(maintenanceMode);
}
/* Called (indirectly) by servlet container and (directly) by test
* class. */
- protected void init(boolean maintenanceMode,
- DocumentStore documentStore, Time time) {
+ protected void init(boolean maintenanceMode) {
this.maintenanceMode = maintenanceMode;
if (!maintenanceMode) {
- RequestHandler.initialize(documentStore, time);
- ResponseBuilder.initialize(documentStore);
+ RequestHandler.initialize();
+ ResponseBuilder.initialize();
}
}
diff --git a/src/org/torproject/onionoo/ResponseBuilder.java b/src/org/torproject/onionoo/ResponseBuilder.java
index 69b5c62..a841d29 100644
--- a/src/org/torproject/onionoo/ResponseBuilder.java
+++ b/src/org/torproject/onionoo/ResponseBuilder.java
@@ -11,8 +11,8 @@ public class ResponseBuilder {
private static DocumentStore documentStore;
- public static void initialize(DocumentStore documentStoreParam) {
- documentStore = documentStoreParam;
+ public static void initialize() {
+ documentStore = ApplicationFactory.getDocumentStore();
}
private String resourceType;
diff --git a/src/org/torproject/onionoo/ReverseDomainNameResolver.java b/src/org/torproject/onionoo/ReverseDomainNameResolver.java
index e762811..3dbf9d1 100644
--- a/src/org/torproject/onionoo/ReverseDomainNameResolver.java
+++ b/src/org/torproject/onionoo/ReverseDomainNameResolver.java
@@ -85,8 +85,8 @@ public class ReverseDomainNameResolver {
private Time time;
- public ReverseDomainNameResolver(Time time) {
- this.time = time;
+ public ReverseDomainNameResolver() {
+ this.time = ApplicationFactory.getTime();
}
private static final long RDNS_LOOKUP_MAX_REQUEST_MILLIS =
diff --git a/src/org/torproject/onionoo/UptimeDocumentWriter.java b/src/org/torproject/onionoo/UptimeDocumentWriter.java
index a7b1bba..6b44b24 100644
--- a/src/org/torproject/onionoo/UptimeDocumentWriter.java
+++ b/src/org/torproject/onionoo/UptimeDocumentWriter.java
@@ -17,11 +17,10 @@ public class UptimeDocumentWriter implements FingerprintListener,
private long now;
- public UptimeDocumentWriter(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public UptimeDocumentWriter() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerFingerprintListeners();
}
diff --git a/src/org/torproject/onionoo/UptimeStatusUpdater.java b/src/org/torproject/onionoo/UptimeStatusUpdater.java
index 97a6be1..4430387 100644
--- a/src/org/torproject/onionoo/UptimeStatusUpdater.java
+++ b/src/org/torproject/onionoo/UptimeStatusUpdater.java
@@ -20,10 +20,9 @@ public class UptimeStatusUpdater implements DescriptorListener,
private DocumentStore documentStore;
- public UptimeStatusUpdater(DescriptorSource descriptorSource,
- DocumentStore documentStore) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
+ public UptimeStatusUpdater() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
this.registerDescriptorListeners();
}
diff --git a/src/org/torproject/onionoo/WeightsDocumentWriter.java b/src/org/torproject/onionoo/WeightsDocumentWriter.java
index 8dcca0a..d2f2a67 100644
--- a/src/org/torproject/onionoo/WeightsDocumentWriter.java
+++ b/src/org/torproject/onionoo/WeightsDocumentWriter.java
@@ -20,11 +20,10 @@ public class WeightsDocumentWriter implements FingerprintListener,
private long now;
- public WeightsDocumentWriter(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public WeightsDocumentWriter() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerFingerprintListeners();
}
diff --git a/src/org/torproject/onionoo/WeightsStatusUpdater.java b/src/org/torproject/onionoo/WeightsStatusUpdater.java
index 1e5d559..d3ddff1 100644
--- a/src/org/torproject/onionoo/WeightsStatusUpdater.java
+++ b/src/org/torproject/onionoo/WeightsStatusUpdater.java
@@ -26,11 +26,10 @@ public class WeightsStatusUpdater implements DescriptorListener,
private long now;
- public WeightsStatusUpdater(DescriptorSource descriptorSource,
- DocumentStore documentStore, Time time) {
- this.descriptorSource = descriptorSource;
- this.documentStore = documentStore;
- this.now = time.currentTimeMillis();
+ public WeightsStatusUpdater() {
+ this.descriptorSource = ApplicationFactory.getDescriptorSource();
+ this.documentStore = ApplicationFactory.getDocumentStore();
+ this.now = ApplicationFactory.getTime().currentTimeMillis();
this.registerDescriptorListeners();
}
diff --git a/test/org/torproject/onionoo/DummyDocumentStore.java b/test/org/torproject/onionoo/DummyDocumentStore.java
index 2f32833..c7ca7ff 100644
--- a/test/org/torproject/onionoo/DummyDocumentStore.java
+++ b/test/org/torproject/onionoo/DummyDocumentStore.java
@@ -1,6 +1,5 @@
package org.torproject.onionoo;
-import java.io.File;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
@@ -10,8 +9,7 @@ public class DummyDocumentStore extends DocumentStore {
private long lastModified;
- public DummyDocumentStore(long lastModified, Time time) {
- super((File) null, time);
+ public DummyDocumentStore(long lastModified) {
this.lastModified = lastModified;
}
diff --git a/test/org/torproject/onionoo/ResourceServletTest.java b/test/org/torproject/onionoo/ResourceServletTest.java
index 37963c8..3b8b5ae 100644
--- a/test/org/torproject/onionoo/ResourceServletTest.java
+++ b/test/org/torproject/onionoo/ResourceServletTest.java
@@ -32,21 +32,21 @@ public class ResourceServletTest {
private SortedMap<String, String> relays, bridges;
- private DummyDocumentStore documentStore;
-
// 2013-04-24 12:22:22
private static long lastModified = 1366806142000L;
private long currentTimeMillis = 1366806142000L;
private class TestingTime extends Time {
+ private long currentTimeMillis;
+ public TestingTime(long currentTimeMillis) {
+ this.currentTimeMillis = currentTimeMillis;
+ }
public long currentTimeMillis() {
- return currentTimeMillis;
+ return this.currentTimeMillis;
}
}
- private Time testingTime = new TestingTime();
-
private boolean maintenanceMode = false;
private class TestingHttpServletRequestWrapper
@@ -155,6 +155,7 @@ public class ResourceServletTest {
private void runTest(String requestURI,
Map<String, String[]> parameterMap) {
try {
+ this.createDummyTime();
this.createDummyDocumentStore();
this.makeRequest(requestURI, parameterMap);
this.parseResponse();
@@ -163,25 +164,31 @@ public class ResourceServletTest {
}
}
+ private void createDummyTime() {
+ Time dummyTime = new TestingTime(this.currentTimeMillis);
+ ApplicationFactory.setTime(dummyTime);
+ }
+
private void createDummyDocumentStore() {
/* TODO Incrementing static lastModified is necessary for
* ResponseBuilder to read state from the newly created DocumentStore.
* Otherwise, ResponseBuilder would use data from the previous test
* run. This is bad design and should be fixed. */
- this.documentStore = new DummyDocumentStore(lastModified++,
- this.testingTime);
+ DummyDocumentStore documentStore = new DummyDocumentStore(
+ lastModified++);
for (String relay : relays.values()) {
documentStore.addNodeStatus(relay);
}
for (String bridge : bridges.values()) {
documentStore.addNodeStatus(bridge);
}
+ ApplicationFactory.setDocumentStore(documentStore);
}
private void makeRequest(String requestURI,
Map<String, String[]> parameterMap) throws IOException {
ResourceServlet rs = new ResourceServlet();
- rs.init(maintenanceMode, this.documentStore, this.testingTime);
+ rs.init(this.maintenanceMode);
this.request = new TestingHttpServletRequestWrapper(requestURI,
parameterMap);
this.response = new TestingHttpServletResponseWrapper();
1
0

14 Apr '14
commit 56695bcbaa409644b2036c508f4d0cf80796241a
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Sat Apr 12 18:41:29 2014 +0200
Fix minor bug in writing uptime documents.
When a relay first showed up in the middle of a, say, 4-hour interval, we
discounted its uptime in that interval by the number of hours that it
wasn't online. We should ignore those hours.
---
.../torproject/onionoo/UptimeDocumentWriter.java | 79 +++++++++++---------
1 file changed, 44 insertions(+), 35 deletions(-)
diff --git a/src/org/torproject/onionoo/UptimeDocumentWriter.java b/src/org/torproject/onionoo/UptimeDocumentWriter.java
index 60ca311..14c800d 100644
--- a/src/org/torproject/onionoo/UptimeDocumentWriter.java
+++ b/src/org/torproject/onionoo/UptimeDocumentWriter.java
@@ -129,14 +129,18 @@ public class UptimeDocumentWriter implements FingerprintListener,
this.dataPointIntervals[graphIntervalIndex];
int dataPointIntervalHours = (int) (dataPointInterval
/ DateTimeHelper.ONE_HOUR);
- List<Integer> statusDataPoints = new ArrayList<Integer>();
+ List<Integer> uptimeDataPoints = new ArrayList<Integer>();
long intervalStartMillis = ((this.now - graphInterval)
/ dataPointInterval) * dataPointInterval;
- int statusHours = 0;
- for (UptimeHistory hist : knownStatuses) {
+ int uptimeHours = 0;
+ long firstStatusStartMillis = -1L;
+ for (UptimeHistory hist : history) {
if (hist.isRelay() != relay) {
continue;
}
+ if (firstStatusStartMillis < 0L) {
+ firstStatusStartMillis = hist.getStartMillis();
+ }
long histEndMillis = hist.getStartMillis() + DateTimeHelper.ONE_HOUR
* hist.getUptimeHours();
if (histEndMillis < intervalStartMillis) {
@@ -144,38 +148,36 @@ public class UptimeDocumentWriter implements FingerprintListener,
}
while (hist.getStartMillis() >= intervalStartMillis
+ dataPointInterval) {
- statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
- ? statusHours : -1);
- statusHours = 0;
+ if (firstStatusStartMillis < intervalStartMillis
+ + dataPointInterval) {
+ uptimeDataPoints.add(uptimeHours);
+ } else {
+ uptimeDataPoints.add(-1);
+ }
+ uptimeHours = 0;
intervalStartMillis += dataPointInterval;
}
while (histEndMillis >= intervalStartMillis + dataPointInterval) {
- statusHours += (int) ((intervalStartMillis + dataPointInterval
+ uptimeHours += (int) ((intervalStartMillis + dataPointInterval
- Math.max(hist.getStartMillis(), intervalStartMillis))
/ DateTimeHelper.ONE_HOUR);
- statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
- ? statusHours : -1);
- statusHours = 0;
+ uptimeDataPoints.add(uptimeHours);
+ uptimeHours = 0;
intervalStartMillis += dataPointInterval;
}
- statusHours += (int) ((histEndMillis - Math.max(
+ uptimeHours += (int) ((histEndMillis - Math.max(
hist.getStartMillis(), intervalStartMillis))
/ DateTimeHelper.ONE_HOUR);
}
- statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
- ? statusHours : -1);
- List<Integer> uptimeDataPoints = new ArrayList<Integer>();
+ uptimeDataPoints.add(uptimeHours);
+ List<Integer> statusDataPoints = new ArrayList<Integer>();
intervalStartMillis = ((this.now - graphInterval)
/ dataPointInterval) * dataPointInterval;
- int uptimeHours = 0;
- long firstStatusStartMillis = -1L;
- for (UptimeHistory hist : history) {
+ int statusHours = -1;
+ for (UptimeHistory hist : knownStatuses) {
if (hist.isRelay() != relay) {
continue;
}
- if (firstStatusStartMillis < 0L) {
- firstStatusStartMillis = hist.getStartMillis();
- }
long histEndMillis = hist.getStartMillis() + DateTimeHelper.ONE_HOUR
* hist.getUptimeHours();
if (histEndMillis < intervalStartMillis) {
@@ -183,28 +185,35 @@ public class UptimeDocumentWriter implements FingerprintListener,
}
while (hist.getStartMillis() >= intervalStartMillis
+ dataPointInterval) {
- if (firstStatusStartMillis < intervalStartMillis
- + dataPointInterval) {
- uptimeDataPoints.add(uptimeHours);
- } else {
- uptimeDataPoints.add(-1);
- }
- uptimeHours = 0;
+ statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
+ ? statusHours : -1);
+ statusHours = -1;
intervalStartMillis += dataPointInterval;
}
while (histEndMillis >= intervalStartMillis + dataPointInterval) {
- uptimeHours += (int) ((intervalStartMillis + dataPointInterval
- - Math.max(hist.getStartMillis(), intervalStartMillis))
+ if (statusHours < 0) {
+ statusHours = 0;
+ }
+ statusHours += (int) ((intervalStartMillis + dataPointInterval
+ - Math.max(Math.max(hist.getStartMillis(),
+ firstStatusStartMillis), intervalStartMillis))
/ DateTimeHelper.ONE_HOUR);
- uptimeDataPoints.add(uptimeHours);
- uptimeHours = 0;
+ statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
+ ? statusHours : -1);
+ statusHours = -1;
intervalStartMillis += dataPointInterval;
}
- uptimeHours += (int) ((histEndMillis - Math.max(
- hist.getStartMillis(), intervalStartMillis))
- / DateTimeHelper.ONE_HOUR);
+ if (statusHours < 0) {
+ statusHours = 0;
+ }
+ statusHours += (int) ((histEndMillis - Math.max(Math.max(
+ hist.getStartMillis(), firstStatusStartMillis),
+ intervalStartMillis)) / DateTimeHelper.ONE_HOUR);
+ }
+ if (statusHours > 0) {
+ statusDataPoints.add(statusHours * 5 > dataPointIntervalHours
+ ? statusHours : -1);
}
- uptimeDataPoints.add(uptimeHours);
List<Double> dataPoints = new ArrayList<Double>();
for (int dataPointIndex = 0; dataPointIndex < statusDataPoints.size();
dataPointIndex++) {
1
0