forked from I2P_Developers/i2p.i2p
ReadWriteLock in TunnelControlGroup (#815)
This commit is contained in:
@@ -11,11 +11,12 @@ import java.util.Properties;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.app.*;
|
import net.i2p.app.*;
|
||||||
@@ -43,6 +44,7 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config";
|
static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config";
|
||||||
|
|
||||||
private final List<TunnelController> _controllers;
|
private final List<TunnelController> _controllers;
|
||||||
|
private final ReadWriteLock _controllersLock;
|
||||||
private final String _configFile;
|
private final String _configFile;
|
||||||
|
|
||||||
private static final String REGISTERED_NAME = "i2ptunnel";
|
private static final String REGISTERED_NAME = "i2ptunnel";
|
||||||
@@ -105,6 +107,7 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
_mgr = mgr;
|
_mgr = mgr;
|
||||||
_log = _context.logManager().getLog(TunnelControllerGroup.class);
|
_log = _context.logManager().getLog(TunnelControllerGroup.class);
|
||||||
_controllers = new ArrayList<TunnelController>();
|
_controllers = new ArrayList<TunnelController>();
|
||||||
|
_controllersLock = new ReentrantReadWriteLock(true);
|
||||||
if (args == null || args.length <= 0)
|
if (args == null || args.length <= 0)
|
||||||
_configFile = DEFAULT_CONFIG_FILE;
|
_configFile = DEFAULT_CONFIG_FILE;
|
||||||
else if (args.length == 1)
|
else if (args.length == 1)
|
||||||
@@ -244,13 +247,18 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
changeState(STARTING);
|
changeState(STARTING);
|
||||||
Properties cfg = loadConfig(configFile);
|
Properties cfg = loadConfig(configFile);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (true) {
|
_controllersLock.writeLock().lock();
|
||||||
String type = cfg.getProperty("tunnel." + i + ".type");
|
try {
|
||||||
if (type == null)
|
while (true) {
|
||||||
break;
|
String type = cfg.getProperty("tunnel." + i + ".type");
|
||||||
TunnelController controller = new TunnelController(cfg, "tunnel." + i + ".");
|
if (type == null)
|
||||||
_controllers.add(controller);
|
break;
|
||||||
i++;
|
TunnelController controller = new TunnelController(cfg, "tunnel." + i + ".");
|
||||||
|
_controllers.add(controller);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_controllersLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
I2PAppThread startupThread = new I2PAppThread(new StartControllers(), "Startup tunnels");
|
I2PAppThread startupThread = new I2PAppThread(new StartControllers(), "Startup tunnels");
|
||||||
startupThread.start();
|
startupThread.start();
|
||||||
@@ -263,10 +271,15 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
private class StartControllers implements Runnable {
|
private class StartControllers implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized(TunnelControllerGroup.this) {
|
synchronized(TunnelControllerGroup.this) {
|
||||||
for (int i = 0; i < _controllers.size(); i++) {
|
_controllersLock.readLock().lock();
|
||||||
TunnelController controller = _controllers.get(i);
|
try {
|
||||||
if (controller.getStartOnLoad())
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
controller.startTunnel();
|
TunnelController controller = _controllers.get(i);
|
||||||
|
if (controller.getStartOnLoad())
|
||||||
|
controller.startTunnel();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,8 +302,13 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public synchronized void unloadControllers() {
|
public synchronized void unloadControllers() {
|
||||||
destroyAllControllers();
|
_controllersLock.writeLock().lock();
|
||||||
_controllers.clear();
|
try {
|
||||||
|
destroyAllControllers();
|
||||||
|
_controllers.clear();
|
||||||
|
} finally {
|
||||||
|
_controllersLock.writeLock().unlock();
|
||||||
|
}
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("All controllers stopped and unloaded");
|
_log.info("All controllers stopped and unloaded");
|
||||||
}
|
}
|
||||||
@@ -300,7 +318,14 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
* a config file or start it or anything)
|
* a config file or start it or anything)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public synchronized void addController(TunnelController controller) { _controllers.add(controller); }
|
public synchronized void addController(TunnelController controller) {
|
||||||
|
_controllersLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
_controllers.add(controller);
|
||||||
|
} finally {
|
||||||
|
_controllersLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop and remove the given tunnel
|
* Stop and remove the given tunnel
|
||||||
@@ -311,7 +336,12 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
if (controller == null) return new ArrayList<String>();
|
if (controller == null) return new ArrayList<String>();
|
||||||
controller.stopTunnel();
|
controller.stopTunnel();
|
||||||
List<String> msgs = controller.clearMessages();
|
List<String> msgs = controller.clearMessages();
|
||||||
_controllers.remove(controller);
|
_controllersLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
_controllers.remove(controller);
|
||||||
|
} finally {
|
||||||
|
_controllersLock.writeLock().unlock();
|
||||||
|
}
|
||||||
msgs.add("Tunnel " + controller.getName() + " removed");
|
msgs.add("Tunnel " + controller.getName() + " removed");
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
@@ -323,13 +353,18 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
*/
|
*/
|
||||||
public synchronized List<String> stopAllControllers() {
|
public synchronized List<String> stopAllControllers() {
|
||||||
List<String> msgs = new ArrayList<String>();
|
List<String> msgs = new ArrayList<String>();
|
||||||
for (int i = 0; i < _controllers.size(); i++) {
|
_controllersLock.readLock().lock();
|
||||||
TunnelController controller = _controllers.get(i);
|
try {
|
||||||
controller.stopTunnel();
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
msgs.addAll(controller.clearMessages());
|
TunnelController controller = _controllers.get(i);
|
||||||
|
controller.stopTunnel();
|
||||||
|
msgs.addAll(controller.clearMessages());
|
||||||
|
}
|
||||||
|
if (_log.shouldLog(Log.INFO))
|
||||||
|
_log.info(_controllers.size() + " controllers stopped");
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
if (_log.shouldLog(Log.INFO))
|
|
||||||
_log.info(_controllers.size() + " controllers stopped");
|
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,14 +390,19 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
*/
|
*/
|
||||||
public synchronized List<String> startAllControllers() {
|
public synchronized List<String> startAllControllers() {
|
||||||
List<String> msgs = new ArrayList<String>();
|
List<String> msgs = new ArrayList<String>();
|
||||||
for (int i = 0; i < _controllers.size(); i++) {
|
_controllersLock.readLock().lock();
|
||||||
TunnelController controller = _controllers.get(i);
|
try {
|
||||||
controller.startTunnelBackground();
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
msgs.addAll(controller.clearMessages());
|
TunnelController controller = _controllers.get(i);
|
||||||
}
|
controller.startTunnelBackground();
|
||||||
|
msgs.addAll(controller.clearMessages());
|
||||||
|
}
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info(_controllers.size() + " controllers started");
|
_log.info(_controllers.size() + " controllers started");
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
|
}
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,13 +413,18 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
*/
|
*/
|
||||||
public synchronized List<String> restartAllControllers() {
|
public synchronized List<String> restartAllControllers() {
|
||||||
List<String> msgs = new ArrayList<String>();
|
List<String> msgs = new ArrayList<String>();
|
||||||
for (int i = 0; i < _controllers.size(); i++) {
|
_controllersLock.readLock().lock();
|
||||||
TunnelController controller = _controllers.get(i);
|
try {
|
||||||
controller.restartTunnel();
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
msgs.addAll(controller.clearMessages());
|
TunnelController controller = _controllers.get(i);
|
||||||
|
controller.restartTunnel();
|
||||||
|
msgs.addAll(controller.clearMessages());
|
||||||
|
}
|
||||||
|
if (_log.shouldLog(Log.INFO))
|
||||||
|
_log.info(_controllers.size() + " controllers restarted");
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
if (_log.shouldLog(Log.INFO))
|
|
||||||
_log.info(_controllers.size() + " controllers restarted");
|
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,11 +433,16 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
*
|
*
|
||||||
* @return list of messages the tunnels have generated
|
* @return list of messages the tunnels have generated
|
||||||
*/
|
*/
|
||||||
public synchronized List<String> clearAllMessages() {
|
public List<String> clearAllMessages() {
|
||||||
List<String> msgs = new ArrayList<String>();
|
List<String> msgs = new ArrayList<String>();
|
||||||
for (int i = 0; i < _controllers.size(); i++) {
|
_controllersLock.readLock().lock();
|
||||||
TunnelController controller = _controllers.get(i);
|
try {
|
||||||
msgs.addAll(controller.clearMessages());
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
|
TunnelController controller = _controllers.get(i);
|
||||||
|
msgs.addAll(controller.clearMessages());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
@@ -419,10 +469,15 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
parent.mkdirs();
|
parent.mkdirs();
|
||||||
|
|
||||||
Properties map = new OrderedProperties();
|
Properties map = new OrderedProperties();
|
||||||
for (int i = 0; i < _controllers.size(); i++) {
|
_controllersLock.readLock().lock();
|
||||||
TunnelController controller = _controllers.get(i);
|
try {
|
||||||
Properties cur = controller.getConfig("tunnel." + i + ".");
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
map.putAll(cur);
|
TunnelController controller = _controllers.get(i);
|
||||||
|
Properties cur = controller.getConfig("tunnel." + i + ".");
|
||||||
|
map.putAll(cur);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
DataHelper.storeProps(map, cfgFile);
|
DataHelper.storeProps(map, cfgFile);
|
||||||
@@ -460,8 +515,13 @@ public class TunnelControllerGroup implements ClientApp {
|
|||||||
*
|
*
|
||||||
* @return list of TunnelController objects
|
* @return list of TunnelController objects
|
||||||
*/
|
*/
|
||||||
public synchronized List<TunnelController> getControllers() {
|
public List<TunnelController> getControllers() {
|
||||||
return new ArrayList<TunnelController>(_controllers);
|
_controllersLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
return new ArrayList<TunnelController>(_controllers);
|
||||||
|
} finally {
|
||||||
|
_controllersLock.readLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user