remove stale users after 10 minutes

This commit is contained in:
BetaSteward 2011-07-06 22:50:01 -04:00
parent b4b02d0f68
commit bf2f4e3078
9 changed files with 135 additions and 33 deletions

View file

@ -70,6 +70,24 @@ public class ChatManager {
chatSessions.get(chatId).broadcast(userName, message, color);
}
/**
*
* use mainly for announcing that a user connection was lost or that a user has reconnected
*
* @param userId
* @param message
* @param color
*/
public void broadcast(UUID userId, String message, MessageColor color) {
User user = UserManager.getInstance().getUser(userId);
if (user != null) {
for (ChatSession chat: chatSessions.values()) {
if (chat.hasUser(userId))
chat.broadcast(user.getName(), message, color);
}
}
}
void removeUser(UUID userId) {
for (ChatSession chat: chatSessions.values()) {
chat.kill(userId);

View file

@ -32,7 +32,6 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import mage.interfaces.callback.ClientCallback;
@ -51,8 +50,6 @@ public class ChatSession {
private UUID chatId;
private DateFormat timeFormatter = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT);
//TODO: use sessionId for chatting - prevents sending without being part of the chat
public ChatSession() {
chatId = UUID.randomUUID();
}
@ -98,4 +95,8 @@ public class ChatSession {
return chatId;
}
public boolean hasUser(UUID userId) {
return clients.containsKey(userId);
}
}

View file

@ -253,7 +253,7 @@ public class MageServerImpl implements MageServer {
new Runnable() {
@Override
public void run() {
SessionManager.getInstance().disconnect(sessionId);
SessionManager.getInstance().disconnect(sessionId, true);
logger.info("Client deregistered ...");
}
}
@ -563,8 +563,8 @@ public class MageServerImpl implements MageServer {
new Runnable() {
@Override
public void run() {
UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
GameManager.getInstance().sendPlayerUUID(gameId, userId, data);
User user = SessionManager.getInstance().getUser(sessionId);
user.sendPlayerUUID(gameId, data);
}
}
);
@ -583,8 +583,8 @@ public class MageServerImpl implements MageServer {
new Runnable() {
@Override
public void run() {
UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
GameManager.getInstance().sendPlayerString(gameId, userId, data);
User user = SessionManager.getInstance().getUser(sessionId);
user.sendPlayerString(gameId, data);
}
}
);
@ -603,8 +603,8 @@ public class MageServerImpl implements MageServer {
new Runnable() {
@Override
public void run() {
UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
GameManager.getInstance().sendPlayerBoolean(gameId, userId, data);
User user = SessionManager.getInstance().getUser(sessionId);
user.sendPlayerBoolean(gameId, data);
}
}
);
@ -623,8 +623,8 @@ public class MageServerImpl implements MageServer {
new Runnable() {
@Override
public void run() {
UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
GameManager.getInstance().sendPlayerInteger(gameId, userId, data);
User user = SessionManager.getInstance().getUser(sessionId);
user.sendPlayerInteger(gameId, data);
}
}
);

View file

@ -138,12 +138,13 @@ public class Main {
else
sessionName = session.getHost();
if (throwable instanceof ClientDisconnectedException) {
SessionManager.getInstance().disconnect(client.getSessionId(), true);
logger.info("client disconnected - " + sessionName);
}
else {
SessionManager.getInstance().disconnect(client.getSessionId(), false);
logger.info("connection to client lost - " + sessionName);
}
SessionManager.getInstance().disconnect(client.getSessionId());
}
}
}
@ -200,9 +201,10 @@ public class Main {
@Override
public void removeListener(InvokerCallbackHandler callbackHandler) {
ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
String sessionId = handler.getCallbackClient().getSessionId();
SessionManager.getInstance().disconnect(sessionId);
logger.fatal("removeListener called");
// ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
// String sessionId = handler.getCallbackClient().getSessionId();
// SessionManager.getInstance().disconnect(sessionId);
}
}

View file

