LongPollingSystem now only times out waiting resources.

This commit is contained in:
marcins78
2013-01-18 18:23:45 +00:00
parent f97f44d67d
commit ca24378de4
5 changed files with 114 additions and 79 deletions

View File

@@ -7,6 +7,7 @@ import com.gempukku.lotro.async.ResponseWriter;
import com.gempukku.lotro.chat.ChatMessage; import com.gempukku.lotro.chat.ChatMessage;
import com.gempukku.lotro.chat.ChatRoomMediator; import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer; import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.game.ChatCommunicationChannel;
import com.gempukku.lotro.game.Player; import com.gempukku.lotro.game.Player;
import com.gempukku.polling.LongPollingResource; import com.gempukku.polling.LongPollingResource;
import com.gempukku.polling.LongPollingSystem; import com.gempukku.polling.LongPollingSystem;
@@ -66,11 +67,13 @@ public class ChatRequestHandler extends LotroServerRequestHandler implements Uri
throw new HttpProcessingException(403); throw new HttpProcessingException(403);
} }
ChatUpdateLongPollingResource polledResource = new ChatUpdateLongPollingResource(chatRoom, room, resourceOwner.getName(), responseWriter); try {
if (polledResource.isChanged()) ChatCommunicationChannel pollableResource = chatRoom.getChatRoomListener(resourceOwner.getName());
polledResource.processIfNotProcessed(); ChatUpdateLongPollingResource polledResource = new ChatUpdateLongPollingResource(chatRoom, room, resourceOwner.getName(), responseWriter);
else _longPollingSystem.processLongPollingResource(polledResource, pollableResource);
_longPollingSystem.appendLongPollingResource(polledResource); } catch (SubscriptionExpiredException exp) {
responseWriter.writeError(410);
}
} }
private class ChatUpdateLongPollingResource implements LongPollingResource { private class ChatUpdateLongPollingResource implements LongPollingResource {
@@ -96,6 +99,11 @@ public class ChatRequestHandler extends LotroServerRequestHandler implements Uri
} }
} }
@Override
public synchronized boolean wasProcessed() {
return _processed;
}
@Override @Override
public synchronized void processIfNotProcessed() { public synchronized void processIfNotProcessed() {
if (!_processed) { if (!_processed) {

View File

@@ -85,12 +85,17 @@ public class GameRequestHandler extends LotroServerRequestHandler implements Uri
if (decisionId != null) if (decisionId != null)
gameMediator.playerAnswered(resourceOwner, channelNumber, decisionId, decisionValue); gameMediator.playerAnswered(resourceOwner, channelNumber, decisionId, decisionValue);
GameUpdateLongPollingResource pollingResource = new GameUpdateLongPollingResource(channelNumber, gameMediator, resourceOwner, responseWriter); try {
GameCommunicationChannel pollableResource = gameMediator.getCommunicationChannel(resourceOwner, channelNumber);
if (pollingResource.isChanged()) GameUpdateLongPollingResource pollingResource = new GameUpdateLongPollingResource(channelNumber, gameMediator, resourceOwner, responseWriter);
pollingResource.processIfNotProcessed(); _longPollingSystem.processLongPollingResource(pollingResource, pollableResource);
else } catch (SubscriptionConflictException exp) {
_longPollingSystem.appendLongPollingResource(pollingResource); responseWriter.writeError(409);
} catch (PrivateInformationException e) {
responseWriter.writeError(403);
} catch (SubscriptionExpiredException e) {
responseWriter.writeError(410);
}
} }
private class GameUpdateLongPollingResource implements LongPollingResource { private class GameUpdateLongPollingResource implements LongPollingResource {
@@ -120,6 +125,11 @@ public class GameRequestHandler extends LotroServerRequestHandler implements Uri
} }
} }
@Override
public synchronized boolean wasProcessed() {
return _processed;
}
@Override @Override
public synchronized void processIfNotProcessed() { public synchronized void processIfNotProcessed() {
if (!_processed) { if (!_processed) {

View File

@@ -8,10 +8,12 @@ import com.gempukku.lotro.collection.CollectionsManager;
import com.gempukku.lotro.db.vo.League; import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.draft.Draft; import com.gempukku.lotro.draft.Draft;
import com.gempukku.lotro.draft.DraftChannelVisitor; import com.gempukku.lotro.draft.DraftChannelVisitor;
import com.gempukku.lotro.draft.DraftCommunicationChannel;
import com.gempukku.lotro.draft.DraftFinishedException; import com.gempukku.lotro.draft.DraftFinishedException;
import com.gempukku.lotro.game.*; import com.gempukku.lotro.game.*;
import com.gempukku.lotro.game.formats.LotroFormatLibrary; import com.gempukku.lotro.game.formats.LotroFormatLibrary;
import com.gempukku.lotro.hall.HallChannelVisitor; import com.gempukku.lotro.hall.HallChannelVisitor;
import com.gempukku.lotro.hall.HallCommunicationChannel;
import com.gempukku.lotro.hall.HallException; import com.gempukku.lotro.hall.HallException;
import com.gempukku.lotro.hall.HallServer; import com.gempukku.lotro.hall.HallServer;
import com.gempukku.lotro.league.LeagueSerieData; import com.gempukku.lotro.league.LeagueSerieData;
@@ -130,11 +132,17 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
int channelNumber = Integer.parseInt(getFormParameterSafely(postDecoder, "channelNumber")); int channelNumber = Integer.parseInt(getFormParameterSafely(postDecoder, "channelNumber"));
Player resourceOwner = getResourceOwnerSafely(request, participantId); Player resourceOwner = getResourceOwnerSafely(request, participantId);
DraftUpdateLongPollingResource polledResource = new DraftUpdateLongPollingResource(tournamentId, resourceOwner, channelNumber, responseWriter); try {
if (polledResource.isChanged()) DraftCommunicationChannel pollableResource = _hallServer.getDraft(tournamentId).getCommunicationChannel(resourceOwner.getName(), channelNumber);
polledResource.processIfNotProcessed(); DraftUpdateLongPollingResource polledResource = new DraftUpdateLongPollingResource(tournamentId, resourceOwner, channelNumber, responseWriter);
else _longPollingSystem.processLongPollingResource(polledResource, pollableResource);
_longPollingSystem.appendLongPollingResource(polledResource); } catch (DraftFinishedException e) {
responseWriter.writeError(204);
} catch (SubscriptionConflictException e) {
responseWriter.writeError(409);
} catch (SubscriptionExpiredException e) {
responseWriter.writeError(410);
}
} }
private class DraftUpdateLongPollingResource implements LongPollingResource { private class DraftUpdateLongPollingResource implements LongPollingResource {
@@ -164,6 +172,11 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
} }
} }
@Override
public synchronized boolean wasProcessed() {
return _processed;
}
public synchronized void processIfNotProcessed() { public synchronized void processIfNotProcessed() {
if (!_processed) { if (!_processed) {
try { try {
@@ -174,24 +187,20 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
Element draftElem = doc.createElement("draft"); Element draftElem = doc.createElement("draft");
try { Draft draft = _hallServer.getDraft(_tournamentId);
Draft draft = _hallServer.getDraft(_tournamentId); SerializeDraftVisitor serializeDraftVisitor = new SerializeDraftVisitor(doc, draftElem);
SerializeDraftVisitor serializeDraftVisitor = new SerializeDraftVisitor(doc, draftElem); draft.getCommunicationChannel(_player.getName(), _channelNumber)
draft.getCommunicationChannel(_player.getName(), _channelNumber) .processCommunicationChannel(draft.getCardChoice(_player.getName()), draft.getChosenCards(_player.getName()), serializeDraftVisitor);
.processCommunicationChannel(draft.getCardChoice(_player.getName()), draft.getChosenCards(_player.getName()), serializeDraftVisitor);
doc.appendChild(draftElem); doc.appendChild(draftElem);
_responseWriter.writeXmlResponse(doc); _responseWriter.writeXmlResponse(doc);
} catch (DraftFinishedException e) { } catch (DraftFinishedException e) {
throw new HttpProcessingException(204); _responseWriter.writeError(204);
} catch (SubscriptionConflictException e) { } catch (SubscriptionConflictException e) {
throw new HttpProcessingException(409); _responseWriter.writeError(409);
} catch (SubscriptionExpiredException e) { } catch (SubscriptionExpiredException e) {
throw new HttpProcessingException(410); _responseWriter.writeError(410);
}
} catch (HttpProcessingException exp) {
_responseWriter.writeError(exp.getStatus());
} catch (Exception exp) { } catch (Exception exp) {
_responseWriter.writeError(500); _responseWriter.writeError(500);
} }
@@ -431,11 +440,15 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
Player resourceOwner = getResourceOwnerSafely(request, participantId); Player resourceOwner = getResourceOwnerSafely(request, participantId);
processLoginReward(resourceOwner.getName()); processLoginReward(resourceOwner.getName());
HallUpdateLongPollingResource polledResource = new HallUpdateLongPollingResource(request, resourceOwner, channelNumber, responseWriter); try {
if (polledResource.isChanged()) HallCommunicationChannel pollableResource = _hallServer.getCommunicationChannel(resourceOwner, channelNumber);
polledResource.processIfNotProcessed(); HallUpdateLongPollingResource polledResource = new HallUpdateLongPollingResource(request, resourceOwner, channelNumber, responseWriter);
else _longPollingSystem.processLongPollingResource(polledResource, pollableResource);
_longPollingSystem.appendLongPollingResource(polledResource); } catch (SubscriptionExpiredException exp) {
responseWriter.writeError(410);
} catch (SubscriptionConflictException exp) {
responseWriter.writeError(409);
}
} }
private class HallUpdateLongPollingResource implements LongPollingResource { private class HallUpdateLongPollingResource implements LongPollingResource {
@@ -463,6 +476,11 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
} }
} }
@Override
public synchronized boolean wasProcessed() {
return _processed;
}
@Override @Override
public synchronized void processIfNotProcessed() { public synchronized void processIfNotProcessed() {
if (!_processed) { if (!_processed) {
@@ -473,13 +491,7 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
Document doc = documentBuilder.newDocument(); Document doc = documentBuilder.newDocument();
Element hall = doc.createElement("hall"); Element hall = doc.createElement("hall");
try { _hallServer.getCommunicationChannel(_resourceOwner, _channelNumber).processCommunicationChannel(_hallServer, _resourceOwner, new SerializeHallInfoVisitor(doc, hall));
_hallServer.getCommunicationChannel(_resourceOwner, _channelNumber).processCommunicationChannel(_hallServer, _resourceOwner, new SerializeHallInfoVisitor(doc, hall));
} catch (SubscriptionExpiredException exp) {
throw new HttpProcessingException(410);
} catch (SubscriptionConflictException exp) {
throw new HttpProcessingException(409);
}
hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(_resourceOwner, "permanent").getCurrency())); hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(_resourceOwner, "permanent").getCurrency()));
doc.appendChild(hall); doc.appendChild(hall);
@@ -488,8 +500,10 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
processDeliveryServiceNotification(_request, headers); processDeliveryServiceNotification(_request, headers);
_responseWriter.writeXmlResponse(doc, headers); _responseWriter.writeXmlResponse(doc, headers);
} catch (HttpProcessingException exp) { } catch (SubscriptionExpiredException exp) {
_responseWriter.writeError(exp.getStatus()); _responseWriter.writeError(410);
} catch (SubscriptionConflictException exp) {
_responseWriter.writeError(409);
} catch (Exception exp) { } catch (Exception exp) {
_responseWriter.writeError(500); _responseWriter.writeError(500);
} }

