[or-cvs] [metrics-db/master] Finally get rid of DirreqStatsFileHandler.

karsten at torproject.org karsten at torproject.org
Thu Jan 13 15:33:42 UTC 2011


commit ebe99772243af9d6794d7a09a6da2c3a43e5b925
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Thu Jan 13 16:05:45 2011 +0100

    Finally get rid of DirreqStatsFileHandler.
    
    There's no need to maintain a local file with dirreq stats only to import
    the same data to the database shortly after.  We now import to the
    database directly in RelayDescriptorDatabaseImporter.
---
 config.template                                    |    3 -
 src/org/torproject/ernie/db/Configuration.java     |   15 +-
 .../ernie/db/DirreqStatsFileHandler.java           |  351 --------------------
 src/org/torproject/ernie/db/Main.java              |   17 +-
 .../ernie/db/RelayDescriptorDatabaseImporter.java  |   87 +++++
 .../torproject/ernie/db/RelayDescriptorParser.java |   16 +-
 6 files changed, 98 insertions(+), 391 deletions(-)

diff --git a/config.template b/config.template
index 5ba3b74..aff609c 100644
--- a/config.template
+++ b/config.template
@@ -99,9 +99,6 @@
 ## Write consensus stats to disk
 #WriteConsensusStats 0
 #
-## Write dirreq stats to disk
-#WriteDirreqStats 0
-#
 ## Write bridge stats to disk
 #WriteBridgeStats 0
 