@ -93,20 +93,21 @@ public class Session {
return sessionId;
}
public void kill() {
// TableManager.getInstance().removeSession(sessionId);
// GameManager.getInstance().removeSession(sessionId);
// ChatManager.getInstance().removeSession(sessionId);
public void disconnect() {
UserManager.getInstance().disconnect(userId);
}
public void kill() {
UserManager.getInstance().removeUser(userId);
}
synchronized void fireCallback(final ClientCallback call) {
try {
call.setMessageId(messageId++);
callbackHandler.handleCallbackOneway(new Callback(call));
} catch (HandleCallbackException ex) {
logger.fatal("Session fireCallback error", ex);
kill();
disconnect();
}
}

View file

@ -28,13 +28,11 @@
package mage.server;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import mage.MageException;
import mage.view.UserView;
import org.apache.log4j.Logger;
import org.jboss.remoting.callback.InvokerCallbackHandler;
@ -83,10 +81,13 @@ public class SessionManager {
return false;
}
public synchronized void disconnect(String sessionId) {
public synchronized void disconnect(String sessionId, boolean voluntary) {
Session session = sessions.get(sessionId);
if (session != null) {
session.kill();
if (voluntary)
session.kill();
else
session.disconnect();
sessions.remove(sessionId);
}
}
@ -101,10 +102,7 @@ public class SessionManager {
public void disconnectUser(String sessionId, String userSessionId) {
if (isAdmin(sessionId)) {
Session session = sessions.get(userSessionId);
if (session != null) {
session.kill();
}
disconnect(userSessionId, true);
}
}
@ -122,4 +120,10 @@ public class SessionManager {
return false;
}
public User getUser(String sessionId) {
if (sessions.containsKey(sessionId)) {
return UserManager.getInstance().getUser(sessions.get(sessionId).getUserId());
}
return null;
}
}

View file

@ -53,6 +53,7 @@ public class User {
private String sessionId = "";
private String host;
private Date connectionTime = new Date();
private Date lastActivity = new Date();
private UserState userState;
private Map<UUID, GameSession> gameSessions = new HashMap<UUID, GameSession>();
@ -133,6 +134,30 @@ public class User {
fireCallback(new ClientCallback("replayGame", gameId));
}
public void sendPlayerUUID(final UUID gameId, final UUID data) {
lastActivity = new Date();
GameManager.getInstance().sendPlayerUUID(gameId, userId, data);
}
public void sendPlayerString(final UUID gameId, final String data) {
lastActivity = new Date();
GameManager.getInstance().sendPlayerString(gameId, userId, data);
}
public void sendPlayerBoolean(final UUID gameId, final Boolean data) {
lastActivity = new Date();
GameManager.getInstance().sendPlayerBoolean(gameId, userId, data);
}
public void sendPlayerInteger(final UUID gameId, final Integer data) {
lastActivity = new Date();
GameManager.getInstance().sendPlayerInteger(gameId, userId, data);
}
public boolean isExpired(Date expired) {
return userState == UserState.Disconnected && lastActivity.before(expired);
}
private void reconnect() {
for (Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
gameStarted(entry.getValue().getGameId(), entry.getKey());
@ -148,5 +173,11 @@ public class User {
public void removeGame(UUID playerId) {
gameSessions.remove(playerId);
}
public void kill() {
for (Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
entry.getValue().kill();
}
}
}

View file

@ -27,23 +27,41 @@
*/
package mage.server;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import mage.view.ChatMessage.MessageColor;
/**
*
* manages users - if a user is disconnected and 10 minutes have passed with no
* activity the user is removed
*
* @author BetaSteward_at_googlemail.com
*/
public class UserManager {
protected static ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
private final static UserManager INSTANCE = new UserManager();
public static UserManager getInstance() {
return INSTANCE;
}
private UserManager() {}
private UserManager() {
expireExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
checkExpired();
}
}, 60, 60, TimeUnit.SECONDS);
}
private ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<UUID, User>();
@ -82,6 +100,7 @@ public class UserManager {
public void disconnect(UUID userId) {
if (users.containsKey(userId)) {
users.get(userId).setSessionId("");
ChatManager.getInstance().broadcast(userId, "has lost connection", MessageColor.BLACK);
}
}
@ -91,5 +110,25 @@ public class UserManager {
}
return false;
}
public void removeUser(UUID userId) {
if (users.containsKey(userId)) {
users.get(userId).setSessionId("");
ChatManager.getInstance().broadcast(userId, "has disconnected", MessageColor.BLACK);
users.get(userId).kill();
users.remove(userId);
}
}
private void checkExpired() {
Calendar expired = Calendar.getInstance();
expired.add(Calendar.MINUTE, -10) ;
for (User user: users.values()) {
if (user.isExpired(expired.getTime())) {
user.kill();
users.remove(user.getId());
}
}
}
}

View file

@ -210,11 +210,17 @@ public class GameSession extends GameWatcher {
}
public void removeGame() {
UserManager.getInstance().getUser(userId).removeGame(playerId);
User user = UserManager.getInstance().getUser(userId);
if (user != null)
user.removeGame(playerId);
}
public UUID getGameId() {
return game.getId();
}
public void kill() {
game.quit(playerId);
}
}