mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 03:39:05 +01:00
Wrapped the system clock in an interface so it can be replaced in tests.
This commit is contained in:
11
components/net/sf/briar/clock/ClockModule.java
Normal file
11
components/net/sf/briar/clock/ClockModule.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package net.sf.briar.clock;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
public class ClockModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(Clock.class).to(SystemClock.class);
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,7 @@ import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.api.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
import net.sf.briar.clock.Clock;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
@@ -103,6 +104,7 @@ DatabaseCleaner.Callback {
|
||||
private final DatabaseCleaner cleaner;
|
||||
private final ShutdownManager shutdown;
|
||||
private final PacketFactory packetFactory;
|
||||
private final Clock clock;
|
||||
|
||||
private final Collection<DatabaseListener> listeners =
|
||||
new CopyOnWriteArrayList<DatabaseListener>();
|
||||
@@ -117,11 +119,13 @@ DatabaseCleaner.Callback {
|
||||
|
||||
@Inject
|
||||
DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner,
|
||||
ShutdownManager shutdown, PacketFactory packetFactory) {
|
||||
ShutdownManager shutdown, PacketFactory packetFactory,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.cleaner = cleaner;
|
||||
this.shutdown = shutdown;
|
||||
this.packetFactory = packetFactory;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
public void open(boolean resume) throws DbException, IOException {
|
||||
@@ -632,7 +636,7 @@ DatabaseCleaner.Callback {
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
timestamp = System.currentTimeMillis() - 1;
|
||||
timestamp = clock.currentTimeMillis() - 1;
|
||||
holes = db.getVisibleHoles(txn, c, timestamp);
|
||||
subs = db.getVisibleSubscriptions(txn, c, timestamp);
|
||||
expiry = db.getExpiryTime(txn);
|
||||
@@ -652,7 +656,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
|
||||
private boolean updateIsDue(long sent) {
|
||||
long now = System.currentTimeMillis();
|
||||
long now = clock.currentTimeMillis();
|
||||
return now - sent >= DatabaseConstants.MAX_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
@@ -686,7 +690,7 @@ DatabaseCleaner.Callback {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
transports = db.getLocalTransports(txn);
|
||||
timestamp = System.currentTimeMillis();
|
||||
timestamp = clock.currentTimeMillis();
|
||||
db.setTransportsSent(txn, c, timestamp);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
@@ -1328,7 +1332,7 @@ DatabaseCleaner.Callback {
|
||||
try {
|
||||
if(!p.equals(db.getLocalProperties(txn, t))) {
|
||||
db.setLocalProperties(txn, t, p);
|
||||
db.setTransportsModified(txn, System.currentTimeMillis());
|
||||
db.setTransportsModified(txn, clock.currentTimeMillis());
|
||||
changed = true;
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
@@ -1606,7 +1610,7 @@ DatabaseCleaner.Callback {
|
||||
|
||||
public boolean shouldCheckFreeSpace() {
|
||||
synchronized(spaceLock) {
|
||||
long now = System.currentTimeMillis();
|
||||
long now = clock.currentTimeMillis();
|
||||
if(bytesStoredSinceLastCheck > MAX_BYTES_BETWEEN_SPACE_CHECKS
|
||||
|| now - timeOfLastCheck > MAX_MS_BETWEEN_SPACE_CHECKS) {
|
||||
bytesStoredSinceLastCheck = 0L;
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.sf.briar.api.protocol.GroupFactory;
|
||||
import net.sf.briar.api.protocol.PacketFactory;
|
||||
import net.sf.briar.api.transport.ConnectionContextFactory;
|
||||
import net.sf.briar.api.transport.ConnectionWindowFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
import net.sf.briar.util.BoundedExecutor;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
@@ -51,16 +52,16 @@ public class DatabaseModule extends AbstractModule {
|
||||
@DatabasePassword Password password, @DatabaseMaxSize long maxSize,
|
||||
ConnectionContextFactory connectionContextFactory,
|
||||
ConnectionWindowFactory connectionWindowFactory,
|
||||
GroupFactory groupFactory) {
|
||||
GroupFactory groupFactory, Clock clock) {
|
||||
return new H2Database(dir, password, maxSize, connectionContextFactory,
|
||||
connectionWindowFactory, groupFactory);
|
||||
connectionWindowFactory, groupFactory, clock);
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
DatabaseComponent getDatabaseComponent(Database<Connection> db,
|
||||
DatabaseCleaner cleaner, ShutdownManager shutdown,
|
||||
PacketFactory packetFactory) {
|
||||
PacketFactory packetFactory, Clock clock) {
|
||||
return new DatabaseComponentImpl<Connection>(db, cleaner, shutdown,
|
||||
packetFactory);
|
||||
packetFactory, clock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.protocol.GroupFactory;
|
||||
import net.sf.briar.api.transport.ConnectionContextFactory;
|
||||
import net.sf.briar.api.transport.ConnectionWindowFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
|
||||
import org.apache.commons.io.FileSystemUtils;
|
||||
|
||||
@@ -40,9 +41,9 @@ class H2Database extends JdbcDatabase {
|
||||
@DatabaseMaxSize long maxSize,
|
||||
ConnectionContextFactory connectionContextFactory,
|
||||
ConnectionWindowFactory connectionWindowFactory,
|
||||
GroupFactory groupFactory) {
|
||||
GroupFactory groupFactory, Clock clock) {
|
||||
super(connectionContextFactory, connectionWindowFactory, groupFactory,
|
||||
HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE);
|
||||
clock, HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE);
|
||||
home = new File(dir, "db");
|
||||
this.password = password;
|
||||
url = "jdbc:h2:split:" + home.getPath()
|
||||
|
||||
@@ -42,6 +42,7 @@ import net.sf.briar.api.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionContextFactory;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
import net.sf.briar.api.transport.ConnectionWindowFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
import net.sf.briar.util.FileUtils;
|
||||
|
||||
/**
|
||||
@@ -275,6 +276,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private final ConnectionContextFactory connectionContextFactory;
|
||||
private final ConnectionWindowFactory connectionWindowFactory;
|
||||
private final GroupFactory groupFactory;
|
||||
private final Clock clock;
|
||||
// Different database libraries use different names for certain types
|
||||
private final String hashType, binaryType, counterType, secretType;
|
||||
|
||||
@@ -288,11 +290,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
JdbcDatabase(ConnectionContextFactory connectionContextFactory,
|
||||
ConnectionWindowFactory connectionWindowFactory,
|
||||
GroupFactory groupFactory, String hashType, String binaryType,
|
||||
String counterType, String secretType) {
|
||||
GroupFactory groupFactory, Clock clock, String hashType,
|
||||
String binaryType, String counterType, String secretType) {
|
||||
this.connectionContextFactory = connectionContextFactory;
|
||||
this.connectionWindowFactory = connectionWindowFactory;
|
||||
this.groupFactory = groupFactory;
|
||||
this.clock = clock;
|
||||
this.hashType = hashType;
|
||||
this.binaryType = binaryType;
|
||||
this.counterType = counterType;
|
||||
@@ -654,7 +657,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, b.getBytes());
|
||||
ps.setInt(2, c.getInt());
|
||||
ps.setLong(3, System.currentTimeMillis());
|
||||
ps.setLong(3, clock.currentTimeMillis());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
@@ -741,7 +744,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.setBytes(1, g.getId().getBytes());
|
||||
ps.setString(2, g.getName());
|
||||
ps.setBytes(3, g.getPublicKey());
|
||||
long now = System.currentTimeMillis();
|
||||
long now = clock.currentTimeMillis();
|
||||
ps.setLong(4, now);
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
@@ -2230,7 +2233,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// Remove the group ID from the visibility lists
|
||||
long now = System.currentTimeMillis();
|
||||
long now = clock.currentTimeMillis();
|
||||
String sql = "SELECT contactId, nextId FROM visibilities"
|
||||
+ " WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -2342,7 +2345,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps = txn.prepareStatement(sql);
|
||||
if(nextId == null) ps.setNull(1, Types.BINARY); // At the tail
|
||||
else ps.setBytes(1, nextId); // At the head or in the middle
|
||||
ps.setLong(2, System.currentTimeMillis());
|
||||
ps.setLong(2, clock.currentTimeMillis());
|
||||
ps.setInt(3, c.getInt());
|
||||
ps.setBytes(4, g.getBytes());
|
||||
affected = ps.executeUpdate();
|
||||
|
||||
@@ -12,8 +12,6 @@ import java.security.KeyPair;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.crypto.PseudoRandom;
|
||||
@@ -32,6 +30,8 @@ import net.sf.briar.api.serial.Writer;
|
||||
import net.sf.briar.api.serial.WriterFactory;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
class InvitationStarterImpl implements InvitationStarter {
|
||||
|
||||
private static final String TIMED_OUT = "INVITATION_TIMED_OUT";
|
||||
|
||||
@@ -35,6 +35,7 @@ import net.sf.briar.api.protocol.TransportId;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.transport.ConnectionDispatcher;
|
||||
import net.sf.briar.api.ui.UiCallback;
|
||||
import net.sf.briar.clock.Clock;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
@@ -54,6 +55,7 @@ class PluginManagerImpl implements PluginManager {
|
||||
};
|
||||
|
||||
private final ExecutorService pluginExecutor;
|
||||
private final Clock clock;
|
||||
private final DatabaseComponent db;
|
||||
private final Poller poller;
|
||||
private final ConnectionDispatcher dispatcher;
|
||||
@@ -63,9 +65,10 @@ class PluginManagerImpl implements PluginManager {
|
||||
|
||||
@Inject
|
||||
PluginManagerImpl(@PluginExecutor ExecutorService pluginExecutor,
|
||||
DatabaseComponent db, Poller poller,
|
||||
Clock clock, DatabaseComponent db, Poller poller,
|
||||
ConnectionDispatcher dispatcher, UiCallback uiCallback) {
|
||||
this.pluginExecutor = pluginExecutor;
|
||||
this.clock = clock;
|
||||
this.db = db;
|
||||
this.poller = poller;
|
||||
this.dispatcher = dispatcher;
|
||||
@@ -88,7 +91,7 @@ class PluginManagerImpl implements PluginManager {
|
||||
(SimplexPluginFactory) c.newInstance();
|
||||
SimplexCallback callback = new SimplexCallback();
|
||||
SimplexPlugin plugin = factory.createPlugin(pluginExecutor,
|
||||
callback);
|
||||
clock, callback);
|
||||
if(plugin == null) {
|
||||
if(LOG.isLoggable(Level.INFO)) {
|
||||
LOG.info(factory.getClass().getSimpleName()
|
||||
@@ -128,7 +131,7 @@ class PluginManagerImpl implements PluginManager {
|
||||
(DuplexPluginFactory) c.newInstance();
|
||||
DuplexCallback callback = new DuplexCallback();
|
||||
DuplexPlugin plugin = factory.createPlugin(pluginExecutor,
|
||||
callback);
|
||||
clock, callback);
|
||||
if(plugin == null) {
|
||||
if(LOG.isLoggable(Level.INFO)) {
|
||||
LOG.info(factory.getClass().getSimpleName()
|
||||
|
||||
@@ -32,6 +32,7 @@ import net.sf.briar.api.plugins.duplex.DuplexPlugin;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
|
||||
import net.sf.briar.api.protocol.TransportId;
|
||||
import net.sf.briar.clock.Clock;
|
||||
import net.sf.briar.util.OsUtils;
|
||||
import net.sf.briar.util.StringUtils;
|
||||
|
||||
@@ -47,6 +48,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
Logger.getLogger(BluetoothPlugin.class.getName());
|
||||
|
||||
private final Executor pluginExecutor;
|
||||
private final Clock clock;
|
||||
private final DuplexPluginCallback callback;
|
||||
private final long pollingInterval;
|
||||
private final Object discoveryLock = new Object();
|
||||
@@ -58,9 +60,10 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
private LocalDevice localDevice = null; // Locking: this
|
||||
private StreamConnectionNotifier socket = null; // Locking: this
|
||||
|
||||
BluetoothPlugin(@PluginExecutor Executor pluginExecutor,
|
||||
BluetoothPlugin(@PluginExecutor Executor pluginExecutor, Clock clock,
|
||||
DuplexPluginCallback callback, long pollingInterval) {
|
||||
this.pluginExecutor = pluginExecutor;
|
||||
this.clock = clock;
|
||||
this.callback = callback;
|
||||
this.pollingInterval = pollingInterval;
|
||||
scheduler = Executors.newScheduledThreadPool(0);
|
||||
@@ -360,9 +363,9 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
|
||||
// Try to discover the other party until the invitation times out
|
||||
long end = System.currentTimeMillis() + c.getTimeout();
|
||||
long end = clock.currentTimeMillis() + c.getTimeout();
|
||||
String url = null;
|
||||
while(url == null && System.currentTimeMillis() < end) {
|
||||
while(url == null && clock.currentTimeMillis() < end) {
|
||||
InvitationListener listener = new InvitationListener(discoveryAgent,
|
||||
c.getUuid());
|
||||
// FIXME: Avoid making alien calls with a lock held
|
||||
|
||||
@@ -6,13 +6,15 @@ import net.sf.briar.api.plugins.PluginExecutor;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
|
||||
public class BluetoothPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final long POLLING_INTERVAL = 3L * 60L * 1000L; // 3 mins
|
||||
|
||||
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
|
||||
DuplexPluginCallback callback) {
|
||||
return new BluetoothPlugin(pluginExecutor, callback, POLLING_INTERVAL);
|
||||
Clock clock, DuplexPluginCallback callback) {
|
||||
return new BluetoothPlugin(pluginExecutor, clock, callback,
|
||||
POLLING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@ import java.util.concurrent.Executor;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexPlugin;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
|
||||
public class GmailPluginFactory implements SimplexPluginFactory {
|
||||
|
||||
public SimplexPlugin createPlugin(Executor pluginExecutor,
|
||||
public SimplexPlugin createPlugin(Executor pluginExecutor, Clock clock,
|
||||
SimplexPluginCallback callback) {
|
||||
|
||||
return new GmailPlugin(pluginExecutor, callback);
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.sf.briar.api.plugins.PluginExecutor;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexPlugin;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
import net.sf.briar.util.OsUtils;
|
||||
|
||||
public class RemovableDrivePluginFactory implements SimplexPluginFactory {
|
||||
@@ -13,7 +14,7 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
|
||||
private static final long POLLING_INTERVAL = 10L * 1000L; // 10 seconds
|
||||
|
||||
public SimplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
|
||||
SimplexPluginCallback callback) {
|
||||
Clock clock, SimplexPluginCallback callback) {
|
||||
RemovableDriveFinder finder;
|
||||
RemovableDriveMonitor monitor;
|
||||
if(OsUtils.isLinux()) {
|
||||
|
||||
@@ -6,13 +6,14 @@ import net.sf.briar.api.plugins.PluginExecutor;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
|
||||
public class SimpleSocketPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final long POLLING_INTERVAL = 5L * 60L * 1000L; // 5 mins
|
||||
|
||||
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
|
||||
DuplexPluginCallback callback) {
|
||||
Clock clock, DuplexPluginCallback callback) {
|
||||
return new SimpleSocketPlugin(pluginExecutor, callback,
|
||||
POLLING_INTERVAL);
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@ import net.sf.briar.api.plugins.PluginExecutor;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
|
||||
import net.sf.briar.clock.Clock;
|
||||
|
||||
public class TorPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final long POLLING_INTERVAL = 15L * 60L * 1000L; // 15 mins
|
||||
|
||||
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
|
||||
DuplexPluginCallback callback) {
|
||||
Clock clock, DuplexPluginCallback callback) {
|
||||
return new TorPlugin(pluginExecutor, callback, POLLING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user