diff --git a/src/org/torproject/ernie/db/Configuration.java b/src/org/torproject/ernie/db/Configuration.java
index 79658ae..413e03b 100644
--- a/src/org/torproject/ernie/db/Configuration.java
+++ b/src/org/torproject/ernie/db/Configuration.java
@@ -14,7 +14,6 @@ import java.util.logging.*;
  */
 public class Configuration {
   private boolean writeConsensusStats = false;
-  private boolean writeDirreqStats = false;
   private boolean writeBridgeStats = false;
   private boolean writeDirectoryArchives = false;
   private String directoryArchivesOutputDirectory = "directory-archive/";
@@ -73,9 +72,6 @@ public class Configuration {
         } else if (line.startsWith("WriteConsensusStats")) {
           this.writeConsensusStats = Integer.parseInt(
               line.split(" ")[1]) != 0;
-        } else if (line.startsWith("WriteDirreqStats")) {
-          this.writeDirreqStats = Integer.parseInt(
-              line.split(" ")[1]) != 0;
         } else if (line.startsWith("WriteBridgeStats")) {
           this.writeBridgeStats = Integer.parseInt(
               line.split(" ")[1]) != 0;
@@ -202,8 +198,7 @@ public class Configuration {
         !this.writeRelayDescriptorDatabase &&
         !this.writeAggregateStatsDatabase &&
         !this.writeSanitizedBridges && !this.writeConsensusStats &&
-        !this.writeDirreqStats && !this.writeBridgeStats &&
-        !this.writeConsensusHealth) {
+        !this.writeBridgeStats && !this.writeConsensusHealth) {
       logger.warning("We have not been configured to read data from any "
           + "data source or write data to any data sink. You need to "
           + "edit your config file (" + configFile.getAbsolutePath()
@@ -215,8 +210,7 @@ public class Configuration {
         !(this.writeDirectoryArchives ||
         this.writeRelayDescriptorDatabase ||
         this.writeRelayDescriptorsRawFiles || this.writeConsensusStats ||
-        this.writeDirreqStats || this.writeBridgeStats ||
-        this.writeConsensusHealth)) {
+        this.writeBridgeStats || this.writeConsensusHealth)) {
       logger.warning("We are configured to import/download relay "
           + "descriptors, but we don't have a single data sink to write "
           + "relay descriptors to.");
@@ -224,7 +218,7 @@ public class Configuration {
     if (!(this.importCachedRelayDescriptors ||
         this.importDirectoryArchives || this.downloadRelayDescriptors) &&
         (this.writeDirectoryArchives ||
-        this.writeRelayDescriptorDatabase || this.writeDirreqStats)) {
+        this.writeRelayDescriptorDatabase)) {
       logger.warning("We are configured to write relay descriptor to at "
           + "least one data sink, but we don't have a single data source "
           + "containing relay descriptors.");
@@ -254,9 +248,6 @@ public class Configuration {
   public boolean getWriteConsensusStats() {
     return this.writeConsensusStats;
   }
-  public boolean getWriteDirreqStats() {
-    return this.writeDirreqStats;
-  }
   public boolean getWriteBridgeStats() {
     return this.writeBridgeStats;
   }
diff --git a/src/org/torproject/ernie/db/DirreqStatsFileHandler.java b/src/org/torproject/ernie/db/DirreqStatsFileHandler.java
deleted file mode 100644
index 1cbbad5..0000000
--- a/src/org/torproject/ernie/db/DirreqStatsFileHandler.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/* Copyright 2010 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.ernie.db;
-
-import java.io.*;
-import java.sql.*;
-import java.text.*;
-import java.util.*;
-import java.util.logging.*;
-
-/**
- * Extracts statistics on v3 directory requests by country from extra-info
- * descriptors and writes them to a CSV file that is easily parsable by R.
- * Parse results come from <code>RelayDescriptorParser</code> and are
- * written to <code>stats/dirreq-stats</code>.
- */
-public class DirreqStatsFileHandler {
-
-  /**
-   * Two-letter country codes of known countries.
-   */
-  private SortedSet<String> countries;
-
-  /**
-   * Results file containing v3 directory requests by country.
-   */
-  private File dirreqStatsFile;
-
-  /**
-   * Directory requests by directory and date. Map keys are directory and
-   * date written as "directory,statsend,seconds", map values are
-   * country-user maps.
-   */
-  private SortedMap<String, Map<String, String>> dirreqs;
-
-  /**
-   * Modification flag for directory requests stored in memory. This flag
-   * is used to decide whether the contents of <code>dirreqs</code> need
-   * to be written to disk during <code>writeFile</code>.
-   */
-  private boolean dirreqsModified;
-
-  /**
-   * Logger for this class.
-   */
-  private Logger logger;
-
-  private int addedResults = 0;
-
-  /* Database connection string. */
-  private String connectionURL = null;
-
-  /* Format for parsing dirreq-stats-end timestamps. */
-  private SimpleDateFormat dateTimeFormat = null;
-
-  /**
-   * Initializes this class, including reading in previous results from
-   * <code>stats/dirreq-stats</code>.
-   */
-  public DirreqStatsFileHandler(String connectionURL) {
-
-    /* Initialize set of known countries. */
-    this.countries = new TreeSet<String>();
-    this.countries.add("zy");
-
-    /* Initialize local data structure to hold observations received from
-     * RelayDescriptorParser. */
-    this.dirreqs = new TreeMap<String, Map<String, String>>();
-
-    /* Initialize file name for observations file. */
-    this.dirreqStatsFile = new File("stats/dirreq-stats");
-
-    /* Initialize database connection string. */
-    this.connectionURL = connectionURL;
-
-    /* Initialize format to parse dirreq-stats-end lines. */
-    this.dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-    this.dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-
-    /* Initialize logger. */
-    this.logger = Logger.getLogger(
-        DirreqStatsFileHandler.class.getName());
-
-    /* Read in previously stored results. */
-    if (this.dirreqStatsFile.exists()) {
-      try {
-        this.logger.fine("Reading file "
-            + this.dirreqStatsFile.getAbsolutePath() + "...");
-        BufferedReader br = new BufferedReader(new FileReader(
-            this.dirreqStatsFile));
-        String line = br.readLine();
-        if (line != null) {
-          /* The first line should contain headers that we need to parse
-           * in order to learn what countries we were interested in when
-           * writing this file. */
-          if (!line.startsWith("directory,statsend,seconds,")) {
-            this.logger.warning("Incorrect first line '" + line + "' in "
-                + this.dirreqStatsFile.getAbsolutePath() + "! This line "
-                + "should contain headers! Aborting to read in this "
-                + "file!");
-          } else {
-            String[] headers = line.split(",");
-            for (int i = 3; i < headers.length; i++) {
-              if (!headers[i].equals("all")) {
-                this.countries.add(headers[i]);
-              }
-            }
-            /* Read in the rest of the file. */
-            while ((line = br.readLine()) != null) {
-              String[] parts = line.split(",");
-              if (parts.length != headers.length) {
-                this.logger.warning("Corrupt line '" + line + "' in file "
-                    + this.dirreqStatsFile.getAbsolutePath() + "! This "
-                    + "line has either fewer or more columns than the "
-                    + "file has column headers! Aborting to read this "
-                    + "file!");
-                break;
-              }
-              String directory = parts[0];
-              String statsEnd = parts[1];
-              long seconds = Long.parseLong(parts[2]);
-              Map<String, String> obs = new HashMap<String, String>();
-              for (int i = 3; i < parts.length; i++) {
-                if (parts[i].equals("NA")) {
-                  continue;
-                }
-                if (headers[i].equals("all")) {
-                  obs.put("zy", parts[i]);
-                } else {
-                  obs.put(headers[i], parts[i]);
-                }
-              }
-              this.addObs(directory, statsEnd, seconds, obs);
-            }
-          }
-        }
-        br.close();
-        this.logger.fine("Finished reading file "
-            + this.dirreqStatsFile.getAbsolutePath() + ".");
-      } catch (IOException e) {
-        this.logger.log(Level.WARNING, "Failed to read file "
-            + this.dirreqStatsFile.getAbsolutePath() + "!", e);
-      }
-    }
-
-    /* Set modification flag to false and counter for stats to zero. */
-    this.dirreqsModified = false;
-    this.addedResults = 0;
-  }
-
-  /**
-   * Adds observations on the number of directory requests by country as
-   * seen on a directory at a given date.
-   */
-  public void addObs(String directory, String statsEnd, long seconds,
-      Map<String, String> obs) {
-    for (String country : obs.keySet()) {
-      this.countries.add(country);
-    }
-    String key = directory + "," + statsEnd + "," + seconds;
-    if (!this.dirreqs.containsKey(key)) {
-      this.logger.finer("Adding new directory request numbers: " + key);
-      this.dirreqs.put(key, obs);
-      this.dirreqsModified = true;
-      this.addedResults++;
-    } else {
-      this.logger.fine("The directory request numbers we were just "
-          + "given for " + key + " may be different from what we learned "
-          + "before. Overwriting!");
-      this.dirreqs.put(key, obs);
-      this.dirreqsModified = true;
-    }
-  }
-
-  /**
-   * Writes the v3 directory request numbers from memory to
-   * <code>stats/dirreq-stats</code> if they have changed.
-   */
-  public void writeFile() {
-
-    /* Only write file if we learned something new. */
-    if (this.dirreqsModified) {
-      try {
-        this.logger.fine("Writing file "
-            + this.dirreqStatsFile.getAbsolutePath() + "...");
-        this.dirreqStatsFile.getParentFile().mkdirs();
-        BufferedWriter bw = new BufferedWriter(new FileWriter(
-            this.dirreqStatsFile));
-        /* Write header. */
-        bw.append("directory,statsend,seconds");
-        for (String country : this.countries) {
-          if (country.equals("zy")) {
-            bw.append(",all");
-          } else {
-            bw.append("," + country);
-          }
-        }
-        bw.append("\n");
-        /* Write observations. */
-        for (Map.Entry<String, Map<String, String>> e :
-            this.dirreqs.entrySet()) {
-          String key = e.getKey();
-          Map<String, String> obs = e.getValue();
-          StringBuilder sb = new StringBuilder(key);
-          for (String c : this.countries) {
-            sb.append("," + (obs.containsKey(c) ? obs.get(c) : "NA"));
-          }
-          String line = sb.toString();
-          bw.append(line + "\n");
-        }
-        bw.close();
-        this.logger.fine("Finished writing file "
-            + this.dirreqStatsFile.getAbsolutePath() + ".");
-      } catch (IOException e) {
-        this.logger.log(Level.WARNING, "Failed to write file "
-            + this.dirreqStatsFile.getAbsolutePath() + "!", e);
-      }
-    } else {
-      this.logger.fine("Not writing file "
-          + this.dirreqStatsFile.getAbsolutePath() + ", because "
-          + "nothing has changed.");
-    }
-
-    /* Add directory requests by country to database. */
-    if (connectionURL != null) {
-      try {
-        List<String> countryList = new ArrayList<String>();
-        for (String c : this.countries) {
-          countryList.add(c);
-        }
-        Map<String, String> insertRows = new HashMap<String, String>(),
-            updateRows = new HashMap<String, String>();
-        for (Map.Entry<String, Map<String, String>> e :
-            this.dirreqs.entrySet()) {
-          String[] parts = e.getKey().split(",");
-          String source = parts[0];
-          String statsEnd = parts[1];
-          String seconds = parts[2];
-          Map<String, String> obs = e.getValue();
-          int i = 0;
-          for (String country : this.countries) {
-            if (obs.containsKey(country)) {
-              String key = source + "," + statsEnd + "," + seconds + ","
-                  + country;
-              String requests = "" + obs.get(country);
-              insertRows.put(key, requests);
-            }
-          }
-        }
-        Connection conn = DriverManager.getConnection(connectionURL);
-        conn.setAutoCommit(false);
-        Statement statement = conn.createStatement();
-        ResultSet rs = statement.executeQuery(
-            "SELECT source, statsend, seconds, country, requests "
-            + "FROM dirreq_stats");
-        while (rs.next()) {
-          String source = rs.getString(1);
-          String statsEnd = this.dateTimeFormat.format(
-              rs.getTimestamp(2).getTime());
-          long seconds = rs.getLong(3);
-          String country = rs.getString(4);
-          String key = source + "," + statsEnd + "," + seconds + ","
-              + country;
-          if (insertRows.containsKey(key)) {
-            String insertRow = insertRows.remove(key);
-            long oldUsers = rs.getLong(5);
-            long newUsers = Long.parseLong(insertRow.split(",")[0]);
-            if (oldUsers != newUsers) {
-              updateRows.put(key, insertRow);
-            }
-          }
-        }
-        rs.close();
-        PreparedStatement psU = conn.prepareStatement(
-            "UPDATE dirreq_stats SET requests = ? "
-            + "WHERE source = ? AND statsend = ? AND seconds = ? "
-            + "AND country = ?");
-        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
-        for (Map.Entry<String, String> e : updateRows.entrySet()) {
-          String[] keyParts = e.getKey().split(",");
-          String source = keyParts[0];
-          Timestamp statsEnd = new Timestamp(this.dateTimeFormat.parse(
-              keyParts[1]).getTime());
-          long seconds = Long.parseLong(keyParts[2]);
-          String country = keyParts[3];
-          long requests = Long.parseLong(e.getValue());
-          psU.clearParameters();
-          psU.setLong(1, requests);
-          psU.setString(2, source);
-          psU.setTimestamp(3, statsEnd, cal);
-          psU.setLong(4, seconds);
-          psU.setString(5, country);
-          psU.executeUpdate();
-        }
-        PreparedStatement psI = conn.prepareStatement(
-            "INSERT INTO dirreq_stats (requests, source, statsend, "
-            + "seconds, country) VALUES (?, ?, ?, ?, ?)");
-        for (Map.Entry<String, String> e : insertRows.entrySet()) {
-          String[] keyParts = e.getKey().split(",");
-          String source = keyParts[0];
-          Timestamp statsEnd = new Timestamp(this.dateTimeFormat.parse(
-              keyParts[1]).getTime());
-          long seconds = Long.parseLong(keyParts[2]);
-          String country = keyParts[3];
-          long requests = Long.parseLong(e.getValue());
-          psI.clearParameters();
-          psI.setLong(1, requests);
-          psI.setString(2, source);
-          psI.setTimestamp(3, statsEnd, cal);
-          psI.setLong(4, seconds);
-          psI.setString(5, country);
-          psI.executeUpdate();
-        }
-        conn.commit();
-        conn.close();
-      } catch (SQLException e) {
-        logger.log(Level.WARNING, "Failed to add directory requests by "
-            + "country to database.", e);
-      } catch (ParseException e) {
-        logger.log(Level.WARNING, "Failed to add directory requests by "
-            + "country to database.", e);
-      }
-    }
-
-    /* Set modification flag to false again. */
-    this.dirreqsModified = false;
-
-    /* Write stats. */
-    StringBuilder dumpStats = new StringBuilder("Finished writing "
-        + "statistics on directory requests by country.\nAdded "
-        + this.addedResults + " new observations in this execution.\n"
-        + "Last known observations by directory are:");
-    String lastDir = null;
-    String lastDate = null;
-    for (String line : this.dirreqs.keySet()) {
-      String[] parts = line.split(",");
-      if (lastDir == null) {
-        lastDir = parts[0];
-      } else if (!parts[0].equals(lastDir)) {
-        dumpStats.append("\n" + lastDir.substring(0, 8) + " " + lastDate);
-        lastDir = parts[0];
-      }
-      lastDate = parts[1];
-    }
-    if (lastDir != null) {
-      dumpStats.append("\n" + lastDir.substring(0, 8) + " " + lastDate);
-    }
-    logger.info(dumpStats.toString());
-  }
-}
-
diff --git a/src/org/torproject/ernie/db/Main.java b/src/org/torproject/ernie/db/Main.java
index 64dcc55..6110ec0 100644
--- a/src/org/torproject/ernie/db/Main.java
+++ b/src/org/torproject/ernie/db/Main.java
@@ -38,10 +38,6 @@ public class Main {
         new BridgeStatsFileHandler(
         config.getWriteAggregateStatsDatabase() ?
         config.getRelayDescriptorDatabaseJDBC() : null) : null;
-    DirreqStatsFileHandler dsfh = config.getWriteDirreqStats() ?
-        new DirreqStatsFileHandler(
-        config.getWriteAggregateStatsDatabase() ?
-        config.getRelayDescriptorDatabaseJDBC() : null) : null;
 
     // Prepare consensus health checker
     ConsensusHealthChecker chc = config.getWriteConsensusHealth() ?
@@ -65,13 +61,12 @@ public class Main {
     // Prepare relay descriptor parser (only if we are writing stats or
     // directory archives to disk)
     RelayDescriptorParser rdp = config.getWriteConsensusStats() ||
-        config.getWriteBridgeStats() || config.getWriteDirreqStats() ||
+        config.getWriteBridgeStats() ||
         config.getWriteDirectoryArchives() ||
         config.getWriteRelayDescriptorDatabase() ||
         config.getWriteRelayDescriptorsRawFiles() ||
         config.getWriteConsensusHealth() ?
-        new RelayDescriptorParser(csfh, bsfh, dsfh, aw, rddi, chc)
-            : null;
+        new RelayDescriptorParser(csfh, bsfh, aw, rddi, chc) : null;
 
     // Import/download relay descriptors from the various sources
     if (rdp != null) {
@@ -83,8 +78,8 @@ public class Main {
             bsfh != null || rddi != null || chc != null;
         boolean downloadCurrentVotes = aw != null || chc != null;
         boolean downloadAllServerDescriptors = aw != null ||
-            dsfh != null || rddi != null;
-        boolean downloadAllExtraInfos = aw != null || dsfh != null;
+            rddi != null;
+        boolean downloadAllExtraInfos = aw != null || rddi != null;
         rdd = new RelayDescriptorDownloader(rdp, dirSources,
             downloadCurrentConsensus, downloadCurrentVotes,
             downloadAllServerDescriptors, downloadAllExtraInfos);
@@ -131,10 +126,6 @@ public class Main {
       aw.dumpStats();
       aw = null;
     }
-    if (dsfh != null) {
-      dsfh.writeFile();
-      dsfh = null;
-    }
 
     // Prepare sanitized bridge descriptor writer
     SanitizedBridgesWriter sbw = config.getWriteSanitizedBridges() ?
diff --git a/src/org/torproject/ernie/db/RelayDescriptorDatabaseImporter.java b/src/org/torproject/ernie/db/RelayDescriptorDatabaseImporter.java
index 2d25ca1..be30ea2 100644
--- a/src/org/torproject/ernie/db/RelayDescriptorDatabaseImporter.java
+++ b/src/org/torproject/ernie/db/RelayDescriptorDatabaseImporter.java
@@ -30,6 +30,7 @@ public final class RelayDescriptorDatabaseImporter {
   private int rcsCount = 0;
   private int rvsCount = 0;
   private int rbsCount = 0;
+  private int rqsCount = 0;
 
   /**
    * Relay descriptor database connection.
@@ -86,6 +87,12 @@ public final class RelayDescriptorDatabaseImporter {
   private PreparedStatement psBs;
 
   /**
+   * Prepared statement to check whether a given dirreq stats string has
+   * been imported into the database before.
+   */
+  private PreparedStatement psQs;
+
+  /**
    * Prepared statement to insert a network status consensus entry into
    * the database.
    */
@@ -127,6 +134,12 @@ public final class RelayDescriptorDatabaseImporter {
   private PreparedStatement psB;
 
   /**
+   * Prepared statement to insert a given dirreq stats string into the
+   * database.
+   */
+  private PreparedStatement psQ;
+
+  /**
    * Logger for this class.
    */
   private Logger logger;
@@ -172,6 +185,11 @@ public final class RelayDescriptorDatabaseImporter {
   private BufferedWriter connBiDirectOut;
 
   /**
+   * Raw import file containing dirreq stats.
+   */
+  private BufferedWriter dirReqOut;
+
+  /**
    * Date format to parse timestamps.
    */
   private SimpleDateFormat dateTimeFormat;
@@ -230,6 +248,8 @@ public final class RelayDescriptorDatabaseImporter {
             + "FROM vote WHERE validafter = ? AND dirsource = ?");
         this.psBs = conn.prepareStatement("SELECT COUNT(*) "
             + "FROM connbidirect WHERE source = ? AND statsend = ?");
+        this.psQs = conn.prepareStatement("SELECT COUNT(*) "
+            + "FROM dirreq_stats WHERE source = ? AND statsend = ?");
         this.psR = conn.prepareStatement("INSERT INTO statusentry "
             + "(validafter, nickname, fingerprint, descriptor, "
             + "published, address, orport, dirport, isauthority, "
@@ -257,6 +277,9 @@ public final class RelayDescriptorDatabaseImporter {
         this.psB = conn.prepareStatement("INSERT INTO connbidirect "
             + "(source, statsend, seconds, belownum, readnum, writenum, "
             + "bothnum) VALUES (?, ?, ?, ?, ?, ?, ?)");
+        this.psQ = conn.prepareStatement("INSERT INTO dirreq_stats "
+            + "(source, statsend, seconds, country, requests) VALUES "
+            + "(?, ?, ?, ?, ?)");
       } catch (SQLException e) {
         this.logger.log(Level.WARNING, "Could not connect to database or "
             + "prepare statements.", e);
@@ -783,6 +806,70 @@ public final class RelayDescriptorDatabaseImporter {
   }
 
   /**
+   * Adds observations on the number of directory requests by country as
+   * seen on a directory at a given date to the database.
+   */
+  public void addDirReqStats(String source, String statsEnd, long seconds,
+      Map<String, String> dirReqsPerCountry) {
+    long statsEndTime = 0L;
+    try {
+      statsEndTime = this.dateTimeFormat.parse(statsEnd).getTime();
+    } catch (ParseException e) {
+      this.logger.log(Level.WARNING, "Could not add dirreq stats with "
+          + "interval ending '" + statsEnd + "'.", e);
+      return;
+    }
+    if (this.psQs != null && this.psQ != null) {
+      try {
+        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+        Timestamp statsEndTimestamp = new Timestamp(statsEndTime);
+        this.psQs.setString(1, source);
+        this.psQs.setTimestamp(2, statsEndTimestamp, cal);
+        ResultSet rs = psQs.executeQuery();
+        rs.next();
+        if (rs.getInt(1) == 0) {
+          for (Map.Entry<String, String> e :
+              dirReqsPerCountry.entrySet()) {
+            this.psQ.clearParameters();
+            this.psQ.setString(1, source);
+            this.psQ.setTimestamp(2, statsEndTimestamp, cal);
+            this.psQ.setLong(3, seconds);
+            this.psQ.setString(4, e.getKey());
+            this.psQ.setLong(5, Long.parseLong(e.getValue()));
+            this.psQ.executeUpdate();
+            rqsCount++;
+            if (rqsCount % autoCommitCount == 0)  {
+              this.conn.commit();
+              rqsCount = 0;
+            }
+          }
+        }
+      } catch (SQLException e) {
+        this.logger.log(Level.WARNING, "Could not add dirreq stats.", e);
+      }
+    }
+    if (this.rawFilesDirectory != null) {
+      try {
+        if (this.dirReqOut == null) {
+          new File(rawFilesDirectory).mkdirs();
+          this.dirReqOut = new BufferedWriter(new FileWriter(
+              rawFilesDirectory + "/dirreq_stats.sql"));
+          this.dirReqOut.write(" COPY dirreq_stats (source, statsend, "
+              + "seconds, country, requests) FROM stdin;\n");
+        }
+        for (Map.Entry<String, String> e :
+            dirReqsPerCountry.entrySet()) {
+          this.dirReqOut.write(source + "\t" + statsEnd + "\t" + seconds
+              + "\t" + e.getKey() + "\t" + e.getValue() + "\n");
+        }
+      } catch (IOException e) {
+        this.logger.log(Level.WARNING, "Could not write dirreq stats to "
+            + "raw database import file.", e);
+      }
+    }
+  }
+
+  /**
    * Close the relay descriptor database connection.
    */
   public void closeConnection() {
diff --git a/src/org/torproject/ernie/db/RelayDescriptorParser.java b/src/org/torproject/ernie/db/RelayDescriptorParser.java
index 187bddb..f2cdfed 100644
--- a/src/org/torproject/ernie/db/RelayDescriptorParser.java
+++ b/src/org/torproject/ernie/db/RelayDescriptorParser.java
@@ -18,12 +18,6 @@ import org.apache.commons.codec.binary.*;
 public class RelayDescriptorParser {
 
   /**
-   * Stats file handler that accepts parse results for directory request
-   * statistics.
-   */
-  private DirreqStatsFileHandler dsfh;
-
-  /**
    * Stats file handler that accepts parse results for consensus
    * statistics.
    */
@@ -65,12 +59,10 @@ public class RelayDescriptorParser {
    * Initializes this class.
    */
   public RelayDescriptorParser(ConsensusStatsFileHandler csfh,
-      BridgeStatsFileHandler bsfh, DirreqStatsFileHandler dsfh,
-      ArchiveWriter aw, RelayDescriptorDatabaseImporter rddi,
-      ConsensusHealthChecker chc) {
+      BridgeStatsFileHandler bsfh, ArchiveWriter aw,
+      RelayDescriptorDatabaseImporter rddi, ConsensusHealthChecker chc) {
     this.csfh = csfh;
     this.bsfh = bsfh;
-    this.dsfh = dsfh;
     this.aw = aw;
     this.rddi = rddi;
     this.chc = chc;
@@ -376,7 +368,7 @@ public class RelayDescriptorParser {
             seconds = Long.parseLong(parts[3].substring(1));
           } else if (line.startsWith("dirreq-v3-reqs ")
               && line.length() > "dirreq-v3-reqs ".length()) {
-            if (this.dsfh != null) {
+            if (this.rddi != null) {
               try {
                 int allUsers = 0;
                 Map<String, String> obs = new HashMap<String, String>();
@@ -389,7 +381,7 @@ public class RelayDescriptorParser {
                   obs.put(country, "" + users);
                 }
                 obs.put("zy", "" + allUsers);
-                this.dsfh.addObs(dir, statsEnd, seconds, obs);
+                this.rddi.addDirReqStats(dir, statsEnd, seconds, obs);
               } catch (NumberFormatException e) {
                 this.logger.log(Level.WARNING, "Could not parse "
                     + "dirreq-v3-reqs line '" + line + "' in descriptor. "



More information about the tor-commits mailing list