View File

@@ -3,5 +3,7 @@ package com.gempukku.polling;
public interface LongPollingResource { public interface LongPollingResource {
public boolean isChanged(); public boolean isChanged();
public boolean wasProcessed();
public void processIfNotProcessed(); public void processIfNotProcessed();
} }

View File

@@ -2,18 +2,18 @@ package com.gempukku.polling;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class LongPollingSystem { public class LongPollingSystem {
private static Logger _log = Logger.getLogger(LongPollingSystem.class); private static Logger _log = Logger.getLogger(LongPollingSystem.class);
private ConcurrentLinkedQueue<LongPollingResource> _waitingActions = new ConcurrentLinkedQueue<LongPollingResource>(); private ConcurrentLinkedQueue<TimeoutResource> _waitingActions = new ConcurrentLinkedQueue<TimeoutResource>();
private long _pollingInterval = 200; private long _pollingInterval = 200;
private long _pollingLength = 10000; private long _pollingLength = 10000;
private ProcessingRunnable _processingRunnable; private ProcessingRunnable _processingRunnable;
public LongPollingSystem() { public LongPollingSystem() {
_waitingActions.add(new PauseResource());
} }
public void start() { public void start() {
@@ -22,8 +22,13 @@ public class LongPollingSystem {
thr.start(); thr.start();
} }
public void appendLongPollingResource(LongPollingResource resource) { public void processLongPollingResource(LongPollingResource resource, LongPollableResource pollableResource) {
_waitingActions.add(new TimeoutLongPollingResource(resource)); if (resource.isChanged())
resource.processIfNotProcessed();
else
pollableResource.registerForChanges(resource);
_waitingActions.add(new TimeoutResource(resource, pollableResource, System.currentTimeMillis()));
} }
private void pause() { private void pause() {
@@ -38,50 +43,46 @@ public class LongPollingSystem {
@Override @Override
public void run() { public void run() {
while (true) { while (true) {
LongPollingResource resource = _waitingActions.poll(); long now = System.currentTimeMillis();
try { Iterator<TimeoutResource> iterator = _waitingActions.iterator();
if (resource.isChanged()) while (iterator.hasNext()) {
resource.processIfNotProcessed(); TimeoutResource resource = iterator.next();
else if (resource.getLongPollingResource().wasProcessed())
_waitingActions.add(resource); iterator.remove();
} catch (Exception exp) { else {
_log.error("Error while processing a long-polled resource", exp); if (resource.getStart() + _pollingLength < now) {
resource.getLongPollableResource().deregisterResource(resource.getLongPollingResource());
resource.getLongPollingResource().processIfNotProcessed();
iterator.remove();
}
}
} }
pause();
} }
} }
} }
private class TimeoutLongPollingResource implements LongPollingResource { private class TimeoutResource {
private long _start; private long _start;
private LongPollableResource _longPollableResource;
private LongPollingResource _longPollingResource; private LongPollingResource _longPollingResource;
private TimeoutLongPollingResource(LongPollingResource longPollingResource) { private TimeoutResource(LongPollingResource longPollingResource, LongPollableResource longPollableResource, long start) {
_longPollingResource = longPollingResource; _longPollingResource = longPollingResource;
_start = System.currentTimeMillis(); _longPollableResource = longPollableResource;
_start = start;
} }
@Override public LongPollableResource getLongPollableResource() {
public boolean isChanged() { return _longPollableResource;
boolean timeout = _start + _pollingLength < System.currentTimeMillis();
return timeout || _longPollingResource.isChanged();
} }
@Override public LongPollingResource getLongPollingResource() {
public void processIfNotProcessed() { return _longPollingResource;
_longPollingResource.processIfNotProcessed();
}
}
private class PauseResource implements LongPollingResource {
@Override
public boolean isChanged() {
return true;
} }
@Override public long getStart() {
public void processIfNotProcessed() { return _start;
pause();
_waitingActions.add(this);
} }
} }
} }