context: New ClientAppManagerImpl in AppContext, so registration

works there (for i2psnark-rpc in standalone)
This commit is contained in:
zzz
2017-03-21 19:26:48 +00:00
parent a00f11d5b7
commit ca6ce37a0b
3 changed files with 80 additions and 30 deletions

View File

@ -8,6 +8,7 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import net.i2p.app.ClientAppManager; import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppManagerImpl;
import net.i2p.client.naming.NamingService; import net.i2p.client.naming.NamingService;
import net.i2p.crypto.AESEngine; import net.i2p.crypto.AESEngine;
import net.i2p.crypto.CryptixAESEngine; import net.i2p.crypto.CryptixAESEngine;
@ -116,6 +117,7 @@ public class I2PAppContext {
private final File _appDir; private final File _appDir;
private volatile File _tmpDir; private volatile File _tmpDir;
private final Random _tmpDirRand = new Random(); private final Random _tmpDirRand = new Random();
private final ClientAppManager _appManager;
// split up big lock on this to avoid deadlocks // split up big lock on this to avoid deadlocks
private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(), _lock4 = new Object(), private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(), _lock4 = new Object(),
_lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(), _lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(),
@ -198,6 +200,7 @@ public class I2PAppContext {
_overrideProps.putAll(envProps); _overrideProps.putAll(envProps);
_shutdownTasks = new ConcurrentHashSet<Runnable>(32); _shutdownTasks = new ConcurrentHashSet<Runnable>(32);
_portMapper = new PortMapper(this); _portMapper = new PortMapper(this);
_appManager = isRouterContext() ? null : new ClientAppManagerImpl(this);
/* /*
* Directories. These are all set at instantiation and will not be changed by * Directories. These are all set at instantiation and will not be changed by
@ -1007,8 +1010,11 @@ public class I2PAppContext {
} }
/** /**
* The RouterAppManager in RouterContext, null always in I2PAppContext * As of 0.9.30, returns non-null in I2PAppContext, null in RouterContext.
* @return null always * Prior to that, returned null always.
* Overridden in RouterContext to return the RouterAppManager.
*
* @return As of 0.9.30, returns non-null in I2PAppContext, null in RouterContext
* @since 0.9.11, in RouterContext since 0.9.4 * @since 0.9.11, in RouterContext since 0.9.4
*/ */
public ClientAppManager clientAppManager() { public ClientAppManager clientAppManager() {

View File

@ -0,0 +1,67 @@
package net.i2p.app;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.I2PAppContext;
/**
* A simple ClientAppManager that supports register/unregister only,
* so that client apps may find each other in AppContext.
* See RouterAppManager for the real thing in RouterContext.
*
* @since 0.9.30
*/
public class ClientAppManagerImpl implements ClientAppManager {
// registered name to client
protected final ConcurrentHashMap<String, ClientApp> _registered;
public ClientAppManagerImpl(I2PAppContext ctx) {
_registered = new ConcurrentHashMap<String, ClientApp>(8);
}
/**
* Does nothing.
*
* @param app non-null
* @param state non-null
* @param message may be null
* @param e may be null
*/
public void notify(ClientApp app, ClientAppState state, String message, Exception e) {}
/**
* Register with the manager under the given name,
* so that other clients may find it.
* Only required for apps used by other apps.
*
* @param app non-null
* @return true if successful, false if duplicate name
*/
public boolean register(ClientApp app) {
return _registered.putIfAbsent(app.getName(), app) == null;
}
/**
* Unregister with the manager. Name must be the same as that from register().
* Only required for apps used by other apps.
*
* @param app non-null
*/
public void unregister(ClientApp app) {
_registered.remove(app.getName(), app);
}
/**
* Get a registered app.
* Only used for apps finding other apps.
* Do not hold a static reference.
* If you only need to find a port, use the PortMapper instead.
*
* @param name non-null
* @return client app or null
*/
public ClientApp getRegisteredApp(String name) {
return _registered.get(name);
}
}

View File

@ -22,21 +22,19 @@ import net.i2p.util.Log;
* *
* @since 0.9.4 * @since 0.9.4
*/ */
public class RouterAppManager implements ClientAppManager { public class RouterAppManager extends ClientAppManagerImpl {
private final RouterContext _context; private final RouterContext _context;
private final Log _log; private final Log _log;
// client to args // client to args
// this assumes clients do not override equals() // this assumes clients do not override equals()
private final ConcurrentHashMap<ClientApp, String[]> _clients; private final ConcurrentHashMap<ClientApp, String[]> _clients;
// registered name to client
private final ConcurrentHashMap<String, ClientApp> _registered;
public RouterAppManager(RouterContext ctx) { public RouterAppManager(RouterContext ctx) {
super(ctx);
_context = ctx; _context = ctx;
_log = ctx.logManager().getLog(RouterAppManager.class); _log = ctx.logManager().getLog(RouterAppManager.class);
_clients = new ConcurrentHashMap<ClientApp, String[]>(16); _clients = new ConcurrentHashMap<ClientApp, String[]>(16);
_registered = new ConcurrentHashMap<String, ClientApp>(8);
ctx.addShutdownTask(new Shutdown()); ctx.addShutdownTask(new Shutdown());
} }
@ -91,6 +89,7 @@ public class RouterAppManager implements ClientAppManager {
* @param message may be null * @param message may be null
* @param e may be null * @param e may be null
*/ */
@Override
public void notify(ClientApp app, ClientAppState state, String message, Exception e) { public void notify(ClientApp app, ClientAppState state, String message, Exception e) {
switch(state) { switch(state) {
case UNINITIALIZED: case UNINITIALIZED:
@ -137,6 +136,7 @@ public class RouterAppManager implements ClientAppManager {
* @param app non-null * @param app non-null
* @return true if successful, false if duplicate name * @return true if successful, false if duplicate name
*/ */
@Override
public boolean register(ClientApp app) { public boolean register(ClientApp app) {
if (!_clients.containsKey(app)) { if (!_clients.containsKey(app)) {
// Allow registration even if we didn't start it, // Allow registration even if we didn't start it,
@ -148,32 +148,9 @@ public class RouterAppManager implements ClientAppManager {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Client " + app.getDisplayName() + " REGISTERED AS " + app.getName()); _log.info("Client " + app.getDisplayName() + " REGISTERED AS " + app.getName());
// TODO if old app in there is not running and != this app, allow replacement // TODO if old app in there is not running and != this app, allow replacement
return _registered.putIfAbsent(app.getName(), app) == null; return super.register(app);
} }
/**
* Unregister with the manager. Name must be the same as that from register().
* Only required for apps used by other apps.
*
* @param app non-null
*/
public void unregister(ClientApp app) {
_registered.remove(app.getName(), app);
}
/**
* Get a registered app.
* Only used for apps finding other apps.
* Do not hold a static reference.
* If you only need to find a port, use the PortMapper instead.
*
* @param name non-null
* @return client app or null
*/
public ClientApp getRegisteredApp(String name) {
return _registered.get(name);
}
/// end ClientAppManager interface /// end ClientAppManager interface
/** /**