Merged IncomingConnectionExecutor and PluginExecutor into IoExecutor.

We don't need two separate executors for long-running IO threads.
This commit is contained in:
akwizgran
2014-10-02 18:02:53 +01:00
parent 458c0ca285
commit 941efb4bbe
35 changed files with 172 additions and 223 deletions

View File

@@ -10,7 +10,6 @@
<item>org.briarproject.messaging.duplex.DuplexMessagingModule</item> <item>org.briarproject.messaging.duplex.DuplexMessagingModule</item>
<item>org.briarproject.messaging.simplex.SimplexMessagingModule</item> <item>org.briarproject.messaging.simplex.SimplexMessagingModule</item>
<item>org.briarproject.plugins.AndroidPluginsModule</item> <item>org.briarproject.plugins.AndroidPluginsModule</item>
<item>org.briarproject.plugins.PluginsModule</item>
<item>org.briarproject.serial.SerialModule</item> <item>org.briarproject.serial.SerialModule</item>
<item>org.briarproject.system.AndroidSystemModule</item> <item>org.briarproject.system.AndroidSystemModule</item>
<item>org.briarproject.transport.TransportModule</item> <item>org.briarproject.transport.TransportModule</item>

View File

@@ -30,8 +30,8 @@ public class SplashScreenActivity extends RoboSplashActivity {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SplashScreenActivity.class.getName()); Logger.getLogger(SplashScreenActivity.class.getName());
// This build expires on 12 July 2014 // This build expires on 8 October 2014
private static final long EXPIRY_DATE = 1405123200 * 1000L; private static final long EXPIRY_DATE = 1412726400 * 1000L;
private long now = System.currentTimeMillis(); private long now = System.currentTimeMillis();

View File

@@ -7,8 +7,8 @@ import java.util.concurrent.Executor;
import org.briarproject.api.android.AndroidExecutor; import org.briarproject.api.android.AndroidExecutor;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
import org.briarproject.api.plugins.PluginExecutor;
import org.briarproject.api.plugins.duplex.DuplexPluginConfig; import org.briarproject.api.plugins.duplex.DuplexPluginConfig;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory; import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.plugins.simplex.SimplexPluginConfig; import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
@@ -21,12 +21,9 @@ import org.briarproject.plugins.tor.TorPluginFactory;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
public class AndroidPluginsModule extends AbstractModule { public class AndroidPluginsModule extends PluginsModule {
protected void configure() {}
@Provides @Provides
SimplexPluginConfig getSimplexPluginConfig() { SimplexPluginConfig getSimplexPluginConfig() {
@@ -38,19 +35,17 @@ public class AndroidPluginsModule extends AbstractModule {
} }
@Provides @Provides
DuplexPluginConfig getDuplexPluginConfig( DuplexPluginConfig getDuplexPluginConfig(@IoExecutor Executor ioExecutor,
@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Application app, AndroidExecutor androidExecutor, Application app,
CryptoComponent crypto, LocationUtils locationUtils, CryptoComponent crypto, LocationUtils locationUtils,
ShutdownManager shutdownManager) { ShutdownManager shutdownManager) {
Context appContext = app.getApplicationContext(); Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory( DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
pluginExecutor, androidExecutor, appContext, androidExecutor, appContext, crypto.getSecureRandom());
crypto.getSecureRandom()); DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
DuplexPluginFactory tor = new TorPluginFactory(pluginExecutor, locationUtils, shutdownManager);
appContext, locationUtils, shutdownManager); DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory( appContext);
pluginExecutor, appContext);
final Collection<DuplexPluginFactory> factories = final Collection<DuplexPluginFactory> factories =
Arrays.asList(bluetooth, tor, lan); Arrays.asList(bluetooth, tor, lan);
return new DuplexPluginConfig() { return new DuplexPluginConfig() {

View File

@@ -63,7 +63,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private static final String DISCOVERY_FINISHED = private static final String DISCOVERY_FINISHED =
"android.bluetooth.adapter.action.DISCOVERY_FINISHED"; "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
private final Executor pluginExecutor; private final Executor ioExecutor;
private final AndroidExecutor androidExecutor; private final AndroidExecutor androidExecutor;
private final Context appContext; private final Context appContext;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
@@ -80,11 +80,11 @@ class DroidtoothPlugin implements DuplexPlugin {
// Non-null if the plugin started successfully // Non-null if the plugin started successfully
private volatile BluetoothAdapter adapter = null; private volatile BluetoothAdapter adapter = null;
DroidtoothPlugin(Executor pluginExecutor, AndroidExecutor androidExecutor, DroidtoothPlugin(Executor ioExecutor, AndroidExecutor androidExecutor,
Context appContext, SecureRandom secureRandom, Clock clock, Context appContext, SecureRandom secureRandom, Clock clock,
DuplexPluginCallback callback, int maxFrameLength, long maxLatency, DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
long pollingInterval) { long pollingInterval) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor; this.androidExecutor = androidExecutor;
this.appContext = appContext; this.appContext = appContext;
this.secureRandom = secureRandom; this.secureRandom = secureRandom;
@@ -147,7 +147,7 @@ class DroidtoothPlugin implements DuplexPlugin {
} }
private void bind() { private void bind() {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
if(!isRunning()) return; if(!isRunning()) return;
if(LOG.isLoggable(INFO)) if(LOG.isLoggable(INFO))
@@ -256,7 +256,7 @@ class DroidtoothPlugin implements DuplexPlugin {
if(StringUtils.isNullOrEmpty(address)) continue; if(StringUtils.isNullOrEmpty(address)) continue;
final String uuid = e.getValue().get("uuid"); final String uuid = e.getValue().get("uuid");
if(StringUtils.isNullOrEmpty(uuid)) continue; if(StringUtils.isNullOrEmpty(uuid)) continue;
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
if(!running) return; if(!running) return;
BluetoothSocket s = connect(address, uuid); BluetoothSocket s = connect(address, uuid);

View File

@@ -19,16 +19,16 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
private final Executor pluginExecutor; private final Executor ioExecutor;
private final AndroidExecutor androidExecutor; private final AndroidExecutor androidExecutor;
private final Context appContext; private final Context appContext;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final Clock clock; private final Clock clock;
public DroidtoothPluginFactory(Executor pluginExecutor, public DroidtoothPluginFactory(Executor ioExecutor,
AndroidExecutor androidExecutor, Context appContext, AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom) { SecureRandom secureRandom) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor; this.androidExecutor = androidExecutor;
this.appContext = appContext; this.appContext = appContext;
this.secureRandom = secureRandom; this.secureRandom = secureRandom;
@@ -40,7 +40,7 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
} }
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new DroidtoothPlugin(pluginExecutor, androidExecutor, appContext, return new DroidtoothPlugin(ioExecutor, androidExecutor, appContext,
secureRandom, clock, callback, MAX_FRAME_LENGTH, MAX_LATENCY, secureRandom, clock, callback, MAX_FRAME_LENGTH, MAX_LATENCY,
POLLING_INTERVAL); POLLING_INTERVAL);
} }

View File

@@ -25,10 +25,10 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
private volatile BroadcastReceiver networkStateReceiver = null; private volatile BroadcastReceiver networkStateReceiver = null;
AndroidLanTcpPlugin(Executor pluginExecutor, Context appContext, AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
DuplexPluginCallback callback, int maxFrameLength, long maxLatency, DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
long pollingInterval) { long pollingInterval) {
super(pluginExecutor, callback, maxFrameLength, maxLatency, super(ioExecutor, callback, maxFrameLength, maxLatency,
pollingInterval); pollingInterval);
this.appContext = appContext; this.appContext = appContext;
} }

View File

@@ -15,12 +15,11 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
private final Executor pluginExecutor; private final Executor ioExecutor;
private final Context appContext; private final Context appContext;
public AndroidLanTcpPluginFactory(Executor pluginExecutor, public AndroidLanTcpPluginFactory(Executor ioExecutor, Context appContext) {
Context appContext) { this.ioExecutor = ioExecutor;
this.pluginExecutor = pluginExecutor;
this.appContext = appContext; this.appContext = appContext;
} }
@@ -29,7 +28,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
} }
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new AndroidLanTcpPlugin(pluginExecutor, appContext, callback, return new AndroidLanTcpPlugin(ioExecutor, appContext, callback,
MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL); MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
} }
} }

