From ade836c08a83f3ac53410e790d6cecaf00aaf6fe Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Sat, 25 Jun 2011 14:34:39 -0400 Subject: [PATCH] added connection leasing + cleanup --- Mage.Common/src/mage/remote/Session.java | 53 +++++++-------- .../main/java/mage/server/MageServerImpl.java | 65 +++++++++---------- .../src/main/java/mage/server/Main.java | 30 ++++++++- .../src/main/java/mage/server/Session.java | 3 +- .../main/java/mage/server/SessionManager.java | 8 ++- .../java/mage/server/TableController.java | 5 ++ .../main/java/mage/server/TableManager.java | 4 +- .../mage/server/draft/DraftController.java | 2 +- .../java/mage/server/game/GameController.java | 2 +- .../tournament/TournamentController.java | 2 +- .../java/mage/server/util/ThreadExecutor.java | 14 ++-- pom.xml | 11 ++-- 12 files changed, 115 insertions(+), 84 deletions(-) diff --git a/Mage.Common/src/mage/remote/Session.java b/Mage.Common/src/mage/remote/Session.java index 9c379c6e42..dbafa22ede 100644 --- a/Mage.Common/src/mage/remote/Session.java +++ b/Mage.Common/src/mage/remote/Session.java @@ -104,44 +104,45 @@ public class Session { public boolean connect() { sessionState = SessionState.CONNECTING; try { -// System.setProperty("http.nonProxyHosts", "code.google.com"); -// System.setProperty("socksNonProxyHosts", "code.google.com"); -// -// // clear previous values -// System.clearProperty("socksProxyHost"); -// System.clearProperty("socksProxyPort"); -// System.clearProperty("http.proxyHost"); -// System.clearProperty("http.proxyPort"); -// -// switch (connection.getProxyType()) { -// case SOCKS: -// System.setProperty("socksProxyHost", connection.getProxyHost()); -// System.setProperty("socksProxyPort", Integer.toString(connection.getProxyPort())); -// break; -// case HTTP: -// System.setProperty("http.proxyHost", connection.getProxyHost()); -// System.setProperty("http.proxyPort", Integer.toString(connection.getProxyPort())); -// Authenticator.setDefault(new MageAuthenticator(connection.getProxyUsername(), connection.getProxyPassword())); -// break; -// } + System.setProperty("http.nonProxyHosts", "code.google.com"); + System.setProperty("socksNonProxyHosts", "code.google.com"); + + // clear previous values + System.clearProperty("socksProxyHost"); + System.clearProperty("socksProxyPort"); + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + + switch (connection.getProxyType()) { + case SOCKS: + System.setProperty("socksProxyHost", connection.getProxyHost()); + System.setProperty("socksProxyPort", Integer.toString(connection.getProxyPort())); + break; + case HTTP: + System.setProperty("http.proxyHost", connection.getProxyHost()); + System.setProperty("http.proxyPort", Integer.toString(connection.getProxyPort())); + Authenticator.setDefault(new MageAuthenticator(connection.getProxyUsername(), connection.getProxyPassword())); + break; + } InvokerLocator clientLocator = new InvokerLocator(connection.getURI()); Map metadata = new HashMap(); metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000"); metadata.put("generalizeSocketException", "true"); server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata); - callbackClient = new Client(clientLocator, "callback"); - callbackClient.connect(); + Map clientMetadata = new HashMap(); + clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000"); + clientMetadata.put("generalizeSocketException", "true"); + clientMetadata.put(Client.ENABLE_LEASE, "true"); + callbackClient = new Client(clientLocator, "callback", clientMetadata); Map listenerMetadata = new HashMap(); listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "5000"); listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "2000"); - callbackClient.addConnectionListener(new ClientConnectionListener(), listenerMetadata); + callbackClient.connect(new ClientConnectionListener(), listenerMetadata); Map callbackMetadata = new HashMap(); callbackMetadata.put(Bisocket.IS_CALLBACK_SERVER, "true"); - callbackMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000"); - callbackMetadata.put("generalizeSocketException", "true"); CallbackHandler callbackHandler = new CallbackHandler(); callbackClient.addListener(callbackHandler, callbackMetadata); @@ -201,7 +202,7 @@ public class Session { class ClientConnectionListener implements ConnectionListener { @Override public void handleConnectionException(Throwable throwable, Client client) { - logger.info("connection to server lost"); + logger.info("connection to server lost - " + throwable.getMessage()); disconnect(true); } } diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 7afe35741e..00487ff501 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -66,7 +66,7 @@ import org.apache.log4j.Logger; public class MageServerImpl implements MageServer { private final static Logger logger = Logger.getLogger("Mage Server"); - private static ExecutorService rmiExecutor = ThreadExecutor.getInstance().getRMIExecutor(); + private static ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor(); private String password; private boolean testMode; @@ -137,7 +137,7 @@ public class MageServerImpl implements MageServer { public void removeTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -243,15 +243,12 @@ public class MageServerImpl implements MageServer { @Override public void deregisterClient(final String sessionId) throws MageException { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { - Session session = SessionManager.getInstance().getSession(sessionId); - if (session != null) { - session.kill(); - logger.info("Client deregistered ..."); - } + SessionManager.getInstance().disconnect(sessionId); + logger.info("Client deregistered ..."); } } ); @@ -265,7 +262,7 @@ public class MageServerImpl implements MageServer { public void startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -284,7 +281,7 @@ public class MageServerImpl implements MageServer { public void startChallenge(final String sessionId, final UUID roomId, final UUID tableId, final UUID challengeId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -303,7 +300,7 @@ public class MageServerImpl implements MageServer { public void startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -332,7 +329,7 @@ public class MageServerImpl implements MageServer { @Override public void sendChatMessage(final UUID chatId, final String userName, final String message) throws MageException { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -349,7 +346,7 @@ public class MageServerImpl implements MageServer { @Override public void joinChat(final UUID chatId, final String sessionId, final String userName) throws MageException { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -366,7 +363,7 @@ public class MageServerImpl implements MageServer { @Override public void leaveChat(final UUID chatId, final String sessionId) throws MageException { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -417,7 +414,7 @@ public class MageServerImpl implements MageServer { public void swapSeats(final String sessionId, final UUID roomId, final UUID tableId, final int seatNum1, final int seatNum2) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -436,7 +433,7 @@ public class MageServerImpl implements MageServer { public void leaveTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -466,7 +463,7 @@ public class MageServerImpl implements MageServer { public void joinGame(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -485,7 +482,7 @@ public class MageServerImpl implements MageServer { public void joinDraft(final UUID draftId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -504,7 +501,7 @@ public class MageServerImpl implements MageServer { public void joinTournament(final UUID tournamentId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -545,7 +542,7 @@ public class MageServerImpl implements MageServer { public void sendPlayerUUID(final UUID gameId, final String sessionId, final UUID data) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -564,7 +561,7 @@ public class MageServerImpl implements MageServer { public void sendPlayerString(final UUID gameId, final String sessionId, final String data) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -583,7 +580,7 @@ public class MageServerImpl implements MageServer { public void sendPlayerBoolean(final UUID gameId, final String sessionId, final Boolean data) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -602,7 +599,7 @@ public class MageServerImpl implements MageServer { public void sendPlayerInteger(final UUID gameId, final String sessionId, final Integer data) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -634,7 +631,7 @@ public class MageServerImpl implements MageServer { public void concedeGame(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -666,7 +663,7 @@ public class MageServerImpl implements MageServer { public void watchGame(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -685,7 +682,7 @@ public class MageServerImpl implements MageServer { public void stopWatching(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -704,7 +701,7 @@ public class MageServerImpl implements MageServer { public void replayGame(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -723,7 +720,7 @@ public class MageServerImpl implements MageServer { public void startReplay(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -742,7 +739,7 @@ public class MageServerImpl implements MageServer { public void stopReplay(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -761,7 +758,7 @@ public class MageServerImpl implements MageServer { public void nextPlay(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -780,7 +777,7 @@ public class MageServerImpl implements MageServer { public void previousPlay(final UUID gameId, final String sessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -816,7 +813,7 @@ public class MageServerImpl implements MageServer { public void cheat(final UUID gameId, final String sessionId, final UUID playerId, final DeckCardLists deckList) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -867,7 +864,7 @@ public class MageServerImpl implements MageServer { public void disconnectUser(final String sessionId, final String userSessionId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { @@ -886,7 +883,7 @@ public class MageServerImpl implements MageServer { public void removeTable(final String sessionId, final UUID tableId) throws MageException { if (SessionManager.getInstance().isValidSession(sessionId)) { try { - rmiExecutor.execute( + callExecutor.execute( new Runnable() { @Override public void run() { diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 31bfcd6cf5..6d94fd4488 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -31,6 +31,7 @@ package mage.server; import mage.server.util.PluginClassLoader; import java.io.File; import java.io.FilenameFilter; +import java.io.IOException; import java.net.InetAddress; import java.util.Map; import javax.management.MBeanServer; @@ -47,6 +48,9 @@ import mage.server.util.config.Plugin; import mage.server.util.config.GamePlugin; import mage.utils.MageVersion; import org.apache.log4j.Logger; +import org.jboss.remoting.Client; +import org.jboss.remoting.ClientDisconnectedException; +import org.jboss.remoting.ConnectionListener; import org.jboss.remoting.InvocationRequest; import org.jboss.remoting.InvokerLocator; import org.jboss.remoting.ServerInvocationHandler; @@ -113,20 +117,40 @@ public class Main { logger.info("Started MAGE server - listening on " + connection.toString()); if (testMode) logger.info("MAGE server running in test mode"); - + } catch (IOException ex) { + logger.fatal("Failed to start server - " + connection.toString(), ex); } catch (Exception ex) { logger.fatal("Failed to start server - " + connection.toString(), ex); } } + static class ClientConnectionListener implements ConnectionListener { + @Override + public void handleConnectionException(Throwable throwable, Client client) { + Session session = SessionManager.getInstance().getSession(client.getSessionId()); + if (session != null) { + String sessionName = session.getUsername() + " at " + session.getHost(); + if (throwable instanceof ClientDisconnectedException) { + logger.info("client disconnected - " + sessionName); + } + else { + logger.info("connection to client lost - " + sessionName); + } + SessionManager.getInstance().disconnect(client.getSessionId()); + } + } + } + static class MageTransporterServer extends TransporterServer { - Connector connector; + protected Connector connector; public MageTransporterServer(InvokerLocator locator, Object target, String subsystem, MageServerInvocationHandler callback) throws Exception { super(locator, target, subsystem); connector.addInvocationHandler("callback", callback); + connector.setLeasePeriod(5000); + connector.addConnectionListener(new ClientConnectionListener()); } public Connector getConnector() throws Exception { @@ -170,7 +194,7 @@ public class Main { public void removeListener(InvokerCallbackHandler callbackHandler) { ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler; String sessionId = handler.getCallbackClient().getSessionId(); - SessionManager.getInstance().removeSession(sessionId); + SessionManager.getInstance().disconnect(sessionId); } } diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 345d1a75e5..b8376dcdc6 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -76,9 +76,8 @@ public class Session { public String getId() { return sessionId; } - + public void kill() { - SessionManager.getInstance().removeSession(sessionId); TableManager.getInstance().removeSession(sessionId); GameManager.getInstance().removeSession(sessionId); ChatManager.getInstance().removeSession(sessionId); diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index fe623d6b72..3219308fb8 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -82,8 +82,12 @@ public class SessionManager { return false; } - public void removeSession(String sessionId) { - sessions.remove(sessionId); + public synchronized void disconnect(String sessionId) { + Session session = sessions.get(sessionId); + if (session != null) { + session.kill(); + sessions.remove(sessionId); + } } public Map getSessions() { diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index b3a824ae3e..93a904b793 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -237,6 +237,11 @@ public class TableController { return player; } + public void kill(String sessionId) { + leaveTable(sessionId); + sessionPlayerMap.remove(sessionId); + } + public synchronized void leaveTable(String sessionId) { if (table.getState() == TableState.WAITING || table.getState() == TableState.STARTING) table.leaveTable(sessionPlayerMap.get(sessionId)); diff --git a/Mage.Server/src/main/java/mage/server/TableManager.java b/Mage.Server/src/main/java/mage/server/TableManager.java index ff476b7e06..5f1d6fab8c 100644 --- a/Mage.Server/src/main/java/mage/server/TableManager.java +++ b/Mage.Server/src/main/java/mage/server/TableManager.java @@ -114,7 +114,9 @@ public class TableManager { } public void removeSession(String sessionId) { - // TODO: search through tables and remove session + for (TableController controller: controllers.values()) { + controller.kill(sessionId); + } } public boolean isTableOwner(UUID tableId, String sessionId) { diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftController.java b/Mage.Server/src/main/java/mage/server/draft/DraftController.java index 9b333fd888..b1061b7871 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftController.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftController.java @@ -142,7 +142,7 @@ public class DraftController { private void checkStart() { if (allJoined()) { - ThreadExecutor.getInstance().getRMIExecutor().execute( + ThreadExecutor.getInstance().getCallExecutor().execute( new Runnable() { @Override public void run() { diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index af282f6f22..183df1e94a 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -209,7 +209,7 @@ public class GameController implements GameCallback { private void checkStart() { if (allJoined()) { - ThreadExecutor.getInstance().getRMIExecutor().execute( + ThreadExecutor.getInstance().getCallExecutor().execute( new Runnable() { @Override public void run() { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index a93d7b7090..ff2d934baa 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -141,7 +141,7 @@ public class TournamentController { private void checkStart() { if (allJoined()) { - ThreadExecutor.getInstance().getRMIExecutor().execute( + ThreadExecutor.getInstance().getCallExecutor().execute( new Runnable() { @Override public void run() { diff --git a/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java b/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java index 318aa379b2..f2844fd5bb 100644 --- a/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java +++ b/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java @@ -36,13 +36,13 @@ import java.util.concurrent.*; */ public class ThreadExecutor { - private static ExecutorService rmiExecutor = Executors.newCachedThreadPool(); - private static ExecutorService gameExecutor = Executors.newFixedThreadPool(ConfigSettings.getInstance().getMaxGameThreads()); - private static ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(5); + private static final ExecutorService callExecutor = Executors.newCachedThreadPool(); + private static final ExecutorService gameExecutor = Executors.newFixedThreadPool(ConfigSettings.getInstance().getMaxGameThreads()); + private static final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(5); static { - ((ThreadPoolExecutor)rmiExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); - ((ThreadPoolExecutor)rmiExecutor).allowCoreThreadTimeOut(true); + ((ThreadPoolExecutor)callExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); + ((ThreadPoolExecutor)callExecutor).allowCoreThreadTimeOut(true); ((ThreadPoolExecutor)gameExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); ((ThreadPoolExecutor)gameExecutor).allowCoreThreadTimeOut(true); ((ThreadPoolExecutor)timeoutExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); @@ -57,8 +57,8 @@ public class ThreadExecutor { private ThreadExecutor() {} - public ExecutorService getRMIExecutor() { - return rmiExecutor; + public ExecutorService getCallExecutor() { + return callExecutor; } public ExecutorService getGameExecutor() { diff --git a/pom.xml b/pom.xml index 8f7b680a7c..d734aabb87 100644 --- a/pom.xml +++ b/pom.xml @@ -31,14 +31,9 @@ Mage.Plugins Mage.Server.Plugins Mage.Server.Console - Mage.Tests - - sonatype-org - https://maven.nuxeo.org/nexus/content/repositories/public/org/ - jboss-public-repository JBoss Repository @@ -65,6 +60,10 @@ never + + sonatype-org + https://maven.nuxeo.org/nexus/content/repositories/public/org/ + mage.googlecode.com https://mage.googlecode.com/hg/repository/ @@ -92,4 +91,4 @@ 0.8.0 - \ No newline at end of file +