Move all disk i/o to a single thread to prevent very rare errors when running multiple tunnels

This commit is contained in:
zab2
2019-04-06 15:25:37 +00:00
parent 2c602fa46b
commit 8a001adf59

View File

@@ -6,6 +6,8 @@ import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.io.File;
import java.io.FileReader;
@@ -41,6 +43,12 @@ class AccessFilter implements StatefulConnectionFilter {
private static final long PURGE_INTERVAL = 1000;
private static final long SYNC_INTERVAL = 10 * 1000;
/**
* All disk i/o from all instances of this filter
* happen on this thread (apart from initial load)
*/
private static final ExecutorService DISK_WRITER = Executors.newSingleThreadExecutor();
private final FilterDefinition definition;
private final I2PAppContext context;
@@ -55,6 +63,8 @@ class AccessFilter implements StatefulConnectionFilter {
*/
private final Map<Hash, DestTracker> unknownDests = new HashMap<Hash, DestTracker>();
private volatile Syncer syncer;
/**
* @param context the context, used for scheduling and timer purposes
* @param definition definition of this filter
@@ -72,13 +82,14 @@ class AccessFilter implements StatefulConnectionFilter {
public void start() {
if (timersRunning.compareAndSet(false, true)) {
new Purger();
new Syncer();
syncer = new Syncer();
}
}
@Override
public void stop() {
timersRunning.set(false);
syncer = null;
}
@Override
@@ -200,14 +211,21 @@ class AccessFilter implements StatefulConnectionFilter {
public void timeReached() {
if (!timersRunning.get())
return;
try {
record();
reload();
schedule(SYNC_INTERVAL);
} catch (IOException bad) {
Log log = context.logManager().getLog(AccessFilter.class);
log.log(Log.CRIT, "syncing access list failed", bad);
}
}
DISK_WRITER.submit(new Runnable() {
@Override
public void run() {
try {
record();
reload();
Syncer syncer = AccessFilter.this.syncer;
if (syncer != null)
syncer.schedule(SYNC_INTERVAL);
} catch (IOException bad) {
Log log = context.logManager().getLog(AccessFilter.class);
log.log(Log.CRIT, "syncing access list failed", bad);
}
}
});
}
}
}