View File

@@ -72,7 +72,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName()); Logger.getLogger(TorPlugin.class.getName());
private final Executor pluginExecutor; private final Executor ioExecutor;
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final ShutdownManager shutdownManager; private final ShutdownManager shutdownManager;
@@ -92,11 +92,11 @@ class TorPlugin implements DuplexPlugin, EventHandler {
private volatile TorControlConnection controlConnection = null; private volatile TorControlConnection controlConnection = null;
private volatile BroadcastReceiver networkStateReceiver = null; private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor pluginExecutor, Context appContext, TorPlugin(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, ShutdownManager shutdownManager, LocationUtils locationUtils, ShutdownManager shutdownManager,
DuplexPluginCallback callback, int maxFrameLength, long maxLatency, DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
long pollingInterval) { long pollingInterval) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.shutdownManager = shutdownManager; this.shutdownManager = shutdownManager;
@@ -448,7 +448,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
} }
private void bind() { private void bind() {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
// If there's already a port number stored in config, reuse it // If there's already a port number stored in config, reuse it
String portString = callback.getConfig().get("port"); String portString = callback.getConfig().get("port");
@@ -476,7 +476,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
c.put("port", localPort); c.put("port", localPort);
callback.mergeConfig(c); callback.mergeConfig(c);
// Create a hidden service if necessary // Create a hidden service if necessary
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
publishHiddenService(localPort); publishHiddenService(localPort);
} }
@@ -605,7 +605,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
} }
private void connectAndCallBack(final ContactId c) { private void connectAndCallBack(final ContactId c) {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
DuplexTransportConnection d = createConnection(c); DuplexTransportConnection d = createConnection(c);
if(d != null) callback.outgoingConnectionCreated(c, d); if(d != null) callback.outgoingConnectionCreated(c, d);

View File

@@ -22,14 +22,14 @@ public class TorPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
private final Executor pluginExecutor; private final Executor ioExecutor;
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final ShutdownManager shutdownManager; private final ShutdownManager shutdownManager;
public TorPluginFactory(Executor pluginExecutor, Context appContext, public TorPluginFactory(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, ShutdownManager shutdownManager) { LocationUtils locationUtils, ShutdownManager shutdownManager) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.shutdownManager = shutdownManager; this.shutdownManager = shutdownManager;
@@ -45,7 +45,7 @@ public class TorPluginFactory implements DuplexPluginFactory {
LOG.info("Tor is not supported on this architecture"); LOG.info("Tor is not supported on this architecture");
return null; return null;
} }
return new TorPlugin(pluginExecutor,appContext, locationUtils, return new TorPlugin(ioExecutor,appContext, locationUtils,
shutdownManager, callback, MAX_FRAME_LENGTH, MAX_LATENCY, shutdownManager, callback, MAX_FRAME_LENGTH, MAX_LATENCY,
POLLING_INTERVAL); POLLING_INTERVAL);
} }

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.plugins; package org.briarproject.api.lifecycle;
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
@@ -10,8 +10,8 @@ import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation; import com.google.inject.BindingAnnotation;
/** Annotation for injecting the executor used by transport plugins. */ /** Annotation for injecting the executor used by long-lived IO tasks. */
@BindingAnnotation @BindingAnnotation
@Target({ FIELD, METHOD, PARAMETER }) @Target({ FIELD, METHOD, PARAMETER })
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface PluginExecutor {} public @interface IoExecutor {}

View File

@@ -1,19 +0,0 @@
package org.briarproject.api.transport;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
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({ FIELD, METHOD, PARAMETER })
@Retention(RUNTIME)
public @interface IncomingConnectionExecutor {}

View File

@@ -1,18 +1,49 @@
package org.briarproject.lifecycle; package org.briarproject.lifecycle;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides;
public class LifecycleModule extends AbstractModule { public class LifecycleModule extends AbstractModule {
private final ExecutorService ioExecutor;
public LifecycleModule() {
// The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create threads as required and keep them in the pool for 60 seconds
ioExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60, SECONDS, queue, policy);
}
@Override
protected void configure() { protected void configure() {
bind(LifecycleManager.class).to( bind(LifecycleManager.class).to(
LifecycleManagerImpl.class).in(Singleton.class); LifecycleManagerImpl.class).in(Singleton.class);
bind(ShutdownManager.class).to( bind(ShutdownManager.class).to(
ShutdownManagerImpl.class).in(Singleton.class); ShutdownManagerImpl.class).in(Singleton.class);
} }
@Provides @Singleton @IoExecutor
Executor getIoExecutor(LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(ioExecutor);
return ioExecutor;
}
} }

