From 68933856d86f51648701d383b016afd610482a6c Mon Sep 17 00:00:00 2001 From: marcins78 Date: Tue, 8 Jan 2013 15:28:28 +0000 Subject: [PATCH] Long polling for Hall Server. --- .../lotro/hall/HallCommunicationChannel.java | 107 ++++++++++++++++++ .../com/gempukku/lotro/hall/HallServer.java | 18 +++ .../gempukku/lotro/server/HallResource.java | 11 +- 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallCommunicationChannel.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallCommunicationChannel.java index 6dd6b6808..a4948c151 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallCommunicationChannel.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallCommunicationChannel.java @@ -29,6 +29,113 @@ public class HallCommunicationChannel { return _lastConsumed; } + public synchronized boolean hasChangesInCommunicationChannel(HallServer hallServer, Player player) { + final MutableObject newMotd = new MutableObject(); + + final Map> tournamentQueuesOnServer = new LinkedHashMap>(); + final Map> tablesOnServer = new LinkedHashMap>(); + final Map> tournamentsOnServer = new LinkedHashMap>(); + + hallServer.processHall(player, + new HallInfoVisitor() { + @Override + public void serverTime(String time) { + } + + @Override + public void playerBusy(boolean busy) { + } + + @Override + public void motd(String motd) { + newMotd.setValue(motd); + } + + @Override + public void visitTable(String tableId, String gameId, boolean watchable, TableStatus status, String statusDescription, String formatName, String tournamentName, List playerIds, String winner) { + Map props = new HashMap(); + props.put("gameId", gameId); + props.put("watchable", String.valueOf(watchable)); + props.put("status", String.valueOf(status)); + props.put("statusDescription", statusDescription); + props.put("format", formatName); + props.put("tournament", tournamentName); + props.put("players", StringUtils.join(playerIds, ",")); + if (winner != null) + props.put("winner", winner); + + tablesOnServer.put(tableId, props); + } + + @Override + public void visitTournamentQueue(String tournamentQueueKey, int cost, String collectionName, String formatName, String tournamentQueueName, + String tournamentPrizes, String pairingDescription, String startCondition, int playerCount, boolean playerSignedUp, boolean joinable) { + Map props = new HashMap(); + props.put("cost", String.valueOf(cost)); + props.put("collection", collectionName); + props.put("format", formatName); + props.put("queue", tournamentQueueName); + props.put("playerCount", String.valueOf(playerCount)); + props.put("prizes", tournamentPrizes); + props.put("system", pairingDescription); + props.put("start", startCondition); + props.put("signedUp", String.valueOf(playerSignedUp)); + props.put("joinable", String.valueOf(joinable)); + + tournamentQueuesOnServer.put(tournamentQueueKey, props); + } + + @Override + public void visitTournament(String tournamentKey, String collectionName, String formatName, String tournamentName, String pairingDescription, + String tournamentStage, int round, int playerCount, boolean playerInCompetition) { + Map props = new HashMap(); + props.put("collection", collectionName); + props.put("format", formatName); + props.put("name", tournamentName); + props.put("system", pairingDescription); + props.put("stage", tournamentStage); + props.put("round", String.valueOf(round)); + props.put("playerCount", String.valueOf(playerCount)); + props.put("signedUp", String.valueOf(playerInCompetition)); + + tournamentsOnServer.put(tournamentKey, props); + } + + @Override + public void runningPlayerGame(String gameId) { + } + }); + + if (newMotd.getValue() != null && !newMotd.equals(_lastMotd)) + return true; + + if (_tournamentQueuePropsOnClient.size() != tournamentQueuesOnServer.size()) + return true; + + if (_tournamentPropsOnClient.size() != tournamentsOnServer.size()) + return true; + + if (_tablePropsOnClient.size() != tablesOnServer.size()) + return true; + + for (Map.Entry> tournamentQueuePropsOnClientPair: _tournamentQueuePropsOnClient.entrySet()){ + if (!tournamentQueuePropsOnClientPair.getValue().equals(tournamentQueuesOnServer.get(tournamentQueuePropsOnClientPair.getKey()))) + return true; + } + + for (Map.Entry> tournamentPropsOnClientPair: _tournamentPropsOnClient.entrySet()){ + if (!tournamentPropsOnClientPair.getValue().equals(tournamentQueuesOnServer.get(tournamentPropsOnClientPair.getKey()))) + return true; + } + + for (Map.Entry> tablePropsOnClientPair : _tablePropsOnClient.entrySet()){ + if (!tablePropsOnClientPair.getValue().equals(tablesOnServer.get(tablePropsOnClientPair.getKey()))) + return true; + } + + return false; + } + public synchronized void processCommunicationChannel(HallServer hallServer, Player player, final HallChannelVisitor hallChannelVisitor) { hallChannelVisitor.channelNumber(_channelNumber); final MutableObject newMotd = new MutableObject(); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java index c9238a9a5..2b9b99ffa 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java @@ -288,6 +288,24 @@ public class HallServer extends AbstractServer { } } + public boolean hasChanges(Player player, int channelNumber) throws SubscriptionExpiredException, SubscriptionConflictException { + _hallDataAccessLock.readLock().lock(); + try { + HallCommunicationChannel communicationChannel = _playerChannelCommunication.get(player); + if (communicationChannel != null) { + if (communicationChannel.getChannelNumber() == channelNumber) { + return communicationChannel.hasChangesInCommunicationChannel(this, player); + } else { + throw new SubscriptionConflictException(); + } + } else { + throw new SubscriptionExpiredException(); + } + } finally { + _hallDataAccessLock.readLock().unlock(); + } + } + public void processHall(Player player, int channelNumber, HallChannelVisitor hallChannelVisitor) throws SubscriptionExpiredException, SubscriptionConflictException { _hallDataAccessLock.readLock().lock(); try { diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/HallResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/HallResource.java index 600126762..3e18eba02 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/HallResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/HallResource.java @@ -141,15 +141,24 @@ public class HallResource extends AbstractResource { Document doc = documentBuilder.newDocument(); Element hall = doc.createElement("hall"); - hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(resourceOwner, "permanent").getCurrency())); try { + // Use long polling + long start = System.currentTimeMillis(); + while (System.currentTimeMillis()< start+_longPollingLength && !_hallServer.hasChanges(resourceOwner, channelNumber)) { + try { + Thread.sleep(_longPollingInterval); + } catch (InterruptedException exp) { + + } + } _hallServer.processHall(resourceOwner, channelNumber, new SerializeHallInfoVisitor(doc, hall)); } catch (SubscriptionExpiredException exp) { throw new WebApplicationException(Response.Status.GONE); } catch (SubscriptionConflictException exp) { throw new WebApplicationException(Response.Status.CONFLICT); } + hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(resourceOwner, "permanent").getCurrency())); doc.appendChild(hall);