diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/ChatRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/ChatRequestHandler.java index 24bc3cc41..8e8ffb30d 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/ChatRequestHandler.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/ChatRequestHandler.java @@ -7,6 +7,7 @@ import com.gempukku.lotro.async.ResponseWriter; import com.gempukku.lotro.chat.ChatMessage; import com.gempukku.lotro.chat.ChatRoomMediator; import com.gempukku.lotro.chat.ChatServer; +import com.gempukku.lotro.game.ChatCommunicationChannel; import com.gempukku.lotro.game.Player; import com.gempukku.polling.LongPollingResource; import com.gempukku.polling.LongPollingSystem; @@ -66,11 +67,13 @@ public class ChatRequestHandler extends LotroServerRequestHandler implements Uri throw new HttpProcessingException(403); } - ChatUpdateLongPollingResource polledResource = new ChatUpdateLongPollingResource(chatRoom, room, resourceOwner.getName(), responseWriter); - if (polledResource.isChanged()) - polledResource.processIfNotProcessed(); - else - _longPollingSystem.appendLongPollingResource(polledResource); + try { + ChatCommunicationChannel pollableResource = chatRoom.getChatRoomListener(resourceOwner.getName()); + ChatUpdateLongPollingResource polledResource = new ChatUpdateLongPollingResource(chatRoom, room, resourceOwner.getName(), responseWriter); + _longPollingSystem.processLongPollingResource(polledResource, pollableResource); + } catch (SubscriptionExpiredException exp) { + responseWriter.writeError(410); + } } private class ChatUpdateLongPollingResource implements LongPollingResource { @@ -96,6 +99,11 @@ public class ChatRequestHandler extends LotroServerRequestHandler implements Uri } } + @Override + public synchronized boolean wasProcessed() { + return _processed; + } + @Override public synchronized void processIfNotProcessed() { if (!_processed) { diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/GameRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/GameRequestHandler.java index 5a393e43e..6b2056b6e 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/GameRequestHandler.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/GameRequestHandler.java @@ -85,12 +85,17 @@ public class GameRequestHandler extends LotroServerRequestHandler implements Uri if (decisionId != null) gameMediator.playerAnswered(resourceOwner, channelNumber, decisionId, decisionValue); - GameUpdateLongPollingResource pollingResource = new GameUpdateLongPollingResource(channelNumber, gameMediator, resourceOwner, responseWriter); - - if (pollingResource.isChanged()) - pollingResource.processIfNotProcessed(); - else - _longPollingSystem.appendLongPollingResource(pollingResource); + try { + GameCommunicationChannel pollableResource = gameMediator.getCommunicationChannel(resourceOwner, channelNumber); + GameUpdateLongPollingResource pollingResource = new GameUpdateLongPollingResource(channelNumber, gameMediator, resourceOwner, responseWriter); + _longPollingSystem.processLongPollingResource(pollingResource, pollableResource); + } catch (SubscriptionConflictException exp) { + responseWriter.writeError(409); + } catch (PrivateInformationException e) { + responseWriter.writeError(403); + } catch (SubscriptionExpiredException e) { + responseWriter.writeError(410); + } } private class GameUpdateLongPollingResource implements LongPollingResource { @@ -120,6 +125,11 @@ public class GameRequestHandler extends LotroServerRequestHandler implements Uri } } + @Override + public synchronized boolean wasProcessed() { + return _processed; + } + @Override public synchronized void processIfNotProcessed() { if (!_processed) { diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java index 4bdeb6a00..60dcbf0c2 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java @@ -8,10 +8,12 @@ import com.gempukku.lotro.collection.CollectionsManager; import com.gempukku.lotro.db.vo.League; import com.gempukku.lotro.draft.Draft; import com.gempukku.lotro.draft.DraftChannelVisitor; +import com.gempukku.lotro.draft.DraftCommunicationChannel; import com.gempukku.lotro.draft.DraftFinishedException; import com.gempukku.lotro.game.*; import com.gempukku.lotro.game.formats.LotroFormatLibrary; import com.gempukku.lotro.hall.HallChannelVisitor; +import com.gempukku.lotro.hall.HallCommunicationChannel; import com.gempukku.lotro.hall.HallException; import com.gempukku.lotro.hall.HallServer; import com.gempukku.lotro.league.LeagueSerieData; @@ -130,11 +132,17 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri int channelNumber = Integer.parseInt(getFormParameterSafely(postDecoder, "channelNumber")); Player resourceOwner = getResourceOwnerSafely(request, participantId); - DraftUpdateLongPollingResource polledResource = new DraftUpdateLongPollingResource(tournamentId, resourceOwner, channelNumber, responseWriter); - if (polledResource.isChanged()) - polledResource.processIfNotProcessed(); - else - _longPollingSystem.appendLongPollingResource(polledResource); + try { + DraftCommunicationChannel pollableResource = _hallServer.getDraft(tournamentId).getCommunicationChannel(resourceOwner.getName(), channelNumber); + DraftUpdateLongPollingResource polledResource = new DraftUpdateLongPollingResource(tournamentId, resourceOwner, channelNumber, responseWriter); + _longPollingSystem.processLongPollingResource(polledResource, pollableResource); + } catch (DraftFinishedException e) { + responseWriter.writeError(204); + } catch (SubscriptionConflictException e) { + responseWriter.writeError(409); + } catch (SubscriptionExpiredException e) { + responseWriter.writeError(410); + } } 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() { if (!_processed) { try { @@ -174,24 +187,20 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri Element draftElem = doc.createElement("draft"); - try { - Draft draft = _hallServer.getDraft(_tournamentId); - SerializeDraftVisitor serializeDraftVisitor = new SerializeDraftVisitor(doc, draftElem); - draft.getCommunicationChannel(_player.getName(), _channelNumber) - .processCommunicationChannel(draft.getCardChoice(_player.getName()), draft.getChosenCards(_player.getName()), serializeDraftVisitor); + Draft draft = _hallServer.getDraft(_tournamentId); + SerializeDraftVisitor serializeDraftVisitor = new SerializeDraftVisitor(doc, draftElem); + draft.getCommunicationChannel(_player.getName(), _channelNumber) + .processCommunicationChannel(draft.getCardChoice(_player.getName()), draft.getChosenCards(_player.getName()), serializeDraftVisitor); - doc.appendChild(draftElem); + doc.appendChild(draftElem); - _responseWriter.writeXmlResponse(doc); - } catch (DraftFinishedException e) { - throw new HttpProcessingException(204); - } catch (SubscriptionConflictException e) { - throw new HttpProcessingException(409); - } catch (SubscriptionExpiredException e) { - throw new HttpProcessingException(410); - } - } catch (HttpProcessingException exp) { - _responseWriter.writeError(exp.getStatus()); + _responseWriter.writeXmlResponse(doc); + } catch (DraftFinishedException e) { + _responseWriter.writeError(204); + } catch (SubscriptionConflictException e) { + _responseWriter.writeError(409); + } catch (SubscriptionExpiredException e) { + _responseWriter.writeError(410); } catch (Exception exp) { _responseWriter.writeError(500); } @@ -431,11 +440,15 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri Player resourceOwner = getResourceOwnerSafely(request, participantId); processLoginReward(resourceOwner.getName()); - HallUpdateLongPollingResource polledResource = new HallUpdateLongPollingResource(request, resourceOwner, channelNumber, responseWriter); - if (polledResource.isChanged()) - polledResource.processIfNotProcessed(); - else - _longPollingSystem.appendLongPollingResource(polledResource); + try { + HallCommunicationChannel pollableResource = _hallServer.getCommunicationChannel(resourceOwner, channelNumber); + HallUpdateLongPollingResource polledResource = new HallUpdateLongPollingResource(request, resourceOwner, channelNumber, responseWriter); + _longPollingSystem.processLongPollingResource(polledResource, pollableResource); + } catch (SubscriptionExpiredException exp) { + responseWriter.writeError(410); + } catch (SubscriptionConflictException exp) { + responseWriter.writeError(409); + } } private class HallUpdateLongPollingResource implements LongPollingResource { @@ -463,6 +476,11 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri } } + @Override + public synchronized boolean wasProcessed() { + return _processed; + } + @Override public synchronized void processIfNotProcessed() { if (!_processed) { @@ -473,13 +491,7 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri Document doc = documentBuilder.newDocument(); Element hall = doc.createElement("hall"); - try { - _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); - } + _hallServer.getCommunicationChannel(_resourceOwner, _channelNumber).processCommunicationChannel(_hallServer, _resourceOwner, new SerializeHallInfoVisitor(doc, hall)); hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(_resourceOwner, "permanent").getCurrency())); doc.appendChild(hall); @@ -488,8 +500,10 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri processDeliveryServiceNotification(_request, headers); _responseWriter.writeXmlResponse(doc, headers); - } catch (HttpProcessingException exp) { - _responseWriter.writeError(exp.getStatus()); + } catch (SubscriptionExpiredException exp) { + _responseWriter.writeError(410); + } catch (SubscriptionConflictException exp) { + _responseWriter.writeError(409); } catch (Exception exp) { _responseWriter.writeError(500); } diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingResource.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingResource.java index 9d4cd71da..5ac4e8040 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingResource.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingResource.java @@ -3,5 +3,7 @@ package com.gempukku.polling; public interface LongPollingResource { public boolean isChanged(); + public boolean wasProcessed(); + public void processIfNotProcessed(); } diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingSystem.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingSystem.java index ee7ced615..0ac878b20 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingSystem.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/polling/LongPollingSystem.java @@ -2,18 +2,18 @@ package com.gempukku.polling; import org.apache.log4j.Logger; +import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; public class LongPollingSystem { private static Logger _log = Logger.getLogger(LongPollingSystem.class); - private ConcurrentLinkedQueue _waitingActions = new ConcurrentLinkedQueue(); + private ConcurrentLinkedQueue _waitingActions = new ConcurrentLinkedQueue(); private long _pollingInterval = 200; private long _pollingLength = 10000; private ProcessingRunnable _processingRunnable; public LongPollingSystem() { - _waitingActions.add(new PauseResource()); } public void start() { @@ -22,8 +22,13 @@ public class LongPollingSystem { thr.start(); } - public void appendLongPollingResource(LongPollingResource resource) { - _waitingActions.add(new TimeoutLongPollingResource(resource)); + public void processLongPollingResource(LongPollingResource resource, LongPollableResource pollableResource) { + if (resource.isChanged()) + resource.processIfNotProcessed(); + else + pollableResource.registerForChanges(resource); + + _waitingActions.add(new TimeoutResource(resource, pollableResource, System.currentTimeMillis())); } private void pause() { @@ -38,50 +43,46 @@ public class LongPollingSystem { @Override public void run() { while (true) { - LongPollingResource resource = _waitingActions.poll(); - try { - if (resource.isChanged()) - resource.processIfNotProcessed(); - else - _waitingActions.add(resource); - } catch (Exception exp) { - _log.error("Error while processing a long-polled resource", exp); + long now = System.currentTimeMillis(); + Iterator iterator = _waitingActions.iterator(); + while (iterator.hasNext()) { + TimeoutResource resource = iterator.next(); + if (resource.getLongPollingResource().wasProcessed()) + iterator.remove(); + else { + 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 LongPollableResource _longPollableResource; private LongPollingResource _longPollingResource; - private TimeoutLongPollingResource(LongPollingResource longPollingResource) { + private TimeoutResource(LongPollingResource longPollingResource, LongPollableResource longPollableResource, long start) { _longPollingResource = longPollingResource; - _start = System.currentTimeMillis(); + _longPollableResource = longPollableResource; + _start = start; } - @Override - public boolean isChanged() { - boolean timeout = _start + _pollingLength < System.currentTimeMillis(); - return timeout || _longPollingResource.isChanged(); + public LongPollableResource getLongPollableResource() { + return _longPollableResource; } - @Override - public void processIfNotProcessed() { - _longPollingResource.processIfNotProcessed(); - } - } - - private class PauseResource implements LongPollingResource { - @Override - public boolean isChanged() { - return true; + public LongPollingResource getLongPollingResource() { + return _longPollingResource; } - @Override - public void processIfNotProcessed() { - pause(); - _waitingActions.add(this); + public long getStart() { + return _start; } } }