Dedicated executors for plugins and the connection recogniser.

This commit is contained in:
akwizgran
2011-12-08 16:11:24 +00:00
parent caf5f34828
commit 6e080bb35d
26 changed files with 223 additions and 176 deletions

View File

@@ -4,5 +4,5 @@ import java.util.concurrent.Executor;
public interface BatchPluginFactory { public interface BatchPluginFactory {
BatchPlugin createPlugin(Executor executor, BatchPluginCallback callback); BatchPlugin createPlugin(Executor e, BatchPluginCallback callback);
} }

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.plugins;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/** Annotation for injecting the executor used by transport plugins. */
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface PluginExecutor {}

View File

@@ -4,5 +4,5 @@ import java.util.concurrent.Executor;
public interface StreamPluginFactory { public interface StreamPluginFactory {
StreamPlugin createPlugin(Executor executor, StreamPluginCallback callback); StreamPlugin createPlugin(Executor e, StreamPluginCallback callback);
} }

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api.transport;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/**
* Annotation for injecting the executor for recognising incoming connections.
*/
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface ConnectionRecogniserExecutor {}

View File

@@ -4,15 +4,16 @@ import java.io.IOException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import net.sf.briar.api.plugins.Plugin; import net.sf.briar.api.plugins.Plugin;
import net.sf.briar.api.plugins.PluginExecutor;
public abstract class AbstractPlugin implements Plugin { public abstract class AbstractPlugin implements Plugin {
protected final Executor executor; protected final Executor pluginExecutor;
protected boolean started = false; // Locking: this protected boolean started = false; // Locking: this
protected AbstractPlugin(Executor executor) { protected AbstractPlugin(@PluginExecutor Executor pluginExecutor) {
this.executor = executor; this.pluginExecutor = pluginExecutor;
} }
public synchronized void start() throws IOException { public synchronized void start() throws IOException {

View File

@@ -21,6 +21,7 @@ import net.sf.briar.api.plugins.BatchPluginCallback;
import net.sf.briar.api.plugins.BatchPluginFactory; import net.sf.briar.api.plugins.BatchPluginFactory;
import net.sf.briar.api.plugins.Plugin; import net.sf.briar.api.plugins.Plugin;
import net.sf.briar.api.plugins.PluginCallback; import net.sf.briar.api.plugins.PluginCallback;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.PluginManager; import net.sf.briar.api.plugins.PluginManager;
import net.sf.briar.api.plugins.StreamPlugin; import net.sf.briar.api.plugins.StreamPlugin;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.StreamPluginCallback;
@@ -51,7 +52,7 @@ class PluginManagerImpl implements PluginManager {
}; };
private final DatabaseComponent db; private final DatabaseComponent db;
private final Executor executor; private final Executor pluginExecutor;
private final Poller poller; private final Poller poller;
private final ConnectionDispatcher dispatcher; private final ConnectionDispatcher dispatcher;
private final UiCallback uiCallback; private final UiCallback uiCallback;
@@ -59,10 +60,11 @@ class PluginManagerImpl implements PluginManager {
private final List<StreamPlugin> streamPlugins; // Locking: this private final List<StreamPlugin> streamPlugins; // Locking: this
@Inject @Inject
PluginManagerImpl(DatabaseComponent db, Executor executor, Poller poller, PluginManagerImpl(DatabaseComponent db,
@PluginExecutor Executor pluginExecutor, Poller poller,
ConnectionDispatcher dispatcher, UiCallback uiCallback) { ConnectionDispatcher dispatcher, UiCallback uiCallback) {
this.db = db; this.db = db;
this.executor = executor; this.pluginExecutor = pluginExecutor;
this.poller = poller; this.poller = poller;
this.dispatcher = dispatcher; this.dispatcher = dispatcher;
this.uiCallback = uiCallback; this.uiCallback = uiCallback;
@@ -83,11 +85,13 @@ class PluginManagerImpl implements PluginManager {
BatchPluginFactory factory = BatchPluginFactory factory =
(BatchPluginFactory) c.newInstance(); (BatchPluginFactory) c.newInstance();
BatchCallback callback = new BatchCallback(); BatchCallback callback = new BatchCallback();
BatchPlugin plugin = factory.createPlugin(executor, callback); BatchPlugin plugin = factory.createPlugin(pluginExecutor,
callback);
if(plugin == null) { if(plugin == null) {
if(LOG.isLoggable(Level.INFO)) if(LOG.isLoggable(Level.INFO)) {
LOG.info(factory.getClass().getSimpleName() LOG.info(factory.getClass().getSimpleName()
+ " did not create a plugin"); + " did not create a plugin");
}
continue; continue;
} }
TransportId id = plugin.getId(); TransportId id = plugin.getId();
@@ -121,11 +125,13 @@ class PluginManagerImpl implements PluginManager {
StreamPluginFactory factory = StreamPluginFactory factory =
(StreamPluginFactory) c.newInstance(); (StreamPluginFactory) c.newInstance();
StreamCallback callback = new StreamCallback(); StreamCallback callback = new StreamCallback();
StreamPlugin plugin = factory.createPlugin(executor, callback); StreamPlugin plugin = factory.createPlugin(pluginExecutor,
callback);
if(plugin == null) { if(plugin == null) {
if(LOG.isLoggable(Level.INFO)) if(LOG.isLoggable(Level.INFO)) {
LOG.info(factory.getClass().getSimpleName() LOG.info(factory.getClass().getSimpleName()
+ " did not create a plugin"); + " did not create a plugin");
}
continue; continue;
} }
TransportId id = plugin.getId(); TransportId id = plugin.getId();

View File

@@ -1,5 +1,9 @@
package net.sf.briar.plugins; package net.sf.briar.plugins;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.PluginManager; import net.sf.briar.api.plugins.PluginManager;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
@@ -9,6 +13,8 @@ public class PluginsModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(Executor.class).annotatedWith(PluginExecutor.class).toInstance(
Executors.newCachedThreadPool());
bind(PluginManager.class).to( bind(PluginManager.class).to(
PluginManagerImpl.class).in(Singleton.class); PluginManagerImpl.class).in(Singleton.class);
bind(Poller.class).to(PollerImpl.class); bind(Poller.class).to(PollerImpl.class);

View File

@@ -19,6 +19,7 @@ import javax.microedition.io.StreamConnectionNotifier;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportProperties; import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.StreamPlugin; import net.sf.briar.api.plugins.StreamPlugin;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.StreamPluginCallback;
import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportId;
@@ -44,9 +45,9 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
private LocalDevice localDevice = null; // Locking: this private LocalDevice localDevice = null; // Locking: this
private StreamConnectionNotifier socket = null; // Locking: this private StreamConnectionNotifier socket = null; // Locking: this
BluetoothPlugin(Executor executor, StreamPluginCallback callback, BluetoothPlugin(@PluginExecutor Executor pluginExecutor,
long pollingInterval) { StreamPluginCallback callback, long pollingInterval) {
super(executor); super(pluginExecutor);
this.callback = callback; this.callback = callback;
this.pollingInterval = pollingInterval; this.pollingInterval = pollingInterval;
} }
@@ -69,7 +70,7 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
} catch(UnsatisfiedLinkError e) { } catch(UnsatisfiedLinkError e) {
// On Linux the user may need to install libbluetooth-dev // On Linux the user may need to install libbluetooth-dev
if(OsUtils.isLinux()) { if(OsUtils.isLinux()) {
executor.execute(new Runnable() { pluginExecutor.execute(new Runnable() {
public void run() { public void run() {
callback.showMessage("BLUETOOTH_INSTALL_LIBS"); callback.showMessage("BLUETOOTH_INSTALL_LIBS");
} }
@@ -77,7 +78,7 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
} }
throw new IOException(e.getMessage()); throw new IOException(e.getMessage());
} }
executor.execute(createContactSocketBinder()); pluginExecutor.execute(createContactSocketBinder());
} }
@Override @Override
@@ -199,7 +200,7 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
public synchronized void poll() { public synchronized void poll() {
if(!started) return; if(!started) return;
executor.execute(createConnectors()); pluginExecutor.execute(createConnectors());
} }
private Runnable createConnectors() { private Runnable createConnectors() {

View File

@@ -2,16 +2,17 @@ package net.sf.briar.plugins.bluetooth;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.StreamPlugin; import net.sf.briar.api.plugins.StreamPlugin;
import net.sf.briar.api.plugins.StreamPluginCallback;
import net.sf.briar.api.plugins.StreamPluginFactory; import net.sf.briar.api.plugins.StreamPluginFactory;
public class BluetoothPluginFactory implements StreamPluginFactory { public class BluetoothPluginFactory implements StreamPluginFactory {
private static final long POLLING_INTERVAL = 3L * 60L * 1000L; // 3 mins private static final long POLLING_INTERVAL = 3L * 60L * 1000L; // 3 mins
public StreamPlugin createPlugin(Executor executor, public StreamPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
StreamPluginCallback callback) { StreamPluginCallback callback) {
return new BluetoothPlugin(executor, callback, POLLING_INTERVAL); return new BluetoothPlugin(pluginExecutor, callback, POLLING_INTERVAL);
} }
} }

View File

@@ -13,6 +13,7 @@ import java.util.logging.Logger;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.BatchPlugin; import net.sf.briar.api.plugins.BatchPlugin;
import net.sf.briar.api.plugins.BatchPluginCallback; import net.sf.briar.api.plugins.BatchPluginCallback;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.transport.BatchTransportReader; import net.sf.briar.api.transport.BatchTransportReader;
import net.sf.briar.api.transport.BatchTransportWriter; import net.sf.briar.api.transport.BatchTransportWriter;
import net.sf.briar.api.transport.TransportConstants; import net.sf.briar.api.transport.TransportConstants;
@@ -35,8 +36,9 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
protected abstract void writerFinished(File f); protected abstract void writerFinished(File f);
protected abstract void readerFinished(File f); protected abstract void readerFinished(File f);
protected FilePlugin(Executor executor, BatchPluginCallback callback) { protected FilePlugin(@PluginExecutor Executor pluginExecutor,
super(executor); BatchPluginCallback callback) {
super(pluginExecutor);
this.callback = callback; this.callback = callback;
} }
@@ -85,7 +87,7 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
protected synchronized void createReaderFromFile(final File f) { protected synchronized void createReaderFromFile(final File f) {
if(!started) return; if(!started) return;
executor.execute(new ReaderCreator(f)); pluginExecutor.execute(new ReaderCreator(f));
} }
public BatchTransportWriter sendInvitation(int code, long timeout) { public BatchTransportWriter sendInvitation(int code, long timeout) {

View File

@@ -11,6 +11,7 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import net.sf.briar.api.plugins.BatchPluginCallback; import net.sf.briar.api.plugins.BatchPluginCallback;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.util.StringUtils; import net.sf.briar.util.StringUtils;
@@ -28,9 +29,10 @@ implements RemovableDriveMonitor.Callback {
private final RemovableDriveFinder finder; private final RemovableDriveFinder finder;
private final RemovableDriveMonitor monitor; private final RemovableDriveMonitor monitor;
RemovableDrivePlugin(Executor executor, BatchPluginCallback callback, RemovableDrivePlugin(@PluginExecutor Executor pluginExecutor,
RemovableDriveFinder finder, RemovableDriveMonitor monitor) { BatchPluginCallback callback, RemovableDriveFinder finder,
super(executor, callback); RemovableDriveMonitor monitor) {
super(pluginExecutor, callback);
this.finder = finder; this.finder = finder;
this.monitor = monitor; this.monitor = monitor;
} }

View File

@@ -2,16 +2,17 @@ package net.sf.briar.plugins.file;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import net.sf.briar.api.plugins.BatchPluginCallback;
import net.sf.briar.api.plugins.BatchPlugin; import net.sf.briar.api.plugins.BatchPlugin;
import net.sf.briar.api.plugins.BatchPluginCallback;
import net.sf.briar.api.plugins.BatchPluginFactory; import net.sf.briar.api.plugins.BatchPluginFactory;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.util.OsUtils; import net.sf.briar.util.OsUtils;
public class RemovableDrivePluginFactory implements BatchPluginFactory { public class RemovableDrivePluginFactory implements BatchPluginFactory {
private static final long POLLING_INTERVAL = 10L * 1000L; // 10 seconds private static final long POLLING_INTERVAL = 10L * 1000L; // 10 seconds
public BatchPlugin createPlugin(Executor executor, public BatchPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
BatchPluginCallback callback) { BatchPluginCallback callback) {
RemovableDriveFinder finder; RemovableDriveFinder finder;
RemovableDriveMonitor monitor; RemovableDriveMonitor monitor;
@@ -33,6 +34,7 @@ public class RemovableDrivePluginFactory implements BatchPluginFactory {
} else { } else {
return null; return null;
} }
return new RemovableDrivePlugin(executor, callback, finder, monitor); return new RemovableDrivePlugin(pluginExecutor, callback, finder,
monitor);
} }
} }

View File

@@ -14,6 +14,7 @@ import java.util.concurrent.Executor;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.StreamPluginCallback;
import net.sf.briar.api.transport.StreamTransportConnection; import net.sf.briar.api.transport.StreamTransportConnection;
import net.sf.briar.util.ByteUtils; import net.sf.briar.util.ByteUtils;
@@ -24,9 +25,9 @@ class LanSocketPlugin extends SimpleSocketPlugin {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(LanSocketPlugin.class.getName()); Logger.getLogger(LanSocketPlugin.class.getName());
LanSocketPlugin(Executor executor, StreamPluginCallback callback, LanSocketPlugin(@PluginExecutor Executor pluginExecutor,
long pollingInterval) { StreamPluginCallback callback, long pollingInterval) {
super(executor, callback, pollingInterval); super(pluginExecutor, callback, pollingInterval);
} }
@Override @Override

View File

@@ -15,6 +15,7 @@ import java.util.logging.Logger;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportProperties; import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.StreamPluginCallback;
import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.transport.StreamTransportConnection; import net.sf.briar.api.transport.StreamTransportConnection;
@@ -32,9 +33,9 @@ class SimpleSocketPlugin extends SocketPlugin {
private final long pollingInterval; private final long pollingInterval;
SimpleSocketPlugin(Executor executor, StreamPluginCallback callback, SimpleSocketPlugin(@PluginExecutor Executor pluginExecutor,
long pollingInterval) { StreamPluginCallback callback, long pollingInterval) {
super(executor, callback); super(pluginExecutor, callback);
this.pollingInterval = pollingInterval; this.pollingInterval = pollingInterval;
} }

View File

@@ -2,16 +2,18 @@ package net.sf.briar.plugins.socket;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.StreamPlugin; import net.sf.briar.api.plugins.StreamPlugin;
import net.sf.briar.api.plugins.StreamPluginCallback;
import net.sf.briar.api.plugins.StreamPluginFactory; import net.sf.briar.api.plugins.StreamPluginFactory;
public class SimpleSocketPluginFactory implements StreamPluginFactory { public class SimpleSocketPluginFactory implements StreamPluginFactory {
private static final long POLLING_INTERVAL = 5L * 60L * 1000L; // 5 mins private static final long POLLING_INTERVAL = 5L * 60L * 1000L; // 5 mins
public StreamPlugin createPlugin(Executor executor, public StreamPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
StreamPluginCallback callback) { StreamPluginCallback callback) {
return new SimpleSocketPlugin(executor, callback, POLLING_INTERVAL); return new SimpleSocketPlugin(pluginExecutor, callback,
POLLING_INTERVAL);
} }
} }

View File

@@ -9,8 +9,9 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.StreamPluginCallback; import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.StreamPlugin; import net.sf.briar.api.plugins.StreamPlugin;
import net.sf.briar.api.plugins.StreamPluginCallback;
import net.sf.briar.api.transport.StreamTransportConnection; import net.sf.briar.api.transport.StreamTransportConnection;
import net.sf.briar.plugins.AbstractPlugin; import net.sf.briar.plugins.AbstractPlugin;
@@ -32,15 +33,16 @@ abstract class SocketPlugin extends AbstractPlugin implements StreamPlugin {
protected abstract SocketAddress getLocalSocketAddress(); protected abstract SocketAddress getLocalSocketAddress();
protected abstract SocketAddress getRemoteSocketAddress(ContactId c); protected abstract SocketAddress getRemoteSocketAddress(ContactId c);
protected SocketPlugin(Executor executor, StreamPluginCallback callback) { protected SocketPlugin(@PluginExecutor Executor pluginExecutor,
super(executor); StreamPluginCallback callback) {
super(pluginExecutor);
this.callback = callback; this.callback = callback;
} }
@Override @Override
public synchronized void start() throws IOException { public synchronized void start() throws IOException {
super.start(); super.start();
executor.execute(createBinder()); pluginExecutor.execute(createBinder());
} }
private Runnable createBinder() { private Runnable createBinder() {
@@ -140,7 +142,7 @@ abstract class SocketPlugin extends AbstractPlugin implements StreamPlugin {
if(!shouldPoll()) throw new UnsupportedOperationException(); if(!shouldPoll()) throw new UnsupportedOperationException();
if(!started) return; if(!started) return;
for(ContactId c : callback.getRemoteProperties().keySet()) { for(ContactId c : callback.getRemoteProperties().keySet()) {
executor.execute(createConnector(c)); pluginExecutor.execute(createConnector(c));
} }
} }

View File

@@ -2,6 +2,7 @@ package net.sf.briar.protocol.batch;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH; import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.logging.Level; import java.util.logging.Level;
@@ -57,7 +58,7 @@ class OutgoingBatchConnection {
ProtocolWriter writer = protoFactory.createProtocolWriter(out); ProtocolWriter writer = protoFactory.createProtocolWriter(out);
// There should be enough space for a packet // There should be enough space for a packet
long capacity = conn.getRemainingCapacity(); long capacity = conn.getRemainingCapacity();
if(capacity < MAX_PACKET_LENGTH) throw new IOException(); if(capacity < MAX_PACKET_LENGTH) throw new EOFException();
// Write a transport update // Write a transport update
TransportUpdate t = db.generateTransportUpdate(contactId); TransportUpdate t = db.generateTransportUpdate(contactId);
if(t != null) writer.writeTransportUpdate(t); if(t != null) writer.writeTransportUpdate(t);

View File

@@ -33,6 +33,7 @@ import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportIndex; import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionRecogniser; import net.sf.briar.api.transport.ConnectionRecogniser;
import net.sf.briar.api.transport.ConnectionRecogniserExecutor;
import net.sf.briar.api.transport.ConnectionWindow; import net.sf.briar.api.transport.ConnectionWindow;
import net.sf.briar.util.ByteUtils; import net.sf.briar.util.ByteUtils;
@@ -44,9 +45,9 @@ DatabaseListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(ConnectionRecogniserImpl.class.getName()); Logger.getLogger(ConnectionRecogniserImpl.class.getName());
private final CryptoComponent crypto;
private final DatabaseComponent db;
private final Executor executor; private final Executor executor;
private final DatabaseComponent db;
private final CryptoComponent crypto;
private final Cipher tagCipher; // Locking: this private final Cipher tagCipher; // Locking: this
private final Set<TransportId> localTransportIds; // Locking: this private final Set<TransportId> localTransportIds; // Locking: this
private final Map<Bytes, Context> expected; // Locking: this private final Map<Bytes, Context> expected; // Locking: this
@@ -54,11 +55,11 @@ DatabaseListener {
private boolean initialised = false; // Locking: this private boolean initialised = false; // Locking: this
@Inject @Inject
ConnectionRecogniserImpl(CryptoComponent crypto, DatabaseComponent db, ConnectionRecogniserImpl(@ConnectionRecogniserExecutor Executor executor,
Executor executor) { DatabaseComponent db, CryptoComponent crypto) {
this.crypto = crypto;
this.db = db;
this.executor = executor; this.executor = executor;
this.db = db;
this.crypto = crypto;
tagCipher = crypto.getTagCipher(); tagCipher = crypto.getTagCipher();
localTransportIds = new HashSet<TransportId>(); localTransportIds = new HashSet<TransportId>();
expected = new HashMap<Bytes, Context>(); expected = new HashMap<Bytes, Context>();

View File

@@ -1,13 +1,18 @@
package net.sf.briar.transport; package net.sf.briar.transport;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import net.sf.briar.api.transport.ConnectionContextFactory; import net.sf.briar.api.transport.ConnectionContextFactory;
import net.sf.briar.api.transport.ConnectionDispatcher; import net.sf.briar.api.transport.ConnectionDispatcher;
import net.sf.briar.api.transport.ConnectionReaderFactory; import net.sf.briar.api.transport.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionRecogniser; import net.sf.briar.api.transport.ConnectionRecogniser;
import net.sf.briar.api.transport.ConnectionRecogniserExecutor;
import net.sf.briar.api.transport.ConnectionWindowFactory; import net.sf.briar.api.transport.ConnectionWindowFactory;
import net.sf.briar.api.transport.ConnectionWriterFactory; import net.sf.briar.api.transport.ConnectionWriterFactory;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
public class TransportModule extends AbstractModule { public class TransportModule extends AbstractModule {
@@ -18,10 +23,14 @@ public class TransportModule extends AbstractModule {
bind(ConnectionDispatcher.class).to(ConnectionDispatcherImpl.class); bind(ConnectionDispatcher.class).to(ConnectionDispatcherImpl.class);
bind(ConnectionReaderFactory.class).to( bind(ConnectionReaderFactory.class).to(
ConnectionReaderFactoryImpl.class); ConnectionReaderFactoryImpl.class);
bind(ConnectionRecogniser.class).to(ConnectionRecogniserImpl.class); bind(ConnectionRecogniser.class).to(ConnectionRecogniserImpl.class).in(
Singleton.class);
bind(ConnectionWindowFactory.class).to( bind(ConnectionWindowFactory.class).to(
ConnectionWindowFactoryImpl.class); ConnectionWindowFactoryImpl.class);
bind(ConnectionWriterFactory.class).to( bind(ConnectionWriterFactory.class).to(
ConnectionWriterFactoryImpl.class); ConnectionWriterFactoryImpl.class);
bind(Executor.class).annotatedWith(
ConnectionRecogniserExecutor.class).toInstance(
Executors.newCachedThreadPool());
} }
} }

View File

@@ -16,8 +16,6 @@ import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.CryptoComponent;
@@ -59,10 +57,8 @@ import net.sf.briar.transport.TransportModule;
import org.junit.Test; import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module;
public class ProtocolIntegrationTest extends TestCase { public class ProtocolIntegrationTest extends TestCase {
@@ -87,14 +83,7 @@ public class ProtocolIntegrationTest extends TestCase {
public ProtocolIntegrationTest() throws Exception { public ProtocolIntegrationTest() throws Exception {
super(); super();
Module testModule = new AbstractModule() { Injector i = Guice.createInjector(new CryptoModule(),
@Override
public void configure() {
bind(Executor.class).toInstance(
Executors.newCachedThreadPool());
}
};
Injector i = Guice.createInjector(testModule, new CryptoModule(),
new DatabaseModule(), new LifecycleModule(), new DatabaseModule(), new LifecycleModule(),
new ProtocolModule(), new SerialModule(), new ProtocolModule(), new SerialModule(),
new TestDatabaseModule(), new ProtocolBatchModule(), new TestDatabaseModule(), new ProtocolBatchModule(),

View File

@@ -13,8 +13,6 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -56,10 +54,8 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module;
public class H2DatabaseTest extends TestCase { public class H2DatabaseTest extends TestCase {
@@ -97,14 +93,7 @@ public class H2DatabaseTest extends TestCase {
public H2DatabaseTest() throws Exception { public H2DatabaseTest() throws Exception {
super(); super();
Module testModule = new AbstractModule() { Injector i = Guice.createInjector(new CryptoModule(),
@Override
public void configure() {
bind(Executor.class).toInstance(
new ScheduledThreadPoolExecutor(5));
}
};
Injector i = Guice.createInjector(testModule, new CryptoModule(),
new DatabaseModule(), new LifecycleModule(), new DatabaseModule(), new LifecycleModule(),
new ProtocolModule(), new SerialModule(), new ProtocolModule(), new SerialModule(),
new ProtocolBatchModule(), new TransportModule(), new ProtocolBatchModule(), new TransportModule(),

View File

@@ -5,14 +5,10 @@ import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.TestDatabaseModule; import net.sf.briar.TestDatabaseModule;
@@ -31,8 +27,6 @@ import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportIndex; import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.protocol.TransportUpdate; import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.transport.BatchTransportReader;
import net.sf.briar.api.transport.BatchTransportWriter;
import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionReaderFactory; import net.sf.briar.api.transport.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionRecogniser; import net.sf.briar.api.transport.ConnectionRecogniser;
@@ -43,9 +37,6 @@ import net.sf.briar.db.DatabaseModule;
import net.sf.briar.lifecycle.LifecycleModule; import net.sf.briar.lifecycle.LifecycleModule;
import net.sf.briar.plugins.ImmediateExecutor; import net.sf.briar.plugins.ImmediateExecutor;
import net.sf.briar.protocol.ProtocolModule; import net.sf.briar.protocol.ProtocolModule;
import net.sf.briar.protocol.batch.IncomingBatchConnection;
import net.sf.briar.protocol.batch.OutgoingBatchConnection;
import net.sf.briar.protocol.batch.ProtocolBatchModule;
import net.sf.briar.protocol.stream.ProtocolStreamModule; import net.sf.briar.protocol.stream.ProtocolStreamModule;
import net.sf.briar.serial.SerialModule; import net.sf.briar.serial.SerialModule;
import net.sf.briar.transport.TransportModule; import net.sf.briar.transport.TransportModule;
@@ -54,10 +45,8 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module;
public class BatchConnectionReadWriteTest extends TestCase { public class BatchConnectionReadWriteTest extends TestCase {
@@ -90,16 +79,8 @@ public class BatchConnectionReadWriteTest extends TestCase {
} }
private Injector createInjector(File dir) { private Injector createInjector(File dir) {
Module testModule = new AbstractModule() { return Guice.createInjector(new CryptoModule(), new DatabaseModule(),
@Override new LifecycleModule(), new ProtocolModule(), new SerialModule(),
public void configure() {
bind(Executor.class).toInstance(
new ScheduledThreadPoolExecutor(5));
}
};
return Guice.createInjector(testModule, new CryptoModule(),
new DatabaseModule(), new LifecycleModule(),
new ProtocolModule(), new SerialModule(),
new TestDatabaseModule(dir), new ProtocolBatchModule(), new TestDatabaseModule(dir), new ProtocolBatchModule(),
new TransportModule(), new ProtocolStreamModule()); new TransportModule(), new ProtocolStreamModule());
} }
@@ -133,12 +114,14 @@ public class BatchConnectionReadWriteTest extends TestCase {
alice.getInstance(ConnectionWriterFactory.class); alice.getInstance(ConnectionWriterFactory.class);
ProtocolWriterFactory protoFactory = ProtocolWriterFactory protoFactory =
alice.getInstance(ProtocolWriterFactory.class); alice.getInstance(ProtocolWriterFactory.class);
BatchTransportWriter transport = new TestBatchTransportWriter(out); TestBatchTransportWriter transport = new TestBatchTransportWriter(out,
Long.MAX_VALUE);
OutgoingBatchConnection batchOut = new OutgoingBatchConnection(db, OutgoingBatchConnection batchOut = new OutgoingBatchConnection(db,
connFactory, protoFactory, contactId, transportIndex, connFactory, protoFactory, contactId, transportIndex,
transport); transport);
// Write whatever needs to be written // Write whatever needs to be written
batchOut.write(); batchOut.write();
assertTrue(transport.getSuccess());
// Close Alice's database // Close Alice's database
db.close(); db.close();
// Return the contents of the batch connection // Return the contents of the batch connection
@@ -187,14 +170,15 @@ public class BatchConnectionReadWriteTest extends TestCase {
bob.getInstance(ConnectionReaderFactory.class); bob.getInstance(ConnectionReaderFactory.class);
ProtocolReaderFactory protoFactory = ProtocolReaderFactory protoFactory =
bob.getInstance(ProtocolReaderFactory.class); bob.getInstance(ProtocolReaderFactory.class);
BatchTransportReader reader = new TestBatchTransportReader(in); TestBatchTransportReader transport = new TestBatchTransportReader(in);
IncomingBatchConnection batchIn = new IncomingBatchConnection( IncomingBatchConnection batchIn = new IncomingBatchConnection(
new ImmediateExecutor(), new ImmediateExecutor(), db, new ImmediateExecutor(), new ImmediateExecutor(), db,
connFactory, protoFactory, ctx, reader, tag); connFactory, protoFactory, ctx, transport, tag);
// No messages should have been added yet // No messages should have been added yet
assertFalse(listener.messagesAdded); assertFalse(listener.messagesAdded);
// Read whatever needs to be read // Read whatever needs to be read
batchIn.read(); batchIn.read();
assertTrue(transport.getSuccess());
// The private message from Alice should have been added // The private message from Alice should have been added
assertTrue(listener.messagesAdded); assertTrue(listener.messagesAdded);
// Close Bob's database // Close Bob's database
@@ -215,46 +199,6 @@ public class BatchConnectionReadWriteTest extends TestCase {
} }
} }
private static class TestBatchTransportWriter
implements BatchTransportWriter {
private final OutputStream out;
private TestBatchTransportWriter(OutputStream out) {
this.out = out;
}
public long getCapacity() {
return Long.MAX_VALUE;
}
public OutputStream getOutputStream() {
return out;
}
public void dispose(boolean success) {
assertTrue(success);
}
}
private static class TestBatchTransportReader
implements BatchTransportReader {
private final InputStream in;
private TestBatchTransportReader(InputStream in) {
this.in = in;
}
public InputStream getInputStream() {
return in;
}
public void dispose(boolean success) {
assertTrue(success);
}
}
private static class TestCallback implements Callback { private static class TestCallback implements Callback {
private final CountDownLatch latch = new CountDownLatch(1); private final CountDownLatch latch = new CountDownLatch(1);

View File

@@ -0,0 +1,29 @@
package net.sf.briar.protocol.batch;
import java.io.InputStream;
import net.sf.briar.api.transport.BatchTransportReader;
class TestBatchTransportReader
implements BatchTransportReader {
private final InputStream in;
private boolean success = false;
TestBatchTransportReader(InputStream in) {
this.in = in;
}
public InputStream getInputStream() {
return in;
}
public void dispose(boolean success) {
this.success = success;
}
boolean getSuccess() {
return success;
}
}

View File

@@ -0,0 +1,37 @@
package net.sf.briar.protocol.batch;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import net.sf.briar.api.transport.BatchTransportWriter;
class TestBatchTransportWriter
implements BatchTransportWriter {
private final ByteArrayOutputStream out;
private final long capacity;
private boolean success = false;
TestBatchTransportWriter(ByteArrayOutputStream out,
long capacity) {
this.out = out;
this.capacity = capacity;
}
public long getCapacity() {
return capacity - out.size();
}
public OutputStream getOutputStream() {
return out;
}
public void dispose(boolean success) {
this.success = success;
}
boolean getSuccess() {
return success;
}
}

View File

@@ -81,8 +81,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
will(returnValue(window)); will(returnValue(window));
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH])); assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -109,8 +109,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// The tag should not be expected by the wrong transport // The tag should not be expected by the wrong transport
TransportId wrong = new TransportId(TestUtils.getRandomId()); TransportId wrong = new TransportId(TestUtils.getRandomId());
@@ -150,8 +150,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
will(returnValue(window)); will(returnValue(window));
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Ensure the recogniser is initialised // Ensure the recogniser is initialised
assertFalse(c.isInitialised()); assertFalse(c.isInitialised());
@@ -177,8 +177,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
will(returnValue(Collections.emptyList())); will(returnValue(Collections.emptyList()));
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Remove the contact // Remove the contact
c.eventOccurred(new ContactRemovedEvent(contactId)); c.eventOccurred(new ContactRemovedEvent(contactId));
@@ -214,8 +214,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// The tag should not be expected // The tag should not be expected
assertFalse(c.isInitialised()); assertFalse(c.isInitialised());
@@ -262,8 +262,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Add the transport // Add the transport
c.eventOccurred(new TransportAddedEvent(transportId)); c.eventOccurred(new TransportAddedEvent(transportId));
@@ -309,8 +309,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// The tag should not be expected // The tag should not be expected
assertFalse(c.isInitialised()); assertFalse(c.isInitialised());
@@ -358,8 +358,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Update the contact // Update the contact
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId, c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
@@ -401,8 +401,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
will(returnValue(window)); will(returnValue(window));
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Ensure the recogniser is initialised // Ensure the recogniser is initialised
assertFalse(c.isInitialised()); assertFalse(c.isInitialised());
@@ -431,8 +431,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
will(returnValue(null)); will(returnValue(null));
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Update the contact // Update the contact
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId, c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
@@ -497,8 +497,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Ensure the recogniser is initialised // Ensure the recogniser is initialised
assertFalse(c.isInitialised()); assertFalse(c.isInitialised());
@@ -574,8 +574,8 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).setConnectionWindow(contactId, remoteIndex, window); oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
}}); }});
Executor executor = new ImmediateExecutor(); Executor executor = new ImmediateExecutor();
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db, ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
executor); crypto);
byte[] tag = calculateTag(); byte[] tag = calculateTag();
// Update the contact // Update the contact
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId, c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,

View File

@@ -5,8 +5,6 @@ import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGT
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.Random; import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.TestDatabaseModule; import net.sf.briar.TestDatabaseModule;
@@ -22,10 +20,8 @@ import net.sf.briar.serial.SerialModule;
import org.junit.Test; import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module;
public class ConnectionWriterTest extends TestCase { public class ConnectionWriterTest extends TestCase {
@@ -34,14 +30,7 @@ public class ConnectionWriterTest extends TestCase {
public ConnectionWriterTest() throws Exception { public ConnectionWriterTest() throws Exception {
super(); super();
Module testModule = new AbstractModule() { Injector i = Guice.createInjector(new CryptoModule(),
@Override
public void configure() {
bind(Executor.class).toInstance(
new ScheduledThreadPoolExecutor(5));
}
};
Injector i = Guice.createInjector(testModule, new CryptoModule(),
new DatabaseModule(), new LifecycleModule(), new DatabaseModule(), new LifecycleModule(),
new ProtocolModule(), new SerialModule(), new ProtocolModule(), new SerialModule(),
new TestDatabaseModule(), new ProtocolBatchModule(), new TestDatabaseModule(), new ProtocolBatchModule(),