View File

@@ -23,9 +23,9 @@ import org.briarproject.api.TransportId;
import org.briarproject.api.TransportProperties; import org.briarproject.api.TransportProperties;
import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.plugins.Plugin; import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.PluginCallback; import org.briarproject.api.plugins.PluginCallback;
import org.briarproject.api.plugins.PluginExecutor;
import org.briarproject.api.plugins.PluginManager; import org.briarproject.api.plugins.PluginManager;
import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
@@ -49,7 +49,7 @@ class PluginManagerImpl implements PluginManager {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(PluginManagerImpl.class.getName()); Logger.getLogger(PluginManagerImpl.class.getName());
private final Executor pluginExecutor; private final Executor ioExecutor;
private final SimplexPluginConfig simplexPluginConfig; private final SimplexPluginConfig simplexPluginConfig;
private final DuplexPluginConfig duplexPluginConfig; private final DuplexPluginConfig duplexPluginConfig;
private final Clock clock; private final Clock clock;
@@ -62,12 +62,12 @@ class PluginManagerImpl implements PluginManager {
private final List<DuplexPlugin> duplexPlugins; private final List<DuplexPlugin> duplexPlugins;
@Inject @Inject
PluginManagerImpl(@PluginExecutor Executor pluginExecutor, PluginManagerImpl(@IoExecutor Executor ioExecutor,
SimplexPluginConfig simplexPluginConfig, SimplexPluginConfig simplexPluginConfig,
DuplexPluginConfig duplexPluginConfig, Clock clock, DuplexPluginConfig duplexPluginConfig, Clock clock,
DatabaseComponent db, Poller poller, DatabaseComponent db, Poller poller,
ConnectionDispatcher dispatcher, UiCallback uiCallback) { ConnectionDispatcher dispatcher, UiCallback uiCallback) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.simplexPluginConfig = simplexPluginConfig; this.simplexPluginConfig = simplexPluginConfig;
this.duplexPluginConfig = duplexPluginConfig; this.duplexPluginConfig = duplexPluginConfig;
this.clock = clock; this.clock = clock;
@@ -87,14 +87,14 @@ class PluginManagerImpl implements PluginManager {
simplexPluginConfig.getFactories(); simplexPluginConfig.getFactories();
final CountDownLatch sLatch = new CountDownLatch(sFactories.size()); final CountDownLatch sLatch = new CountDownLatch(sFactories.size());
for(SimplexPluginFactory factory : sFactories) for(SimplexPluginFactory factory : sFactories)
pluginExecutor.execute(new SimplexPluginStarter(factory, sLatch)); ioExecutor.execute(new SimplexPluginStarter(factory, sLatch));
// Instantiate and start the duplex plugins // Instantiate and start the duplex plugins
LOG.info("Starting duplex plugins"); LOG.info("Starting duplex plugins");
Collection<DuplexPluginFactory> dFactories = Collection<DuplexPluginFactory> dFactories =
duplexPluginConfig.getFactories(); duplexPluginConfig.getFactories();
final CountDownLatch dLatch = new CountDownLatch(dFactories.size()); final CountDownLatch dLatch = new CountDownLatch(dFactories.size());
for(DuplexPluginFactory factory : dFactories) for(DuplexPluginFactory factory : dFactories)
pluginExecutor.execute(new DuplexPluginStarter(factory, dLatch)); ioExecutor.execute(new DuplexPluginStarter(factory, dLatch));
// Wait for the plugins to start // Wait for the plugins to start
try { try {
sLatch.await(); sLatch.await();
@@ -119,11 +119,11 @@ class PluginManagerImpl implements PluginManager {
// Stop the simplex plugins // Stop the simplex plugins
LOG.info("Stopping simplex plugins"); LOG.info("Stopping simplex plugins");
for(SimplexPlugin plugin : simplexPlugins) for(SimplexPlugin plugin : simplexPlugins)
pluginExecutor.execute(new PluginStopper(plugin, latch)); ioExecutor.execute(new PluginStopper(plugin, latch));
// Stop the duplex plugins // Stop the duplex plugins
LOG.info("Stopping duplex plugins"); LOG.info("Stopping duplex plugins");
for(DuplexPlugin plugin : duplexPlugins) for(DuplexPlugin plugin : duplexPlugins)
pluginExecutor.execute(new PluginStopper(plugin, latch)); ioExecutor.execute(new PluginStopper(plugin, latch));
plugins.clear(); plugins.clear();
simplexPlugins.clear(); simplexPlugins.clear();
duplexPlugins.clear(); duplexPlugins.clear();

View File

@@ -1,18 +1,8 @@
package org.briarproject.plugins; package org.briarproject.plugins;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.plugins.PluginExecutor;
import org.briarproject.api.plugins.PluginManager; import org.briarproject.api.plugins.PluginManager;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
@@ -20,19 +10,7 @@ import com.google.inject.Provides;
public class PluginsModule extends AbstractModule { public class PluginsModule extends AbstractModule {
private final ExecutorService pluginExecutor; @Override
public PluginsModule() {
// The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create threads as required and keep them in the pool for 60 seconds
pluginExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60, SECONDS, queue, policy);
}
protected void configure() { protected void configure() {
bind(Poller.class).to(PollerImpl.class); bind(Poller.class).to(PollerImpl.class);
} }
@@ -43,10 +21,4 @@ public class PluginsModule extends AbstractModule {
lifecycleManager.register(pluginManager); lifecycleManager.register(pluginManager);
return pluginManager; return pluginManager;
} }
@Provides @Singleton @PluginExecutor
Executor getPluginExecutor(LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(pluginExecutor);
return pluginExecutor;
}
} }

View File

@@ -9,8 +9,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.plugins.Plugin; import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.PluginExecutor;
import org.briarproject.api.system.Timer; import org.briarproject.api.system.Timer;
import org.briarproject.api.transport.ConnectionRegistry; import org.briarproject.api.transport.ConnectionRegistry;
@@ -19,14 +19,14 @@ class PollerImpl implements Poller {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(PollerImpl.class.getName()); Logger.getLogger(PollerImpl.class.getName());
private final Executor pluginExecutor; private final Executor ioExecutor;
private final ConnectionRegistry connRegistry; private final ConnectionRegistry connRegistry;
private final Timer timer; private final Timer timer;
@Inject @Inject
PollerImpl(@PluginExecutor Executor pluginExecutor, PollerImpl(@IoExecutor Executor ioExecutor, ConnectionRegistry connRegistry,
ConnectionRegistry connRegistry, Timer timer) { Timer timer) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.connRegistry = connRegistry; this.connRegistry = connRegistry;
this.timer = timer; this.timer = timer;
} }
@@ -49,7 +49,7 @@ class PollerImpl implements Poller {
} }
public void pollNow(final Plugin p) { public void pollNow(final Plugin p) {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
if(LOG.isLoggable(INFO)) if(LOG.isLoggable(INFO))
LOG.info("Polling " + p.getClass().getSimpleName()); LOG.info("Polling " + p.getClass().getSimpleName());
@@ -66,6 +66,7 @@ class PollerImpl implements Poller {
this.plugin = plugin; this.plugin = plugin;
} }
@Override
public void run() { public void run() {
pollNow(plugin); pollNow(plugin);
schedule(plugin, false); schedule(plugin, false);

View File

@@ -25,7 +25,7 @@ public abstract class FilePlugin implements SimplexPlugin {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(FilePlugin.class.getName()); Logger.getLogger(FilePlugin.class.getName());
protected final Executor pluginExecutor; protected final Executor ioExecutor;
protected final FileUtils fileUtils; protected final FileUtils fileUtils;
protected final SimplexPluginCallback callback; protected final SimplexPluginCallback callback;
protected final int maxFrameLength; protected final int maxFrameLength;
@@ -38,10 +38,10 @@ public abstract class FilePlugin implements SimplexPlugin {
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 pluginExecutor, FileUtils fileUtils, protected FilePlugin(Executor ioExecutor, FileUtils fileUtils,
SimplexPluginCallback callback, int maxFrameLength, SimplexPluginCallback callback, int maxFrameLength,
long maxLatency) { long maxLatency) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.fileUtils = fileUtils; this.fileUtils = fileUtils;
this.callback = callback; this.callback = callback;
this.maxFrameLength = maxFrameLength; this.maxFrameLength = maxFrameLength;
@@ -100,7 +100,7 @@ public abstract class FilePlugin implements SimplexPlugin {
protected void createReaderFromFile(final File f) { protected void createReaderFromFile(final File f) {
if(!running) return; if(!running) return;
pluginExecutor.execute(new ReaderCreator(f)); ioExecutor.execute(new ReaderCreator(f));
} }
private class ReaderCreator implements Runnable { private class ReaderCreator implements Runnable {

View File

@@ -16,9 +16,9 @@ class LanTcpPlugin extends TcpPlugin {
static final TransportId ID = new TransportId("lan"); static final TransportId ID = new TransportId("lan");
LanTcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback, LanTcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
int maxFrameLength, long maxLatency, long pollingInterval) { int maxFrameLength, long maxLatency, long pollingInterval) {
super(pluginExecutor, callback, maxFrameLength, maxLatency, super(ioExecutor, callback, maxFrameLength, maxLatency,
pollingInterval); pollingInterval);
} }

View File

@@ -13,10 +13,10 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
private final Executor pluginExecutor; private final Executor ioExecutor;
public LanTcpPluginFactory(Executor pluginExecutor) { public LanTcpPluginFactory(Executor ioExecutor) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
} }
public TransportId getId() { public TransportId getId() {
@@ -24,7 +24,7 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
} }
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new LanTcpPlugin(pluginExecutor, callback, MAX_FRAME_LENGTH, return new LanTcpPlugin(ioExecutor, callback, MAX_FRAME_LENGTH,
MAX_LATENCY, POLLING_INTERVAL); MAX_LATENCY, POLLING_INTERVAL);
} }
} }

View File

@@ -35,7 +35,7 @@ abstract class TcpPlugin implements DuplexPlugin {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TcpPlugin.class.getName()); Logger.getLogger(TcpPlugin.class.getName());
protected final Executor pluginExecutor; protected final Executor ioExecutor;
protected final DuplexPluginCallback callback; protected final DuplexPluginCallback callback;
protected final int maxFrameLength; protected final int maxFrameLength;
protected final long maxLatency, pollingInterval; protected final long maxLatency, pollingInterval;
@@ -52,9 +52,9 @@ abstract class TcpPlugin implements DuplexPlugin {
/** Returns true if connections to the given address can be attempted. */ /** Returns true if connections to the given address can be attempted. */
protected abstract boolean isConnectable(InetSocketAddress remote); protected abstract boolean isConnectable(InetSocketAddress remote);
protected TcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback, protected TcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
int maxFrameLength, long maxLatency, long pollingInterval) { int maxFrameLength, long maxLatency, long pollingInterval) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.callback = callback; this.callback = callback;
this.maxFrameLength = maxFrameLength; this.maxFrameLength = maxFrameLength;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
@@ -76,7 +76,7 @@ abstract class TcpPlugin implements DuplexPlugin {
} }
protected void bind() { protected void bind() {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
if(!running) return; if(!running) return;
ServerSocket ss = null; ServerSocket ss = null;
@@ -172,7 +172,7 @@ abstract class TcpPlugin implements DuplexPlugin {
} }
private void connectAndCallBack(final ContactId c) { private void connectAndCallBack(final ContactId c) {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
DuplexTransportConnection d = createConnection(c); DuplexTransportConnection d = createConnection(c);
if(d != null) callback.outgoingConnectionCreated(c, d); if(d != null) callback.outgoingConnectionCreated(c, d);

View File

@@ -20,10 +20,10 @@ class WanTcpPlugin extends TcpPlugin {
private volatile MappingResult mappingResult; private volatile MappingResult mappingResult;
WanTcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback, WanTcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
int maxFrameLength, long maxLatency, long pollingInterval, int maxFrameLength, long maxLatency, long pollingInterval,
PortMapper portMapper) { PortMapper portMapper) {
super(pluginExecutor, callback, maxFrameLength, maxLatency, super(ioExecutor, callback, maxFrameLength, maxLatency,
pollingInterval); pollingInterval);
this.portMapper = portMapper; this.portMapper = portMapper;
} }

View File

@@ -14,12 +14,12 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes private static final long POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes
private final Executor pluginExecutor; private final Executor ioExecutor;
private final ShutdownManager shutdownManager; private final ShutdownManager shutdownManager;
public WanTcpPluginFactory(Executor pluginExecutor, public WanTcpPluginFactory(Executor ioExecutor,
ShutdownManager shutdownManager) { ShutdownManager shutdownManager) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.shutdownManager = shutdownManager; this.shutdownManager = shutdownManager;
} }
@@ -28,7 +28,7 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
} }
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new WanTcpPlugin(pluginExecutor, callback, MAX_FRAME_LENGTH, return new WanTcpPlugin(ioExecutor, callback, MAX_FRAME_LENGTH,
MAX_LATENCY, POLLING_INTERVAL, MAX_LATENCY, POLLING_INTERVAL,
new PortMapperImpl(shutdownManager)); new PortMapperImpl(shutdownManager));
} }

View File

@@ -14,6 +14,7 @@ import javax.inject.Inject;
import org.briarproject.api.ContactId; import org.briarproject.api.ContactId;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.messaging.duplex.DuplexConnectionFactory; import org.briarproject.api.messaging.duplex.DuplexConnectionFactory;
import org.briarproject.api.messaging.simplex.SimplexConnectionFactory; import org.briarproject.api.messaging.simplex.SimplexConnectionFactory;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
@@ -22,31 +23,30 @@ import org.briarproject.api.plugins.simplex.SimplexTransportWriter;
import org.briarproject.api.transport.ConnectionContext; import org.briarproject.api.transport.ConnectionContext;
import org.briarproject.api.transport.ConnectionDispatcher; import org.briarproject.api.transport.ConnectionDispatcher;
import org.briarproject.api.transport.ConnectionRecogniser; import org.briarproject.api.transport.ConnectionRecogniser;
import org.briarproject.api.transport.IncomingConnectionExecutor;
class ConnectionDispatcherImpl implements ConnectionDispatcher { class ConnectionDispatcherImpl implements ConnectionDispatcher {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(ConnectionDispatcherImpl.class.getName()); Logger.getLogger(ConnectionDispatcherImpl.class.getName());
private final Executor connExecutor; private final Executor ioExecutor;
private final ConnectionRecogniser recogniser; private final ConnectionRecogniser recogniser;
private final SimplexConnectionFactory simplexConnFactory; private final SimplexConnectionFactory simplexConnFactory;
private final DuplexConnectionFactory duplexConnFactory; private final DuplexConnectionFactory duplexConnFactory;
@Inject @Inject
ConnectionDispatcherImpl(@IncomingConnectionExecutor Executor connExecutor, ConnectionDispatcherImpl(@IoExecutor Executor ioExecutor,
ConnectionRecogniser recogniser, ConnectionRecogniser recogniser,
SimplexConnectionFactory simplexConnFactory, SimplexConnectionFactory simplexConnFactory,
DuplexConnectionFactory duplexConnFactory) { DuplexConnectionFactory duplexConnFactory) {
this.connExecutor = connExecutor; this.ioExecutor = ioExecutor;
this.recogniser = recogniser; this.recogniser = recogniser;
this.simplexConnFactory = simplexConnFactory; this.simplexConnFactory = simplexConnFactory;
this.duplexConnFactory = duplexConnFactory; this.duplexConnFactory = duplexConnFactory;
} }
public void dispatchReader(TransportId t, SimplexTransportReader r) { public void dispatchReader(TransportId t, SimplexTransportReader r) {
connExecutor.execute(new DispatchSimplexConnection(t, r)); ioExecutor.execute(new DispatchSimplexConnection(t, r));
} }
public void dispatchWriter(ContactId c, TransportId t, public void dispatchWriter(ContactId c, TransportId t,
@@ -56,7 +56,7 @@ class ConnectionDispatcherImpl implements ConnectionDispatcher {
public void dispatchIncomingConnection(TransportId t, public void dispatchIncomingConnection(TransportId t,
DuplexTransportConnection d) { DuplexTransportConnection d) {
connExecutor.execute(new DispatchDuplexConnection(t, d)); ioExecutor.execute(new DispatchDuplexConnection(t, d));
} }
public void dispatchOutgoingConnection(ContactId c, TransportId t, public void dispatchOutgoingConnection(ContactId c, TransportId t,

View File

@@ -1,14 +1,5 @@
package org.briarproject.transport; package org.briarproject.transport;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.briarproject.api.crypto.KeyManager; import org.briarproject.api.crypto.KeyManager;
@@ -18,26 +9,13 @@ import org.briarproject.api.transport.ConnectionReaderFactory;
import org.briarproject.api.transport.ConnectionRecogniser; import org.briarproject.api.transport.ConnectionRecogniser;
import org.briarproject.api.transport.ConnectionRegistry; import org.briarproject.api.transport.ConnectionRegistry;
import org.briarproject.api.transport.ConnectionWriterFactory; import org.briarproject.api.transport.ConnectionWriterFactory;
import org.briarproject.api.transport.IncomingConnectionExecutor;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
public class TransportModule extends AbstractModule { public class TransportModule extends AbstractModule {
private final ExecutorService incomingConnectionExecutor; @Override
public TransportModule() {
// The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create threads as required and keep them in the pool for 60 seconds
incomingConnectionExecutor = new ThreadPoolExecutor(0,
Integer.MAX_VALUE, 60, SECONDS, queue, policy);
}
protected void configure() { protected void configure() {
bind(ConnectionDispatcher.class).to(ConnectionDispatcherImpl.class); bind(ConnectionDispatcher.class).to(ConnectionDispatcherImpl.class);
bind(ConnectionReaderFactory.class).to( bind(ConnectionReaderFactory.class).to(
@@ -55,10 +33,4 @@ public class TransportModule extends AbstractModule {
lifecycleManager.register(keyManager); lifecycleManager.register(keyManager);
return keyManager; return keyManager;
} }
@Provides @Singleton @IncomingConnectionExecutor
Executor getIncomingConnectionExecutor(LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(incomingConnectionExecutor);
return incomingConnectionExecutor;
}
} }

View File

@@ -4,21 +4,20 @@ import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
import org.briarproject.util.OsUtils; import org.briarproject.util.OsUtils;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton; import com.google.inject.Singleton;
public class DesktopLifecycleModule extends AbstractModule { public class DesktopLifecycleModule extends LifecycleModule {
@Override
protected void configure() { protected void configure() {
bind(LifecycleManager.class).to( bind(LifecycleManager.class).to(
LifecycleManagerImpl.class).in(Singleton.class); LifecycleManagerImpl.class).in(Singleton.class);
if(OsUtils.isWindows()) { if(OsUtils.isWindows()) {
bind(ShutdownManager.class).to( bind(ShutdownManager.class).to(
WindowsShutdownManagerImpl.class).in( WindowsShutdownManagerImpl.class).in(Singleton.class);
Singleton.class);
} else { } else {
bind(ShutdownManager.class).to( bind(ShutdownManager.class).to(
ShutdownManagerImpl.class).in(Singleton.class); ShutdownManagerImpl.class).in(Singleton.class);
} }
} }
} }

View File

@@ -5,8 +5,8 @@ import java.util.Collection;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
import org.briarproject.api.plugins.PluginExecutor;
import org.briarproject.api.plugins.duplex.DuplexPluginConfig; import org.briarproject.api.plugins.duplex.DuplexPluginConfig;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory; import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.plugins.simplex.SimplexPluginConfig; import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
@@ -19,18 +19,15 @@ import org.briarproject.plugins.modem.ModemPluginFactory;
import org.briarproject.plugins.tcp.LanTcpPluginFactory; import org.briarproject.plugins.tcp.LanTcpPluginFactory;
import org.briarproject.plugins.tcp.WanTcpPluginFactory; import org.briarproject.plugins.tcp.WanTcpPluginFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
public class DesktopPluginsModule extends AbstractModule { public class DesktopPluginsModule extends PluginsModule {
public void configure() {}
@Provides @Provides
SimplexPluginConfig getSimplexPluginConfig( SimplexPluginConfig getSimplexPluginConfig(@IoExecutor Executor ioExecutor,
@PluginExecutor Executor pluginExecutor, FileUtils fileUtils) { FileUtils fileUtils) {
SimplexPluginFactory removable = SimplexPluginFactory removable =
new RemovableDrivePluginFactory(pluginExecutor, fileUtils); new RemovableDrivePluginFactory(ioExecutor, fileUtils);
final Collection<SimplexPluginFactory> factories = final Collection<SimplexPluginFactory> factories =
Arrays.asList(removable); Arrays.asList(removable);
return new SimplexPluginConfig() { return new SimplexPluginConfig() {
@@ -41,16 +38,15 @@ public class DesktopPluginsModule extends AbstractModule {
} }
@Provides @Provides
DuplexPluginConfig getDuplexPluginConfig( DuplexPluginConfig getDuplexPluginConfig(@IoExecutor Executor ioExecutor,
@PluginExecutor Executor pluginExecutor,
CryptoComponent crypto, ReliabilityLayerFactory reliabilityFactory, CryptoComponent crypto, ReliabilityLayerFactory reliabilityFactory,
ShutdownManager shutdownManager) { ShutdownManager shutdownManager) {
DuplexPluginFactory bluetooth = new BluetoothPluginFactory( DuplexPluginFactory bluetooth = new BluetoothPluginFactory(
pluginExecutor, crypto.getSecureRandom()); ioExecutor, crypto.getSecureRandom());
DuplexPluginFactory modem = new ModemPluginFactory(pluginExecutor, DuplexPluginFactory modem = new ModemPluginFactory(ioExecutor,
reliabilityFactory); reliabilityFactory);
DuplexPluginFactory lan = new LanTcpPluginFactory(pluginExecutor); DuplexPluginFactory lan = new LanTcpPluginFactory(ioExecutor);
DuplexPluginFactory wan = new WanTcpPluginFactory(pluginExecutor, DuplexPluginFactory wan = new WanTcpPluginFactory(ioExecutor,
shutdownManager); shutdownManager);
final Collection<DuplexPluginFactory> factories = final Collection<DuplexPluginFactory> factories =
Arrays.asList(bluetooth, modem, lan, wan); Arrays.asList(bluetooth, modem, lan, wan);

View File

@@ -42,7 +42,7 @@ class BluetoothPlugin implements DuplexPlugin {
Logger.getLogger(BluetoothPlugin.class.getName()); Logger.getLogger(BluetoothPlugin.class.getName());
private static final int UUID_BYTES = 16; private static final int UUID_BYTES = 16;
private final Executor pluginExecutor; private final Executor ioExecutor;
private final Clock clock; private final Clock clock;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
@@ -54,10 +54,10 @@ class BluetoothPlugin implements DuplexPlugin {
private volatile StreamConnectionNotifier socket = null; private volatile StreamConnectionNotifier socket = null;
private volatile LocalDevice localDevice = null; private volatile LocalDevice localDevice = null;
BluetoothPlugin(Executor pluginExecutor, Clock clock, BluetoothPlugin(Executor ioExecutor, Clock clock, SecureRandom secureRandom,
SecureRandom secureRandom, DuplexPluginCallback callback, DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
int maxFrameLength, long maxLatency, long pollingInterval) { long pollingInterval) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.clock = clock; this.clock = clock;
this.secureRandom = secureRandom; this.secureRandom = secureRandom;
this.callback = callback; this.callback = callback;
@@ -96,7 +96,7 @@ class BluetoothPlugin implements DuplexPlugin {
} }
private void bind() { private void bind() {
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
if(!running) return; if(!running) return;
// Advertise the Bluetooth address to contacts // Advertise the Bluetooth address to contacts
@@ -197,7 +197,7 @@ class BluetoothPlugin implements DuplexPlugin {
if(StringUtils.isNullOrEmpty(address)) continue; if(StringUtils.isNullOrEmpty(address)) continue;
final String uuid = e.getValue().get("uuid"); final String uuid = e.getValue().get("uuid");
if(StringUtils.isNullOrEmpty(uuid)) continue; if(StringUtils.isNullOrEmpty(uuid)) continue;
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
if(!running) return; if(!running) return;
StreamConnection s = connect(makeUrl(address, uuid)); StreamConnection s = connect(makeUrl(address, uuid));

View File

@@ -16,13 +16,13 @@ public class BluetoothPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
private final Executor pluginExecutor; private final Executor ioExecutor;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final Clock clock; private final Clock clock;
public BluetoothPluginFactory(Executor pluginExecutor, public BluetoothPluginFactory(Executor ioExecutor,
SecureRandom secureRandom) { SecureRandom secureRandom) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.secureRandom = secureRandom; this.secureRandom = secureRandom;
clock = new SystemClock(); clock = new SystemClock();
} }
@@ -32,7 +32,7 @@ public class BluetoothPluginFactory implements DuplexPluginFactory {
} }
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new BluetoothPlugin(pluginExecutor, clock, secureRandom, return new BluetoothPlugin(ioExecutor, clock, secureRandom, callback,
callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL); MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
} }
} }

View File

@@ -11,7 +11,7 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(PollingRemovableDriveMonitor.class.getName()); Logger.getLogger(PollingRemovableDriveMonitor.class.getName());
private final Executor pluginExecutor; private final Executor ioExecutor;
private final RemovableDriveFinder finder; private final RemovableDriveFinder finder;
private final long pollingInterval; private final long pollingInterval;
private final Object pollingLock = new Object(); private final Object pollingLock = new Object();
@@ -19,9 +19,9 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
private volatile boolean running = false; private volatile boolean running = false;
private volatile Callback callback = null; private volatile Callback callback = null;
public PollingRemovableDriveMonitor(Executor pluginExecutor, public PollingRemovableDriveMonitor(Executor ioExecutor,
RemovableDriveFinder finder, long pollingInterval) { RemovableDriveFinder finder, long pollingInterval) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.finder = finder; this.finder = finder;
this.pollingInterval = pollingInterval; this.pollingInterval = pollingInterval;
} }
@@ -29,7 +29,7 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
public void start(Callback callback) throws IOException { public void start(Callback callback) throws IOException {
this.callback = callback; this.callback = callback;
running = true; running = true;
pluginExecutor.execute(this); ioExecutor.execute(this);
} }
public void stop() throws IOException { public void stop() throws IOException {

View File

@@ -27,11 +27,11 @@ implements RemovableDriveMonitor.Callback {
private final RemovableDriveFinder finder; private final RemovableDriveFinder finder;
private final RemovableDriveMonitor monitor; private final RemovableDriveMonitor monitor;
RemovableDrivePlugin(Executor pluginExecutor, FileUtils fileUtils, RemovableDrivePlugin(Executor ioExecutor, FileUtils fileUtils,
SimplexPluginCallback callback, RemovableDriveFinder finder, SimplexPluginCallback callback, RemovableDriveFinder finder,
RemovableDriveMonitor monitor, int maxFrameLength, RemovableDriveMonitor monitor, int maxFrameLength,
long maxLatency) { long maxLatency) {
super(pluginExecutor, fileUtils, callback, maxFrameLength, maxLatency); super(ioExecutor, fileUtils, callback, maxFrameLength, maxLatency);
this.finder = finder; this.finder = finder;
this.monitor = monitor; this.monitor = monitor;
} }

View File

@@ -17,12 +17,12 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
private static final long MAX_LATENCY = 14 * 24 * 60 * 60 * 1000; private static final long MAX_LATENCY = 14 * 24 * 60 * 60 * 1000;
private static final long POLLING_INTERVAL = 10 * 1000; // 10 seconds private static final long POLLING_INTERVAL = 10 * 1000; // 10 seconds
private final Executor pluginExecutor; private final Executor ioExecutor;
private final FileUtils fileUtils; private final FileUtils fileUtils;
public RemovableDrivePluginFactory(Executor pluginExecutor, public RemovableDrivePluginFactory(Executor ioExecutor,
FileUtils fileUtils) { FileUtils fileUtils) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.fileUtils = fileUtils; this.fileUtils = fileUtils;
} }
@@ -42,16 +42,16 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
} else if(OsUtils.isMac()) { } else if(OsUtils.isMac()) {
// JNotify requires OS X 10.5 or newer, so we have to poll // JNotify requires OS X 10.5 or newer, so we have to poll
finder = new MacRemovableDriveFinder(); finder = new MacRemovableDriveFinder();
monitor = new PollingRemovableDriveMonitor(pluginExecutor, finder, monitor = new PollingRemovableDriveMonitor(ioExecutor, finder,
POLLING_INTERVAL); POLLING_INTERVAL);
} else if(OsUtils.isWindows()) { } else if(OsUtils.isWindows()) {
finder = new WindowsRemovableDriveFinder(); finder = new WindowsRemovableDriveFinder();
monitor = new PollingRemovableDriveMonitor(pluginExecutor, finder, monitor = new PollingRemovableDriveMonitor(ioExecutor, finder,
POLLING_INTERVAL); POLLING_INTERVAL);
} else { } else {
return null; return null;
} }
return new RemovableDrivePlugin(pluginExecutor, fileUtils, callback, return new RemovableDrivePlugin(ioExecutor, fileUtils, callback,
finder, monitor, MAX_FRAME_LENGTH, MAX_LATENCY); finder, monitor, MAX_FRAME_LENGTH, MAX_LATENCY);
} }
} }

View File

@@ -32,7 +32,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(ModemPlugin.class.getName()); Logger.getLogger(ModemPlugin.class.getName());
private final Executor pluginExecutor; private final Executor ioExecutor;
private final ModemFactory modemFactory; private final ModemFactory modemFactory;
private final SerialPortList serialPortList; private final SerialPortList serialPortList;
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
@@ -43,11 +43,11 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private volatile boolean running = false; private volatile boolean running = false;
private volatile Modem modem = null; private volatile Modem modem = null;
ModemPlugin(Executor pluginExecutor, ModemFactory modemFactory, ModemPlugin(Executor ioExecutor, ModemFactory modemFactory,
SerialPortList serialPortList, DuplexPluginCallback callback, SerialPortList serialPortList, DuplexPluginCallback callback,
int maxFrameLength, long maxLatency, long pollingInterval, int maxFrameLength, long maxLatency, long pollingInterval,
boolean shuffle) { boolean shuffle) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
this.modemFactory = modemFactory; this.modemFactory = modemFactory;
this.serialPortList = serialPortList; this.serialPortList = serialPortList;
this.callback = callback; this.callback = callback;
@@ -112,7 +112,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
public void poll(Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if(!connected.isEmpty()) return; // One at a time please if(!connected.isEmpty()) return; // One at a time please
pluginExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
poll(); poll();
} }

View File

@@ -15,14 +15,14 @@ public class ModemPluginFactory implements DuplexPluginFactory {
private static final long MAX_LATENCY = 60 * 1000; // 1 minute private static final long MAX_LATENCY = 60 * 1000; // 1 minute
private static final long POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour private static final long POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour
private final Executor pluginExecutor; private final Executor ioExecutor;
private final ModemFactory modemFactory; private final ModemFactory modemFactory;
private final SerialPortList serialPortList; private final SerialPortList serialPortList;
public ModemPluginFactory(Executor pluginExecutor, public ModemPluginFactory(Executor ioExecutor,
ReliabilityLayerFactory reliabilityFactory) { ReliabilityLayerFactory reliabilityFactory) {
this.pluginExecutor = pluginExecutor; this.ioExecutor = ioExecutor;
modemFactory = new ModemFactoryImpl(pluginExecutor, reliabilityFactory); modemFactory = new ModemFactoryImpl(ioExecutor, reliabilityFactory);
serialPortList = new SerialPortListImpl(); serialPortList = new SerialPortListImpl();
} }
@@ -34,7 +34,7 @@ public class ModemPluginFactory implements DuplexPluginFactory {
// This plugin is not enabled by default // This plugin is not enabled by default
String enabled = callback.getConfig().get("enabled"); String enabled = callback.getConfig().get("enabled");
if(StringUtils.isNullOrEmpty(enabled)) return null; if(StringUtils.isNullOrEmpty(enabled)) return null;
return new ModemPlugin(pluginExecutor, modemFactory, serialPortList, return new ModemPlugin(ioExecutor, modemFactory, serialPortList,
callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL, callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL,
true); true);
} }

View File

@@ -1,7 +1,10 @@
package org.briarproject; package org.briarproject;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.lifecycle.Service; import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
@@ -10,6 +13,7 @@ import com.google.inject.AbstractModule;
public class TestLifecycleModule extends AbstractModule { public class TestLifecycleModule extends AbstractModule {
@Override
protected void configure() { protected void configure() {
bind(LifecycleManager.class).toInstance(new LifecycleManager() { bind(LifecycleManager.class).toInstance(new LifecycleManager() {
@@ -37,5 +41,7 @@ public class TestLifecycleModule extends AbstractModule {
return true; return true;
} }
}); });
bind(Executor.class).annotatedWith(IoExecutor.class).toInstance(
Executors.newCachedThreadPool());
} }
} }

View File

@@ -29,7 +29,7 @@ public class PluginManagerImplTest extends BriarTestCase {
public void testStartAndStop() throws Exception { public void testStartAndStop() throws Exception {
Clock clock = new SystemClock(); Clock clock = new SystemClock();
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor pluginExecutor = Executors.newCachedThreadPool(); final Executor ioExecutor = Executors.newCachedThreadPool();
final SimplexPluginConfig simplexPluginConfig = final SimplexPluginConfig simplexPluginConfig =
context.mock(SimplexPluginConfig.class); context.mock(SimplexPluginConfig.class);
final DuplexPluginConfig duplexPluginConfig = final DuplexPluginConfig duplexPluginConfig =
@@ -116,7 +116,7 @@ public class PluginManagerImplTest extends BriarTestCase {
oneOf(simplexPlugin).stop(); oneOf(simplexPlugin).stop();
oneOf(duplexPlugin).stop(); oneOf(duplexPlugin).stop();
}}); }});
PluginManagerImpl p = new PluginManagerImpl(pluginExecutor, PluginManagerImpl p = new PluginManagerImpl(ioExecutor,
simplexPluginConfig, duplexPluginConfig, clock, db, poller, simplexPluginConfig, duplexPluginConfig, clock, db, poller,
dispatcher, uiCallback); dispatcher, uiCallback);
// Two plugins should be started and stopped // Two plugins should be started and stopped

View File

@@ -15,7 +15,6 @@ import org.briarproject.api.ContactId;
import org.briarproject.api.TransportProperties; import org.briarproject.api.TransportProperties;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.hamcrest.Description; import org.hamcrest.Description;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery; import org.jmock.Mockery;
@@ -194,8 +193,7 @@ public class ModemPluginTest extends BriarTestCase {
@Test @Test
public void testPolling() throws Exception { public void testPolling() throws Exception {
final ExecutorService pluginExecutor = final ExecutorService ioExecutor = Executors.newSingleThreadExecutor();
Executors.newSingleThreadExecutor();
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); final ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = final SerialPortList serialPortList =
@@ -203,7 +201,7 @@ public class ModemPluginTest extends BriarTestCase {
final DuplexPluginCallback callback = final DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
// Disable shuffling for this test, it confuses jMock // Disable shuffling for this test, it confuses jMock
final ModemPlugin plugin = new ModemPlugin(pluginExecutor, modemFactory, final ModemPlugin plugin = new ModemPlugin(ioExecutor, modemFactory,
serialPortList, callback, 0, 0, 0, false); serialPortList, callback, 0, 0, 0, false);
final Modem modem = context.mock(Modem.class); final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); final TransportProperties local = new TransportProperties();
@@ -265,7 +263,7 @@ public class ModemPluginTest extends BriarTestCase {
assertTrue(plugin.start()); assertTrue(plugin.start());
plugin.poll(Collections.<ContactId>emptyList()); plugin.poll(Collections.<ContactId>emptyList());
assertTrue(disposeAction.invoked.await(5, SECONDS)); assertTrue(disposeAction.invoked.await(5, SECONDS));
pluginExecutor.shutdown(); ioExecutor.shutdown();
context.assertIsSatisfied(); context.assertIsSatisfied();
} }