commit 99f87e820289d1fdba7d6362cb8bb84693f09c94 Author: Karsten Loesing karsten.loesing@gmx.net Date: Thu Sep 29 17:21:43 2016 +0200
Remove module on disagreement among dirauths.
Implements #20227. --- .../org/torproject/metrics/collectdescs/Main.java | 1 - modules/disagreement/.gitignore | 2 - modules/disagreement/build.xml | 38 -- .../org/torproject/metrics/disagreement/Main.java | 642 --------------------- shared/bin/20-run-disagreement-stats.sh | 5 - shared/bin/99-copy-stats-files.sh | 1 - website/etc/metrics.json | 4 +- 7 files changed, 2 insertions(+), 691 deletions(-)
diff --git a/modules/collectdescs/src/org/torproject/metrics/collectdescs/Main.java b/modules/collectdescs/src/org/torproject/metrics/collectdescs/Main.java index 88955b4..8be2e0b 100644 --- a/modules/collectdescs/src/org/torproject/metrics/collectdescs/Main.java +++ b/modules/collectdescs/src/org/torproject/metrics/collectdescs/Main.java @@ -24,7 +24,6 @@ public class Main { "/recent/relay-descriptors/consensuses/", "/recent/relay-descriptors/extra-infos/", "/recent/relay-descriptors/server-descriptors/", - "/recent/relay-descriptors/votes/", "/recent/torperf/" }, 0L, new File("../../shared/in"), true); } diff --git a/modules/disagreement/.gitignore b/modules/disagreement/.gitignore deleted file mode 100644 index bb84c80..0000000 --- a/modules/disagreement/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -stats/ - diff --git a/modules/disagreement/build.xml b/modules/disagreement/build.xml deleted file mode 100644 index aed679b..0000000 --- a/modules/disagreement/build.xml +++ /dev/null @@ -1,38 +0,0 @@ -<project default="run" name="disagreement" basedir="."> - - <property name="disagreement-sources" value="src/main/java"/> - <property name="disagreement-libs" value="../../shared/lib"/> - <property name="disagreement-classes" value="classes"/> - <path id="classpath"> - <pathelement path="${disagreement-classes}"/> - <fileset dir="${disagreement-libs}"> - <include name="descriptor-1.2.0.jar"/> - <include name="commons-compress-1.9.jar"/> - <include name="xz-1.0.jar"/> - </fileset> - </path> - - <target name="compile"> - <mkdir dir="${disagreement-classes}"/> - <javac destdir="${disagreement-classes}" - srcdir="${disagreement-sources}" - source="1.7" - target="1.7" - debug="true" - deprecation="true" - optimize="false" - failonerror="true" - includeantruntime="false"> - <classpath refid="classpath"/> - </javac> - </target> - - <target name="run" depends="compile"> - <java fork="true" - maxmemory="2g" - classname="org.torproject.metrics.disagreement.Main"> - <classpath refid="classpath"/> - </java> - </target> -</project> - diff --git a/modules/disagreement/src/main/java/org/torproject/metrics/disagreement/Main.java b/modules/disagreement/src/main/java/org/torproject/metrics/disagreement/Main.java deleted file mode 100644 index 05159a3..0000000 --- a/modules/disagreement/src/main/java/org/torproject/metrics/disagreement/Main.java +++ /dev/null @@ -1,642 +0,0 @@ -/* Copyright 2016 The Tor Project - * See LICENSE for licensing information */ - -package org.torproject.metrics.disagreement; - -import org.torproject.descriptor.Descriptor; -import org.torproject.descriptor.DescriptorFile; -import org.torproject.descriptor.DescriptorReader; -import org.torproject.descriptor.DescriptorSourceFactory; -import org.torproject.descriptor.NetworkStatusEntry; -import org.torproject.descriptor.RelayNetworkStatusVote; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.LineNumberReader; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.TimeZone; -import java.util.TreeMap; - -/* Read all relay network status votes from the in/ subdirectory with a - * valid-after time of 12:00:00, extract attributes like relay flags or - * bandwidth measurements that the directory authorities assigned to - * relays, and output aggregate statistics on disagreement among the - * directory authorities. - * - * When initializing from descriptor archives, put tarballs in the in/ - * subdirectory, run this code, and then move the tarballs away. - * Otherwise, tarballs will be re-processed in each subsequent execution. - * - * Recent descriptors can stay in the in/ subdirectory and be re-processed - * in each execution. */ -public class Main { - - /** Creates a new instance of this class that executes this - * data-processing module. */ - public static void main(String[] args) throws Exception { - new Main().run(); - } - - /** Executes this data-processing module. */ - public void run() throws Exception { - readResults(); - readDescriptors(); - aggregate(); - writeResults(); - } - - /* We're processing a lot of strings, including authority identities, - * relay fingerprints, and attributes like relay flags. It would be - * wasteful to store more than one instance of these strings in memory. - * We also want to store them as part of long integers below. - * - * That's why we're resolving all strings to integers and keeping maps - * from string to integers. In case of authority identities and relay - * fingerprints we don't need to resolve integers back to strings, but - * in case of attributes we need to put attribute strings into the - * output file, so we're also keeping a list of attribute strings in - * insertion order. */ - private Map<String, Integer> authorityIndexes = - new HashMap<String, Integer>(); - private Map<String, Integer> fingerprintIndexes = - new HashMap<String, Integer>(); - private Map<String, Integer> attributeIndexes = - new HashMap<String, Integer>(); - private List<String> attributeStrings = new ArrayList<String>(); - - /** Initializes this class. */ - public Main() { - - /* Initialize maps from strings to integers and back by adding the - * empty string as 0-th element. This is necessary, because we want - * to be able to treat 0 as special case below. Once we add non-empty - * strings to maps, they'll be indexed starting at 1. */ - this.getAuthorityIndexForString(""); - this.getFingerprintIndexForString(""); - this.getAttributeIndexForString(""); - } - - /* Resolve the given authority string to its authority index, possibly - * after adding it to the mapping if it wasn't contained before. */ - protected int getAuthorityIndexForString(String authorityString) { - return putToMapsAndReturnIndex(this.authorityIndexes, null, - authorityString); - } - - /* Resolve the given fingerprint string to its fingerprint index, - * possibly after adding it to the mapping if it wasn't contained - * before. */ - protected int getFingerprintIndexForString(String fingerprintString) { - return putToMapsAndReturnIndex(this.fingerprintIndexes, null, - fingerprintString); - } - - /* Resolve the given attribute string to its attribute index, possibly - * after adding it to the mapping if it wasn't contained before. */ - protected int getAttributeIndexForString(String attributeString) { - return putToMapsAndReturnIndex(this.attributeIndexes, - this.attributeStrings, attributeString); - } - - /* Resolve the given attribute index to its attribute string, or return - * null if this attribute index doesn't exist. */ - protected String getAttributeStringForIndex(int attributeIndex) { - if (attributeIndex < 0 || attributeIndex >= attributeStrings.size()) { - return null; - } else { - return this.attributeStrings.get(attributeIndex); - } - } - - /* Helper method: Return an index for a given string and possibly put - * the string into the map and corresponding list if it was not - * contained before. */ - protected int putToMapsAndReturnIndex( - Map<String, Integer> stringToIntMap, List<String> strings, - String string) { - Integer index = stringToIntMap.get(string); - if (index == null) { - if (strings != null) { - strings.add(string); - } - stringToIntMap.put(string, stringToIntMap.size()); - } - return stringToIntMap.get(string); - } - - /* The following code is heavily optimized towards low memory usage, - * because we're potentially processing a lot of data, especially when - * initializing from descriptor archives. - * - * We need to be able to store weeks or even months of votes in memory, - * which is really a lot of data. The reason is that we need all votes - * published at the same hour to be present when running aggregations, - * but we cannot rely on the order of incoming votes. That's why we - * have to process votes in two steps: first, we extract everything we - * need from votes and store it in memory, and second, we aggregate what - * we have in memory and output aggregate results. - * - * We're going rather low-level here by converting each attribute that - * an authority assigned to a relay at a certain vote valid-after time - * into a single 64-bit signed long integer. We're doing this by - * subdividing (most of) the available bits into ranges for the - * different parts we want to store. As an added requirement we're - * arranging ranges in a way that we can later process long values in - * sorted order without keeping much state. Ranges are: - * - 22 bits for the valid-after time in half hours since 1970-01-01 - * 00:00:00 (which won't overflow until year 2209), - * - 8 bits for the attribute index (which allows up to 253 different - * relay flags in addition to reserved 0, "Listed", and - * "Measured"), - * - 24 bits for the fingerprint index (which allows over 16 million - * different relay fingerprints in the current execution), and - * - 6 bits for the authority index (which allows up to 63 different - * authorities in addition to the reserved 0). - * - * If any of these numbers overflows during the execution, we'll detect - * that, suggest to process less data at once, and exit with an error. - * Still, it should be possible to process months of data in a single - * execution. For example, one set of votes published at the same - * valid-after hour in December 2015 required to keep 420,000 long - * values in memory, which is roughly 3.2 MiB plus list overhead. */ - protected List<Long> assignments = new ArrayList<Long>(); - - protected static final int VALIDAFTER_LEN = 22; - - protected static final int ATTRIBUTE_LEN = 8; - - protected static final int FINGERPRINT_LEN = 24; - - protected static final int AUTHORITY_LEN = 6; - - protected static final int VALIDAFTER_SHIFT = ATTRIBUTE_LEN - + FINGERPRINT_LEN + AUTHORITY_LEN; - - protected static final int ATTRIBUTE_SHIFT = FINGERPRINT_LEN - + AUTHORITY_LEN; - - protected static final int FINGERPRINT_SHIFT = AUTHORITY_LEN; - - protected static final int AUTHORITY_SHIFT = 0; - - /* Define some constants for timestamp math. */ - protected static final long HALF_HOUR = 30L * 60L * 1000L; - - protected static final long ONE_HOUR = 2L * HALF_HOUR; - - protected static final long HALF_DAY = 12L * ONE_HOUR; - - protected static final long ONE_DAY = 2L * HALF_DAY; - - /* Convert the given valid-after time in milliseconds, attribute index, - * fingerprint index, and authority index to a long integer following - * the conversion rules stated above. Return -1 in case of - * overflows. */ - protected static long convertToLongValue(long validAfterMillis, - int attributeIndex, int fingerprintIndex, int authorityIndex) { - long validAfterHalfHours = validAfterMillis / HALF_HOUR; - if (validAfterHalfHours < 0L - || validAfterHalfHours >= (1L << VALIDAFTER_LEN)) { - return -1; - } - if (attributeIndex < 0 || attributeIndex >= (1 << ATTRIBUTE_LEN)) { - return -1; - } - if (fingerprintIndex < 0 - || fingerprintIndex >= (1 << FINGERPRINT_LEN)) { - return -1; - } - if (authorityIndex < 0 || authorityIndex >= (1 << AUTHORITY_LEN)) { - return -1; - } - long longValue = (validAfterHalfHours << VALIDAFTER_SHIFT) - + ((long) attributeIndex << ATTRIBUTE_SHIFT) - + ((long) fingerprintIndex << FINGERPRINT_SHIFT) - + ((long) authorityIndex << AUTHORITY_SHIFT); - return longValue; - } - - /* Extract the valid-after time in milliseconds from the given long - * integer value. */ - protected static long extractValidAfterMillisFromLongValue( - long longValue) { - return (longValue >> VALIDAFTER_SHIFT) * HALF_HOUR; - } - - /* Extract the attribute index from the given long integer value. */ - protected static int extractAttributeIndexFromLongValue( - long longValue) { - return (int) ((longValue >> ATTRIBUTE_SHIFT) % (1 << ATTRIBUTE_LEN)); - } - - /* Extract the fingerprint index from the given long integer value. */ - protected static int extractFingerprintIndexFromLongValue( - long longValue) { - return (int) ((longValue >> FINGERPRINT_SHIFT) - % (1 << FINGERPRINT_LEN)); - } - - /* Extract the authority index from the given long integer value. */ - protected static int extractAuthorityIndexFromLongValue( - long longValue) { - return (int) ((longValue >> AUTHORITY_SHIFT) % (1 << AUTHORITY_LEN)); - } - - /* Keep all aggregated results in memory, so that we easily merge new - * results obtained in the current execution. - * - * Another reason for keeping all results in memory is that we may have - * processed some votes from a given valid-after time before, and now we - * need to decide whether we keep old results or replace them with new - * results. We decide this by using results that are based on more - * votes, which could be old or new results. - * - * Map keys are valid-after times formatted as strings, map values are - * sorted lists of all subsequent columns starting with that valid-after - * time. */ - protected SortedMap<String, List<String>> results = - new TreeMap<String, List<String>>(); - - /* Store all results in this .csv file. */ - protected File resultsFile = new File("stats/disagreement.csv"); - - /* Use the following .csv header line for results. */ - protected String resultsHeaderLine = - "validafter,attribute,votes,required,max,relays"; - - /* Read results from the previous execution to memory and do some minor - * validation of the file format while doing so. Return immediately - * without error if the file does not exist (yet). */ - private void readResults() throws Exception { - if (!this.resultsFile.exists()) { - return; - } - LineNumberReader lnr = new LineNumberReader(new BufferedReader( - new FileReader(this.resultsFile))); - String line; - if ((line = lnr.readLine()) == null - || !line.equals(this.resultsHeaderLine)) { - lnr.close(); - throw new IOException("Unexpected line " + lnr.getLineNumber() - + " in " + this.resultsFile + "."); - } - while ((line = lnr.readLine()) != null) { - if (!line.contains(",")) { - lnr.close(); - throw new IOException("Cannot parse invalid line " - + lnr.getLineNumber() + " in " + this.resultsFile + "."); - } - int indexOfFirstComma = line.indexOf(","); - String validafter = line.substring(0, indexOfFirstComma); - String otherColumns = line.substring(indexOfFirstComma); - if (!this.results.containsKey(validafter)) { - this.results.put(validafter, new ArrayList<String>()); - } - this.results.get(validafter).add(otherColumns); - } - lnr.close(); - } - - /* Write results to the results file. More precisely, write them to a - * temporary file and rename it to the target file to avoid failing half - * way through and losing the previous results file. */ - private void writeResults() throws Exception { - this.resultsFile.getParentFile().mkdirs(); - File resultsTmpFile = new File(this.resultsFile + ".tmp"); - BufferedWriter bw = new BufferedWriter(new FileWriter( - resultsTmpFile)); - bw.write(this.resultsHeaderLine + "\n"); - for (Map.Entry<String, List<String>> e : this.results.entrySet()) { - String validafter = e.getKey(); - for (String otherColumns : e.getValue()) { - bw.write(validafter + otherColumns + "\n"); - } - } - bw.close(); - resultsTmpFile.renameTo(this.resultsFile); - } - - /* Read relay network status votes from this directory. */ - protected File[] inDirectories = new File[] { - new File("../../shared/in/archive/relay-descriptors/votes"), - new File("../../shared/in/recent/relay-descriptors/votes") - }; - - /* Read relay network status votes from disk and extract all relevant - * pieces from them. */ - protected void readDescriptors() throws Exception { - DescriptorReader descriptorReader = - DescriptorSourceFactory.createDescriptorReader(); - descriptorReader.setMaxDescriptorFilesInQueue(5); - for (File inDirectory : this.inDirectories) { - descriptorReader.addDirectory(inDirectory); - } - Iterator<DescriptorFile> descriptorFiles = - descriptorReader.readDescriptors(); - while (descriptorFiles.hasNext()) { - DescriptorFile descriptorFile = descriptorFiles.next(); - for (Descriptor descriptor : descriptorFile.getDescriptors()) { - if ((descriptor instanceof RelayNetworkStatusVote)) { - RelayNetworkStatusVote vote = - (RelayNetworkStatusVote) descriptor; - processVote(vote); - } - } - } - } - - private static final String LISTED_ATTRIBUTE = "Listed"; - - private static final String MEASURED_ATTRIBUTE = "Measured"; - - /* Process a single relay network status vote. */ - private void processVote(RelayNetworkStatusVote vote) throws Exception { - long validAfterMillis = vote.getValidAfterMillis(); - if (validAfterMillis % ONE_DAY != HALF_DAY) { - /* Only process votes with a valid-after time of 12:00:00 as a means - * to reduce the overall amount of data. */ - return; - } - - /* Use the authority's identity to distinguish votes. */ - String authorityIdentity = vote.getIdentity(); - - /* Collect a set of all attributes that the authority assigns in this - * vote, which includes all known flags, the general "Listed" - * attribute for listing relays, and possibly the "Measured" attribute - * for bandwidth-measured relays. */ - Set<String> knownAttributes = new HashSet<String>( - vote.getKnownFlags()); - knownAttributes.add(LISTED_ATTRIBUTE); - - /* Go through all status entries in this vote and remember which - * attributes this authority assigns to which relays. */ - for (NetworkStatusEntry entry - : vote.getStatusEntries().values()) { - - /* Use the relay's fingerprint to distinguish relays. */ - String fingerprint = entry.getFingerprint(); - - /* Compile a set of all attributes assigned to this relay, including - * all relay flags, "Listed", and possibly "Measured". */ - Set<String> attributes = new HashSet<String>(entry.getFlags()); - attributes.add(LISTED_ATTRIBUTE); - if (entry.getMeasured() >= 0L) { - attributes.add(MEASURED_ATTRIBUTE); - knownAttributes.add(MEASURED_ATTRIBUTE); - } - - /* Remember all attributes assigned to this relay. */ - this.addAssignedAttributes(validAfterMillis, attributes, - fingerprint, authorityIdentity); - } - - /* Remember all attributes assigned by the authority in this vote. */ - this.addKnownAttributes(validAfterMillis, knownAttributes, - authorityIdentity); - - /* Remember all fingerprints voted on by the authority at the given - * valid-after time. */ - this.addKnownFingerprints(validAfterMillis, - vote.getStatusEntries().keySet()); - } - - /* Remember all attributes assigned to a given relay by an authority at - * a given valid-after time. These are converted to long integers - * with all components being non-zero. */ - protected void addAssignedAttributes(long validAfterMillis, - Set<String> attributes, String fingerprint, - String authorityIdentity) throws Exception { - int fingerprintIndex = this.getFingerprintIndexForString(fingerprint); - int authorityIndex = this.getAuthorityIndexForString( - authorityIdentity); - for (String attribute : attributes) { - int attributeIndex = this.getAttributeIndexForString(attribute); - long longValue = convertToLongValue(validAfterMillis, - attributeIndex, fingerprintIndex, authorityIndex); - if (longValue < 0L) { - throw new Exception("Could not convert vote data to the internal " - + "format. Try processing fewer votes at once."); - } - this.assignments.add(longValue); - } - } - - /* Remember all attributes voted on by an authority at a given - * valid-after time. These are converted to long integers with - * fingerprint component being zero. */ - protected void addKnownAttributes(long validAfterMillis, - Set<String> knownAttributes, String authorityIdentity) - throws Exception { - int authorityIndex = this.getAuthorityIndexForString( - authorityIdentity); - for (String attribute : knownAttributes) { - int attributeIndex = this.getAttributeIndexForString(attribute); - long longValue = convertToLongValue(validAfterMillis, - attributeIndex, 0, authorityIndex); - if (longValue < 0L) { - throw new Exception("Could not convert vote data to the internal " - + "format. Try processing fewer votes at once."); - } - this.assignments.add(longValue); - } - } - - /* Remember all fingerprints known by an authority at a given - * valid-after time. These are converted to long integers with - * attribute and authority component being zero. */ - protected void addKnownFingerprints(long validAfterMillis, - Set<String> knownFingerprints) throws Exception { - for (String fingerprint : knownFingerprints) { - int fingerprintIndex = this.getFingerprintIndexForString( - fingerprint); - long longValue = convertToLongValue(validAfterMillis, 0, - fingerprintIndex, 0); - if (longValue < 0L) { - throw new Exception("Could not convert vote data to the internal " - + "format. Try processing fewer votes at once."); - } - this.assignments.add(longValue); - } - } - - /* Aggregate everything we extracted from votes earlier into statistics - * on disagreement among directory authorities. */ - protected void aggregate() { - - /* Initialize a date format for formatting valid-after times. */ - DateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss", Locale.US); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - - /* Sort long integer values and append the largest possible long - * value, so that we can process values in the following order - * (columns are valid-after time, attribute, fingerprint, authority; - * + stands for a value > 0, 0 stands for 0): - * (+, 0, +, 0): all fingerprints known at a given valid-after time - * (+, +, 0, +): all attributes known by a given authority - * (+, +, +, +): attributes assigned to relays by authority - * ... - * (MAX_VALUE): end-of-list marker */ - Collections.sort(this.assignments); - this.assignments.add(Long.MAX_VALUE); - - /* Remember long value and some of its components from the last - * iteration. */ - long lastLongValue = -1L; - long lastValidAfterMillis = -1L; - int lastAttributeIndex = -1; - int lastFingerprintIndex = -1; - - /* Keep a list of all output lines for a single valid-after time. */ - List<String> outputLines = new ArrayList<String>(); - - /* Keep counters for the number of fingerprints seen at a valid-after - * time, the number of authorities voting on an attribute, and the - * number of votes that a relay received for a given attribute. */ - int knownFingerprintsByAllAuthorities = 0; - int authoritiesVotingOnAttribute = 0; - int votesForAttribute = 0; - - /* Keep counters of relays receiving a given number of votes on an - * attribute. The number at element i is the number of relays - * receiving i votes. */ - int[] relays = new int[(1 << AUTHORITY_LEN)]; - - /* Go through all long values in ascending order. */ - for (long longValue : this.assignments) { - - /* Skip duplicate values. */ - if (lastLongValue == longValue) { - continue; - } - - /* If we're looking at attributes assigned to relays and just moved - * from one non-zero fingerprint to the next, we need to wrap up - * results for the last fingerprint before moving on. */ - int fingerprintIndex = extractFingerprintIndexFromLongValue( - longValue); - if (lastAttributeIndex > 0 && lastFingerprintIndex > 0 - && lastFingerprintIndex != fingerprintIndex) { - - /* This relay received at least one vote for the given attribute, - * or otherwise it wouldn't be contained in the list of long - * values. Increment the counter for the number of votes we - * counted for this attribute, and then reset that counter. */ - relays[0]--; - relays[votesForAttribute]++; - votesForAttribute = 0; - } - - /* If we're looking at attributes and just moved from one non-zero - * attribute to the next, we need to wrap up results for the last - * attribute before moving on. And if we just moved to the first - * attribute, initialize counters. */ - int attributeIndex = extractAttributeIndexFromLongValue(longValue); - if (lastAttributeIndex >= 0 - && lastAttributeIndex != attributeIndex) { - - /* If we just finished a non-zero attribute, wrap it up. - * Determine the number of votes required for getting into the - * consensus, which is typically the majority of votes, except for - * the "Measured" attribute, where it's set to 3. Format one - * output line for each possible number of votes, from 0 to the - * total number of authorities voting on the attribute. */ - if (lastAttributeIndex > 0) { - String lastAttribute = this.getAttributeStringForIndex( - lastAttributeIndex); - int required = lastAttribute.equals(MEASURED_ATTRIBUTE) ? 3 - : (authoritiesVotingOnAttribute / 2) + 1; - for (int i = 0; i <= authoritiesVotingOnAttribute; i++) { - outputLines.add(String.format(",%s,%d,%d,%d,%d", - lastAttribute, i, required, authoritiesVotingOnAttribute, - relays[i])); - } - } - - /* Reset counters and initialize the bucket at index 0 with the - * total number of fingerprints known at this valid-after time. */ - authoritiesVotingOnAttribute = 0; - relays = new int[(1 << AUTHORITY_LEN)]; - relays[0] = knownFingerprintsByAllAuthorities; - } - - /* If we just moved from one valid-after time to the next, we need - * to wrap up results for the last valid-after time before moving - * on. */ - long validAfterMillis = extractValidAfterMillisFromLongValue( - longValue); - if (lastValidAfterMillis >= 0L - && lastValidAfterMillis < validAfterMillis) { - - /* Check if results already contain lines for this valid-after - * time. If so, only replace them with new results lines if there - * are more new lines than old lines. The rationale is that more - * lines are very likely based on more votes, and we want to - * include as many votes as possible in the aggregation. */ - String validAfterString = dateTimeFormat.format( - lastValidAfterMillis); - if (!this.results.containsKey(validAfterString) - || this.results.get(validAfterString).size() - < outputLines.size()) { - - /* Sort results lines, and then put them in. */ - Collections.sort(outputLines); - this.results.put(validAfterString, outputLines); - } - - /* Prepare for aggregating votes from the next valid-after - * time. */ - outputLines = new ArrayList<String>(); - knownFingerprintsByAllAuthorities = 0; - } - - /* If we reached our end-of-list marker, stop here. */ - if (longValue == Long.MAX_VALUE) { - break; - } - - /* Look at the current indexes and increment one of the three - * counters. If this value doesn't contain an attribute index, it - * was put in for counting all known fingerprints at this - * valid-after time. */ - if (attributeIndex == 0) { - knownFingerprintsByAllAuthorities++; - - /* Otherwise, if this value doesn't contain a fingerprint index, it - * was put in for counting authorities voting on a given attribute - * at the current valid-after time. */ - } else if (fingerprintIndex == 0) { - authoritiesVotingOnAttribute++; - - /* Otherwise, if both indexes are non-zero, this value was put in to - * count how many authorities assign the attribute to this relay at - * this valid-after time. */ - } else { - votesForAttribute++; - } - - /* Prepare moving on to the next value. */ - lastLongValue = longValue; - lastValidAfterMillis = validAfterMillis; - lastAttributeIndex = attributeIndex; - lastFingerprintIndex = fingerprintIndex; - } - } -} - diff --git a/shared/bin/20-run-disagreement-stats.sh b/shared/bin/20-run-disagreement-stats.sh deleted file mode 100755 index 9abe1e2..0000000 --- a/shared/bin/20-run-disagreement-stats.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -cd modules/disagreement/ -ant | grep "[java]" -cd ../../ - diff --git a/shared/bin/99-copy-stats-files.sh b/shared/bin/99-copy-stats-files.sh index 5ced875..504216a 100755 --- a/shared/bin/99-copy-stats-files.sh +++ b/shared/bin/99-copy-stats-files.sh @@ -6,5 +6,4 @@ cp -a modules/advbwdist/stats/advbwdist.csv shared/stats/ cp -a modules/hidserv/stats/hidserv.csv shared/stats/ cp -a modules/clients/stats/clients.csv shared/stats/ cp -a modules/clients/stats/userstats-combined.csv shared/stats/ -cp -a modules/disagreement/stats/disagreement.csv shared/stats/
diff --git a/website/etc/metrics.json b/website/etc/metrics.json index 64633ca..ffec652 100644 --- a/website/etc/metrics.json +++ b/website/etc/metrics.json @@ -870,13 +870,13 @@ }, { "id": "disagreement-data", - "title": "Disagreement among the directory authorities", + "title": "Disagreement among the directory authorities (deprecated)", "tags": [ "Relays" ], "type": "Data", "level": "Advanced", - "description": "<p>The following data file contains statistics about agreement or disagreement among the <a href="about.html#directory-authority">directory authorities</a>. Once per hour the directory authorities exchange votes with their view of the <a href="about.html#relay">relays</a> in the network including attributes like <a href="about.html#relay-flag">relay flags</a> or bandwidth measurements. This data file includes counts of relays by number of directory authorities assigning them a given attribute.</p>", + "description": "<p><font color="red">As of September 29, 2016, the linked data file is not updated anymore. This page and the linked data file will be removed in the future.</font></p><p>The following data file contains statistics about agreement or disagreement among the <a href="about.html#directory-authority">directory authorities</a>. Once per hour the directory authorities exchange votes with their view of the <a href="about.html#relay">relays</a> in the network including attributes like <a href="about.html#relay-flag">relay flags</a> or bandwidth measurements. This data file includes counts of relays by number of directory authorities assigning them a given attribute.</p>", "data_file": "stats/disagreement.csv", "data_column_spec": [ "<b>validafter:</b> UTC timestamp (YYYY-MM-DD HH:MM:SS) after which votes became valid, which may be used as the vote publication time.",