[tor-commits] [metrics-web/master] Periodically generate R objects with default parameters.

karsten at torproject.org karsten at torproject.org
Tue Mar 20 19:18:52 UTC 2012


commit 52c5c939bc8f04866fa9e21097072acc73c2ff06
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Tue Mar 20 15:11:15 2012 +0100

    Periodically generate R objects with default parameters.
    
    Fixes #3878, among other things.
---
 src/org/torproject/ernie/web/CsvServlet.java       |    2 +-
 src/org/torproject/ernie/web/GraphDataServlet.java |    2 +-
 .../torproject/ernie/web/GraphImageServlet.java    |    2 +-
 .../ernie/web/GraphsSubpagesServlet.java           |    2 +-
 src/org/torproject/ernie/web/RObjectGenerator.java |   60 ++++++++++++++-----
 .../ernie/web/TableParameterChecker.java           |    2 +-
 6 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/src/org/torproject/ernie/web/CsvServlet.java b/src/org/torproject/ernie/web/CsvServlet.java
index 1e9fbf8..3d0e06d 100644
--- a/src/org/torproject/ernie/web/CsvServlet.java
+++ b/src/org/torproject/ernie/web/CsvServlet.java
@@ -77,7 +77,7 @@ public class CsvServlet extends HttpServlet {
     /* Request CSV file from R object generator, which asks Rserve to
      * generate it. */
     String csvFileContent = this.rObjectGenerator.generateCsv(
-        requestedCsvFile);
+        requestedCsvFile, true);
 
     /* Make sure that we have a graph to return. */
     if (csvFileContent == null) {
diff --git a/src/org/torproject/ernie/web/GraphDataServlet.java b/src/org/torproject/ernie/web/GraphDataServlet.java
index 35df73b..b335994 100644
--- a/src/org/torproject/ernie/web/GraphDataServlet.java
+++ b/src/org/torproject/ernie/web/GraphDataServlet.java
@@ -112,7 +112,7 @@ public class GraphDataServlet extends HttpServlet {
     /* Request CSV file from R object generator, which may ask Rserve to
      * generate it. */
     String csvFileContent = this.rObjectGenerator.generateCsv(
-        requestedCsvFile);
+        requestedCsvFile, true);
 
     /* Make sure that we have a CSV to convert into JSON. */
     if (csvFileContent == null) {
diff --git a/src/org/torproject/ernie/web/GraphImageServlet.java b/src/org/torproject/ernie/web/GraphImageServlet.java
index 5d46cdd..20d3297 100644
--- a/src/org/torproject/ernie/web/GraphImageServlet.java
+++ b/src/org/torproject/ernie/web/GraphImageServlet.java
@@ -49,7 +49,7 @@ public class GraphImageServlet extends HttpServlet {
     /* Request graph from R object generator, which either returns it from
      * its cache or asks Rserve to generate it. */
     byte[] graphBytes = rObjectGenerator.generateGraph(requestedGraph,
-        request.getParameterMap());
+        request.getParameterMap(), true);
 
     /* Make sure that we have a graph to return. */
     if (graphBytes == null) {
diff --git a/src/org/torproject/ernie/web/GraphsSubpagesServlet.java b/src/org/torproject/ernie/web/GraphsSubpagesServlet.java
index 5c2743d..d557ce5 100644
--- a/src/org/torproject/ernie/web/GraphsSubpagesServlet.java
+++ b/src/org/torproject/ernie/web/GraphsSubpagesServlet.java
@@ -134,7 +134,7 @@ public class GraphsSubpagesServlet extends HttpServlet {
           this.availableGraphsSubpageTables.get(requestedPage)) {
         List<Map<String, String>> tableData = rObjectGenerator.
             generateTable(tableName, requestedTable,
-            request.getParameterMap());
+            request.getParameterMap(), true);
         request.setAttribute(tableName.replaceAll("-", "_")
               + "_tabledata", tableData);
       }
diff --git a/src/org/torproject/ernie/web/RObjectGenerator.java b/src/org/torproject/ernie/web/RObjectGenerator.java
index da79d43..011eccd 100644
--- a/src/org/torproject/ernie/web/RObjectGenerator.java
+++ b/src/org/torproject/ernie/web/RObjectGenerator.java
@@ -20,7 +20,6 @@ import java.util.TreeSet;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
-import javax.servlet.http.HttpServletResponse;
 
 import org.rosuda.REngine.Rserve.RConnection;
 import org.rosuda.REngine.Rserve.RserveException;
@@ -104,13 +103,40 @@ public class RObjectGenerator implements ServletContextListener {
 
     /* Register ourself, so that servlets can use us. */
     servletContext.setAttribute("RObjectGenerator", this);
+
+    /* Periodically generate R objects with default parameters. */
+    new Thread() {
+      public void run() {
+        long lastUpdated = 0L, sleep;
+        while (true) {
+          while ((sleep = maxCacheAge * 1000L / 2L + lastUpdated
+              - System.currentTimeMillis()) > 0L) {
+            try {
+              Thread.sleep(sleep);
+            } catch (InterruptedException e) {
+            }
+          }
+          for (String csvFile : availableCsvFiles) {
+            generateCsv(csvFile, false);
+          }
+          for (String tableName : availableTables.keySet()) {
+            generateTable(tableName, tableName, new HashMap(), false);
+          }
+          for (String graphName : availableGraphs.keySet()) {
+            generateGraph(graphName, new HashMap(), false);
+          }
+          lastUpdated = System.currentTimeMillis();
+        }
+      };
+    }.start();
   }
 
   public void contextDestroyed(ServletContextEvent event) {
     /* Nothing to do. */
   }
 
-  public byte[] generateGraph(String requestedGraph, Map parameterMap) {
+  public byte[] generateGraph(String requestedGraph, Map parameterMap,
+      boolean checkCache) {
     Map<String, String[]> checkedParameters = GraphParameterChecker.
         getInstance().checkParameters(requestedGraph, parameterMap);
     if (checkedParameters == null) {
@@ -144,19 +170,20 @@ public class RObjectGenerator implements ServletContextListener {
     String imageFilename = imageFilenameBuilder.toString();
     rQueryBuilder.append("path = '%s')");
     String rQuery = rQueryBuilder.toString();
-    return this.generateGraph(rQuery, imageFilename);
+    return this.generateGraph(rQuery, imageFilename, checkCache);
   }
 
   /* Generate a graph using the given R query that has a placeholder for
    * the absolute path to the image to be created. */
-  private byte[] generateGraph(String rQuery, String imageFilename) {
+  private byte[] generateGraph(String rQuery, String imageFilename,
+      boolean checkCache) {
 
     /* See if we need to generate this graph. */
     File imageFile = new File(this.cachedGraphsDirectory + "/"
         + imageFilename);
     long now = System.currentTimeMillis();
-    if (!imageFile.exists() || imageFile.lastModified() < now
-        - this.maxCacheAge * 1000L) {
+    if (!checkCache || !imageFile.exists() ||
+        imageFile.lastModified() < now - this.maxCacheAge * 1000L) {
 
       /* We do. Update the R query to contain the absolute path to the
        * file to be generated, create a connection to Rserve, run the R
@@ -202,24 +229,25 @@ public class RObjectGenerator implements ServletContextListener {
     return this.availableCsvFiles;
   }
 
-  public String generateCsv(String requestedCsvFile) {
+  public String generateCsv(String requestedCsvFile, boolean checkCache) {
     /* Prepare filename and R query string. */
     String rQuery = "export_" + requestedCsvFile.replaceAll("-", "_")
         + "(path = '%s')";
     String csvFilename = requestedCsvFile + ".csv";
-    return this.generateCsv(rQuery, csvFilename);
+    return this.generateCsv(rQuery, csvFilename, checkCache);
   }
 
   /* Generate a comma-separated value file using the given R query that
    * has a placeholder for the absolute path to the file to be created. */
-  private String generateCsv(String rQuery, String csvFilename) {
+  private String generateCsv(String rQuery, String csvFilename,
+      boolean checkCache) {
 
     /* See if we need to generate this .csv file. */
     File csvFile = new File(this.cachedGraphsDirectory + "/"
         + csvFilename);
     long now = System.currentTimeMillis();
-    if (!csvFile.exists() || csvFile.lastModified() < now
-        - this.maxCacheAge * 1000L) {
+    if (!checkCache || !csvFile.exists() ||
+        csvFile.lastModified() < now - this.maxCacheAge * 1000L) {
 
       /* We do. Update the R query to contain the absolute path to the
        * file to be generated, create a connection to Rserve, run the R
@@ -260,7 +288,7 @@ public class RObjectGenerator implements ServletContextListener {
   }
 
   public List<Map<String, String>> generateTable(String tableName,
-      String requestedTable, Map parameterMap) {
+      String requestedTable, Map parameterMap, boolean checkCache) {
 
     Map<String, String[]> checkedParameters = null;
     if (tableName.equals(requestedTable)) {
@@ -303,21 +331,21 @@ public class RObjectGenerator implements ServletContextListener {
     String tableFilename = tableFilenameBuilder.toString();
     rQueryBuilder.append("path = '%s')");
     String rQuery = rQueryBuilder.toString();
-    return this.generateTable(rQuery, tableFilename);
+    return this.generateTable(rQuery, tableFilename, checkCache);
   }
 
   /* Generate table data using the given R query and filename or read
    * previously generated table data from disk if it's not too old and
    * return table data. */
   private List<Map<String, String>> generateTable(String rQuery,
-      String tableFilename) {
+      String tableFilename, boolean checkCache) {
 
     /* See if we need to generate this table. */
     File tableFile = new File(this.cachedGraphsDirectory + "/"
         + tableFilename);
     long now = System.currentTimeMillis();
-    if (!tableFile.exists() || tableFile.lastModified() < now
-        - this.maxCacheAge * 1000L) {
+    if (!checkCache || !tableFile.exists() ||
+        tableFile.lastModified() < now - this.maxCacheAge * 1000L) {
 
       /* We do. Update the R query to contain the absolute path to the
        * file to be generated, create a connection to Rserve, run the R
diff --git a/src/org/torproject/ernie/web/TableParameterChecker.java b/src/org/torproject/ernie/web/TableParameterChecker.java
index 25bd8fa..e4b3e13 100644
--- a/src/org/torproject/ernie/web/TableParameterChecker.java
+++ b/src/org/torproject/ernie/web/TableParameterChecker.java
@@ -55,7 +55,7 @@ public class TableParameterChecker {
   public Map<String, String[]> checkParameters(String tableType,
       Map requestParameters) {
 
-    /* Check if the graph type exists. */
+    /* Check if the table type exists. */
     if (tableType == null ||
         !this.availableTables.containsKey(tableType)) {
       return null;





More information about the tor-commits mailing list