[tor-commits] [onionoo/master] Make WeightsStatus smarter about itself.

karsten at torproject.org karsten at torproject.org
Sun Aug 17 07:06:46 UTC 2014


commit a902feb6bac7b03cedfa3148671039cca00ea8ee
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Fri Aug 15 11:13:14 2014 +0200

    Make WeightsStatus smarter about itself.
    
    Removes another dependency on DateTimeHelper, which gets us closer to
    implementing #12866.
---
 .../org/torproject/onionoo/docs/WeightsStatus.java |   93 +++++++++++++++++
 .../onionoo/updater/WeightsStatusUpdater.java      |  106 ++------------------
 2 files changed, 104 insertions(+), 95 deletions(-)

diff --git a/src/main/java/org/torproject/onionoo/docs/WeightsStatus.java b/src/main/java/org/torproject/onionoo/docs/WeightsStatus.java
index 678789b..ccc818a 100644
--- a/src/main/java/org/torproject/onionoo/docs/WeightsStatus.java
+++ b/src/main/java/org/torproject/onionoo/docs/WeightsStatus.java
@@ -8,9 +8,18 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 
 import org.torproject.onionoo.util.DateTimeHelper;
+import org.torproject.onionoo.util.TimeFactory;
 
 public class WeightsStatus extends Document {
 
+  private transient boolean isDirty = false;
+  public boolean isDirty() {
+    return this.isDirty;
+  }
+  public void clearDirty() {
+    this.isDirty = false;
+  }
+
   private SortedMap<long[], double[]> history =
       new TreeMap<long[], double[]>(new Comparator<long[]>() {
     public int compare(long[] a, long[] b) {
@@ -77,6 +86,90 @@ public class WeightsStatus extends Document {
     s.close();
   }
 
+  public void addToHistory(long validAfterMillis, long freshUntilMillis,
+      double[] weights) {
+    long[] interval = new long[] { validAfterMillis, freshUntilMillis };
+    if ((this.history.headMap(interval).isEmpty() ||
+        this.history.headMap(interval).lastKey()[1] <=
+        validAfterMillis) &&
+        (this.history.tailMap(interval).isEmpty() ||
+        this.history.tailMap(interval).firstKey()[0] >=
+        freshUntilMillis)) {
+      this.history.put(interval, weights);
+      this.isDirty = true;
+    }
+  }
+
+  public void compressHistory() {
+    SortedMap<long[], double[]> uncompressedHistory =
+        new TreeMap<long[], double[]>(this.history);
+    history.clear();
+    long lastStartMillis = 0L, lastEndMillis = 0L;
+    double[] lastWeights = null;
+    String lastMonthString = "1970-01";
+    int lastMissingValues = -1;
+    long now = TimeFactory.getTime().currentTimeMillis();
+    for (Map.Entry<long[], double[]> e : uncompressedHistory.entrySet()) {
+      long startMillis = e.getKey()[0], endMillis = e.getKey()[1];
+      double[] weights = e.getValue();
+      long intervalLengthMillis;
+      if (now - endMillis <= DateTimeHelper.ONE_WEEK) {
+        intervalLengthMillis = DateTimeHelper.ONE_HOUR;
+      } else if (now - endMillis <=
+          DateTimeHelper.ROUGHLY_ONE_MONTH) {
+        intervalLengthMillis = DateTimeHelper.FOUR_HOURS;
+      } else if (now - endMillis <=
+          DateTimeHelper.ROUGHLY_THREE_MONTHS) {
+        intervalLengthMillis = DateTimeHelper.TWELVE_HOURS;
+      } else if (now - endMillis <=
+          DateTimeHelper.ROUGHLY_ONE_YEAR) {
+        intervalLengthMillis = DateTimeHelper.TWO_DAYS;
+      } else {
+        intervalLengthMillis = DateTimeHelper.TEN_DAYS;
+      }
+      String monthString = DateTimeHelper.format(startMillis,
+          DateTimeHelper.ISO_YEARMONTH_FORMAT);
+      int missingValues = 0;
+      for (int i = 0; i < weights.length; i++) {
+        if (weights[i] < -0.5) {
+          missingValues += 1 << i;
+        }
+      }
+      if (lastEndMillis == startMillis &&
+          ((lastEndMillis - 1L) / intervalLengthMillis) ==
+          ((endMillis - 1L) / intervalLengthMillis) &&
+          lastMonthString.equals(monthString) &&
+          lastMissingValues == missingValues) {
+        double lastIntervalInHours = (double) ((lastEndMillis
+            - lastStartMillis) / DateTimeHelper.ONE_HOUR);
+        double currentIntervalInHours = (double) ((endMillis
+            - startMillis) / DateTimeHelper.ONE_HOUR);
+        double newIntervalInHours = (double) ((endMillis
+            - lastStartMillis) / DateTimeHelper.ONE_HOUR);
+        for (int i = 0; i < lastWeights.length; i++) {
+          lastWeights[i] *= lastIntervalInHours;
+          lastWeights[i] += weights[i] * currentIntervalInHours;
+          lastWeights[i] /= newIntervalInHours;
+        }
+        lastEndMillis = endMillis;
+      } else {
+        if (lastStartMillis > 0L) {
+          this.history.put(new long[] { lastStartMillis, lastEndMillis },
+              lastWeights);
+        }
+        lastStartMillis = startMillis;
+        lastEndMillis = endMillis;
+        lastWeights = weights;
+      }
+      lastMonthString = monthString;
+      lastMissingValues = missingValues;
+    }
+    if (lastStartMillis > 0L) {
+      this.history.put(new long[] { lastStartMillis, lastEndMillis },
+          lastWeights);
+    }
+  }
+
   public String toDocumentString() {
     StringBuilder sb = new StringBuilder();
     for (Map.Entry<String, Integer> e :
diff --git a/src/main/java/org/torproject/onionoo/updater/WeightsStatusUpdater.java b/src/main/java/org/torproject/onionoo/updater/WeightsStatusUpdater.java
index f13ad14..2be213f 100644
--- a/src/main/java/org/torproject/onionoo/updater/WeightsStatusUpdater.java
+++ b/src/main/java/org/torproject/onionoo/updater/WeightsStatusUpdater.java
@@ -16,8 +16,6 @@ import org.torproject.descriptor.ServerDescriptor;
 import org.torproject.onionoo.docs.DocumentStore;
 import org.torproject.onionoo.docs.DocumentStoreFactory;
 import org.torproject.onionoo.docs.WeightsStatus;
-import org.torproject.onionoo.util.DateTimeHelper;
-import org.torproject.onionoo.util.TimeFactory;
 
 public class WeightsStatusUpdater implements DescriptorListener,
     StatusUpdater {
@@ -26,12 +24,9 @@ public class WeightsStatusUpdater implements DescriptorListener,
 
   private DocumentStore documentStore;
 
-  private long now;
-
   public WeightsStatusUpdater() {
     this.descriptorSource = DescriptorSourceFactory.getDescriptorSource();
     this.documentStore = DocumentStoreFactory.getDocumentStore();
-    this.now = TimeFactory.getTime().currentTimeMillis();
     this.registerDescriptorListeners();
   }
 
@@ -90,9 +85,19 @@ public class WeightsStatusUpdater implements DescriptorListener,
     for (Map.Entry<String, double[]> e
         : pathSelectionWeights.entrySet()) {
       String fingerprint = e.getKey();
+      WeightsStatus weightsStatus = this.documentStore.retrieve(
+          WeightsStatus.class, true, fingerprint);
+      if (weightsStatus == null) {
+        weightsStatus = new WeightsStatus();
+      }
       double[] weights = e.getValue();
-      this.addToHistory(fingerprint, validAfterMillis, freshUntilMillis,
+      weightsStatus.addToHistory(validAfterMillis, freshUntilMillis,
           weights);
+      if (weightsStatus.isDirty()) {
+        weightsStatus.compressHistory();
+        this.documentStore.store(weightsStatus, fingerprint);
+        weightsStatus.clearDirty();
+      }
     }
   }
 
@@ -228,95 +233,6 @@ public class WeightsStatusUpdater implements DescriptorListener,
     return pathSelectionProbabilities;
   }
 
-  private void addToHistory(String fingerprint, long validAfterMillis,
-      long freshUntilMillis, double[] weights) {
-    WeightsStatus weightsStatus = this.documentStore.retrieve(
-        WeightsStatus.class, true, fingerprint);
-    if (weightsStatus == null) {
-      weightsStatus = new WeightsStatus();
-    }
-    SortedMap<long[], double[]> history = weightsStatus.getHistory();
-    long[] interval = new long[] { validAfterMillis, freshUntilMillis };
-    if ((history.headMap(interval).isEmpty() ||
-        history.headMap(interval).lastKey()[1] <= validAfterMillis) &&
-        (history.tailMap(interval).isEmpty() ||
-        history.tailMap(interval).firstKey()[0] >= freshUntilMillis)) {
-      history.put(interval, weights);
-      this.compressHistory(weightsStatus);
-      this.documentStore.store(weightsStatus, fingerprint);
-    }
-  }
-
-  private void compressHistory(WeightsStatus weightsStatus) {
-    SortedMap<long[], double[]> history = weightsStatus.getHistory();
-    SortedMap<long[], double[]> compressedHistory =
-        new TreeMap<long[], double[]>(history.comparator());
-    long lastStartMillis = 0L, lastEndMillis = 0L;
-    double[] lastWeights = null;
-    String lastMonthString = "1970-01";
-    int lastMissingValues = -1;
-    for (Map.Entry<long[], double[]> e : history.entrySet()) {
-      long startMillis = e.getKey()[0], endMillis = e.getKey()[1];
-      double[] weights = e.getValue();
-      long intervalLengthMillis;
-      if (this.now - endMillis <= DateTimeHelper.ONE_WEEK) {
-        intervalLengthMillis = DateTimeHelper.ONE_HOUR;
-      } else if (this.now - endMillis <=
-          DateTimeHelper.ROUGHLY_ONE_MONTH) {
-        intervalLengthMillis = DateTimeHelper.FOUR_HOURS;
-      } else if (this.now - endMillis <=
-          DateTimeHelper.ROUGHLY_THREE_MONTHS) {
-        intervalLengthMillis = DateTimeHelper.TWELVE_HOURS;
-      } else if (this.now - endMillis <=
-          DateTimeHelper.ROUGHLY_ONE_YEAR) {
-        intervalLengthMillis = DateTimeHelper.TWO_DAYS;
-      } else {
-        intervalLengthMillis = DateTimeHelper.TEN_DAYS;
-      }
-      String monthString = DateTimeHelper.format(startMillis,
-          DateTimeHelper.ISO_YEARMONTH_FORMAT);
-      int missingValues = 0;
-      for (int i = 0; i < weights.length; i++) {
-        if (weights[i] < -0.5) {
-          missingValues += 1 << i;
-        }
-      }
-      if (lastEndMillis == startMillis &&
-          ((lastEndMillis - 1L) / intervalLengthMillis) ==
-          ((endMillis - 1L) / intervalLengthMillis) &&
-          lastMonthString.equals(monthString) &&
-          lastMissingValues == missingValues) {
-        double lastIntervalInHours = (double) ((lastEndMillis
-            - lastStartMillis) / DateTimeHelper.ONE_HOUR);
-        double currentIntervalInHours = (double) ((endMillis
-            - startMillis) / DateTimeHelper.ONE_HOUR);
-        double newIntervalInHours = (double) ((endMillis
-            - lastStartMillis) / DateTimeHelper.ONE_HOUR);
-        for (int i = 0; i < lastWeights.length; i++) {
-          lastWeights[i] *= lastIntervalInHours;
-          lastWeights[i] += weights[i] * currentIntervalInHours;
-          lastWeights[i] /= newIntervalInHours;
-        }
-        lastEndMillis = endMillis;
-      } else {
-        if (lastStartMillis > 0L) {
-          compressedHistory.put(new long[] { lastStartMillis,
-              lastEndMillis }, lastWeights);
-        }
-        lastStartMillis = startMillis;
-        lastEndMillis = endMillis;
-        lastWeights = weights;
-      }
-      lastMonthString = monthString;
-      lastMissingValues = missingValues;
-    }
-    if (lastStartMillis > 0L) {
-      compressedHistory.put(new long[] { lastStartMillis, lastEndMillis },
-          lastWeights);
-    }
-    weightsStatus.setHistory(compressedHistory);
-  }
-
   public String getStatsString() {
     /* TODO Add statistics string. */
     return null;





More information about the tor-commits mailing list