From 9a63be8f6943c46039444c25e2552796ee6e00af Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Sun, 9 Jan 2011 01:03:05 +0000
Subject: [PATCH]     * NetDB: Don't rescan netDb directory unless changed,    
          to reduce Hash cache thrash (backport from test4)

---
 .../KademliaNetworkDatabaseFacade.java        |  6 +-
 .../kademlia/PersistentDataStore.java         | 57 +++++++++++--------
 2 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
index 0ae7181044..e9e81b542f 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
@@ -247,7 +247,11 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
             _enforceNetId = DEFAULT_ENFORCE_NETID;
         
         _kb = new KBucketSet(_context, ri.getIdentity().getHash());
-        _ds = new PersistentDataStore(_context, dbDir, this);
+        try {
+            _ds = new PersistentDataStore(_context, dbDir, this);
+        } catch (IOException ioe) {
+            throw new RuntimeException("Unable to initialize netdb storage", ioe);
+        }
         //_ds = new TransientDataStore();
 //        _exploreKeys = new HashSet(64);
         _dbDir = dbDir;
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java
index 429489cf08..064aac5202 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java
@@ -39,19 +39,22 @@ import net.i2p.util.SecureFileOutputStream;
  *
  */
 class PersistentDataStore extends TransientDataStore {
-    private Log _log;
-    private String _dbDir;
-    private KademliaNetworkDatabaseFacade _facade;
-    private Writer _writer;
-    private ReadJob _readJob;
+    private final Log _log;
+    private final File _dbDir;
+    private final KademliaNetworkDatabaseFacade _facade;
+    private final Writer _writer;
+    private final ReadJob _readJob;
     private boolean _initialized;
     
     private final static int READ_DELAY = 60*1000;
     
-    public PersistentDataStore(RouterContext ctx, String dbDir, KademliaNetworkDatabaseFacade facade) {
+    /**
+     *  @param dbDir relative path
+     */
+    public PersistentDataStore(RouterContext ctx, String dbDir, KademliaNetworkDatabaseFacade facade) throws IOException {
         super(ctx);
         _log = ctx.logManager().getLog(PersistentDataStore.class);
-        _dbDir = dbDir;
+        _dbDir = getDbDir(dbDir);
         _facade = facade;
         _readJob = new ReadJob();
         _context.jobQueue().addJob(_readJob);
@@ -79,7 +82,6 @@ class PersistentDataStore extends TransientDataStore {
     @Override
     public void restart() {
         super.restart();
-        _dbDir = _facade.getDbDir();
     }
     
     @Override
@@ -160,8 +162,7 @@ class PersistentDataStore extends TransientDataStore {
             if (_log.shouldLog(Log.INFO))
                 _log.info("Removing key " + _key /* , getAddedBy() */);
             try {
-                File dbDir = getDbDir();
-                removeFile(_key, dbDir);
+                removeFile(_key, _dbDir);
             } catch (IOException ioe) {
                 _log.error("Error removing key " + _key, ioe);
             }
@@ -236,7 +237,10 @@ class PersistentDataStore extends TransientDataStore {
 
                 if (key != null) {
                     if (data != null) {
-                        write(key, data);
+                        // synch with the reader job
+                        synchronized (_dbDir) {
+                            write(key, data);
+                        }
                         data = null;
                     }
                     key = null;
@@ -278,7 +282,6 @@ class PersistentDataStore extends TransientDataStore {
         File dbFile = null;
         try {
             String filename = null;
-            File dbDir = getDbDir();
 
             if (data instanceof LeaseSet)
                 filename = getLeaseSetName(key);
@@ -287,7 +290,7 @@ class PersistentDataStore extends TransientDataStore {
             else
                 throw new IOException("We don't know how to write objects of type " + data.getClass().getName());
 
-            dbFile = new File(dbDir, filename);
+            dbFile = new File(_dbDir, filename);
             long dataPublishDate = getPublishDate(data);
             if (dbFile.lastModified() < dataPublishDate) {
                 // our filesystem is out of date, lets replace it
@@ -326,14 +329,26 @@ class PersistentDataStore extends TransientDataStore {
     /** This is only for manual reseeding? Why bother every 60 sec??? */
     private class ReadJob extends JobImpl {
         private boolean _alreadyWarned;
+        private long _lastModified;
+
         public ReadJob() {
             super(PersistentDataStore.this._context);
             _alreadyWarned = false;
         }
+
         public String getName() { return "DB Read Job"; }
+
         public void runJob() {
-            _log.info("Rereading new files");
-            readFiles();
+            // check directory mod time to save a lot of object churn in scanning all the file names
+            long lastMod = _dbDir.lastModified();
+            if (lastMod > _lastModified) {
+                _lastModified = lastMod;
+                _log.info("Rereading new files");
+                // synch with the writer job
+                synchronized (_dbDir) {
+                    readFiles();
+                }
+            }
             requeue(READ_DELAY);
         }
         
@@ -343,9 +358,8 @@ class PersistentDataStore extends TransientDataStore {
         
         private void readFiles() {
             int routerCount = 0;
-            try {
-                File dbDir = getDbDir();
-                File routerInfoFiles[] = dbDir.listFiles(RouterInfoFilter.getInstance());
+
+                File routerInfoFiles[] = _dbDir.listFiles(RouterInfoFilter.getInstance());
                 if (routerInfoFiles != null) {
                     routerCount += routerInfoFiles.length;
                     if (routerInfoFiles.length > 5)
@@ -360,9 +374,6 @@ class PersistentDataStore extends TransientDataStore {
                         }
                     }
                 }
-            } catch (IOException ioe) {
-                _log.error("Error reading files in the db dir", ioe);
-            }
             
             if (!_alreadyWarned) {
                 ReseedChecker.checkReseed(_context, routerCount);
@@ -442,8 +453,8 @@ class PersistentDataStore extends TransientDataStore {
     }
     
     
-    private File getDbDir() throws IOException {
-        File f = new SecureDirectory(_context.getRouterDir(), _dbDir);
+    private File getDbDir(String dbDir) throws IOException {
+        File f = new SecureDirectory(_context.getRouterDir(), dbDir);
         if (!f.exists()) {
             boolean created = f.mkdirs();
             if (!created)
-- 
GitLab