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.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) {

View File

@@ -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) {

View File

@@ -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);
}

View File

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

View File

@@ -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<LongPollingResource> _waitingActions = new ConcurrentLinkedQueue<LongPollingResource>();
private ConcurrentLinkedQueue<TimeoutResource> _waitingActions = new ConcurrentLinkedQueue<TimeoutResource>();
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<TimeoutResource> 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;
}
}
}