From ef9b267b8e8e1800be8e614f1ac5bfb329262b40 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Tue, 17 Jul 2012 09:40:54 +0000 Subject: [PATCH] Fixing multi-threading issues. --- .../gempukku/lotro/chat/ChatRoomMediator.java | 110 ++++++--- .../lotro/collection/CollectionsManager.java | 50 +++- .../java/com/gempukku/lotro/db/DeckDAO.java | 8 +- .../java/com/gempukku/lotro/db/PlayerDAO.java | 12 +- .../lotro/game/DefaultCardCollection.java | 32 +-- .../lotro/game/GatheringChatRoomListener.java | 6 +- .../com/gempukku/lotro/game/LotroServer.java | 221 ++++++++---------- .../com/gempukku/lotro/hall/HallServer.java | 4 - .../gempukku/lotro/league/LeagueService.java | 24 +- .../SingleEliminationRecurringQueue.java | 2 +- .../lotro/server/CollectionResource.java | 5 +- .../gempukku/lotro/server/DeckResource.java | 5 +- .../gempukku/lotro/server/HallResource.java | 2 +- .../gempukku/lotro/server/ServerResource.java | 4 +- .../lotro/server/provider/DaoProvider.java | 3 +- .../lotro/server/provider/ServerProvider.java | 21 +- 16 files changed, 292 insertions(+), 217 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/chat/ChatRoomMediator.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/chat/ChatRoomMediator.java index 5936e1871..3b50d0469 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/chat/ChatRoomMediator.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/chat/ChatRoomMediator.java @@ -5,6 +5,8 @@ import com.gempukku.lotro.game.GatheringChatRoomListener; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import java.util.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class ChatRoomMediator { private ChatRoom _chatRoom = new ChatRoom(); @@ -14,6 +16,8 @@ public class ChatRoomMediator { private int _channelInactivityTimeoutPeriod = 1000 * 10; // 10 seconds private Set _allowedPlayers; + private ReadWriteLock _lock = new ReentrantReadWriteLock(); + public ChatRoomMediator(int secondsTimeoutPeriod) { this(secondsTimeoutPeriod, null); } @@ -23,46 +27,76 @@ public class ChatRoomMediator { _channelInactivityTimeoutPeriod = 1000 * secondsTimeoutPeriod; } - public synchronized List joinUser(String playerId) { - GatheringChatRoomListener value = new GatheringChatRoomListener(); - _listeners.put(playerId, value); - _chatRoom.joinChatRoom(playerId, value); - return value.consumeMessages(); - } - - public synchronized List getPendingMessages(String playerId) { - GatheringChatRoomListener gatheringChatRoomListener = _listeners.get(playerId); - if (gatheringChatRoomListener == null) - throw new WebApplicationException(Response.Status.NOT_FOUND); - return gatheringChatRoomListener.consumeMessages(); - } - - public synchronized void partUser(String playerId) { - _chatRoom.partChatRoom(playerId); - _listeners.remove(playerId); - } - - public synchronized void sendMessage(String playerId, String message, boolean admin) { - if (!admin && _allowedPlayers != null && !_allowedPlayers.contains(playerId)) - throw new WebApplicationException(Response.Status.FORBIDDEN); - - _chatRoom.postMessage(playerId, message); - } - - public synchronized void cleanup() { - long currentTime = System.currentTimeMillis(); - Map copy = new HashMap(_listeners); - for (Map.Entry playerListener : copy.entrySet()) { - String playerId = playerListener.getKey(); - GatheringChatRoomListener listener = playerListener.getValue(); - if (currentTime > listener.getLastConsumed().getTime() + _channelInactivityTimeoutPeriod) { - _chatRoom.partChatRoom(playerId); - _listeners.remove(playerId); - } + public List joinUser(String playerId) { + _lock.writeLock(); + try { + GatheringChatRoomListener value = new GatheringChatRoomListener(); + _listeners.put(playerId, value); + _chatRoom.joinChatRoom(playerId, value); + return value.consumeMessages(); + } finally { + _lock.writeLock().unlock(); } } - public synchronized Collection getUsersInRoom() { - return _chatRoom.getUsersInRoom(); + public List getPendingMessages(String playerId) { + _lock.readLock().lock(); + try { + GatheringChatRoomListener gatheringChatRoomListener = _listeners.get(playerId); + if (gatheringChatRoomListener == null) + throw new WebApplicationException(Response.Status.NOT_FOUND); + return gatheringChatRoomListener.consumeMessages(); + } finally { + _lock.readLock().unlock(); + } + } + + public void partUser(String playerId) { + _lock.writeLock().lock(); + try { + _chatRoom.partChatRoom(playerId); + _listeners.remove(playerId); + } finally { + _lock.writeLock().unlock(); + } + } + + public void sendMessage(String playerId, String message, boolean admin) { + _lock.writeLock().lock(); + try { + if (!admin && _allowedPlayers != null && !_allowedPlayers.contains(playerId)) + throw new WebApplicationException(Response.Status.FORBIDDEN); + + _chatRoom.postMessage(playerId, message); + } finally { + _lock.writeLock().unlock(); + } + } + + public void cleanup() { + _lock.writeLock().lock(); + try { + long currentTime = System.currentTimeMillis(); + Map copy = new HashMap(_listeners); + for (Map.Entry playerListener : copy.entrySet()) { + String playerId = playerListener.getKey(); + GatheringChatRoomListener listener = playerListener.getValue(); + if (currentTime > listener.getLastConsumed().getTime() + _channelInactivityTimeoutPeriod) { + _chatRoom.partChatRoom(playerId); + _listeners.remove(playerId); + } + } + } finally { + _lock.writeLock().unlock(); + } + } + + public Collection getUsersInRoom() { + _lock.readLock().lock(); + try { + return _chatRoom.getUsersInRoom(); + } finally { + _lock.readLock().unlock(); + } } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CollectionsManager.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CollectionsManager.java index bac333340..27d4c3f5a 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CollectionsManager.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CollectionsManager.java @@ -1,5 +1,6 @@ package com.gempukku.lotro.collection; +import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.db.CollectionDAO; import com.gempukku.lotro.db.PlayerDAO; import com.gempukku.lotro.db.vo.CollectionType; @@ -10,6 +11,7 @@ import java.io.IOException; import java.sql.SQLException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.ReentrantReadWriteLock; public class CollectionsManager { @@ -20,10 +22,53 @@ public class CollectionsManager { private CollectionDAO _collectionDAO; private DeliveryService _deliveryService; - public CollectionsManager(PlayerDAO playerDAO, CollectionDAO collectionDAO, DeliveryService deliveryService) { + private CountDownLatch _collectionReadyLatch = new CountDownLatch(1); + private DefaultCardCollection _defaultCollection; + + public CollectionsManager(PlayerDAO playerDAO, CollectionDAO collectionDAO, DeliveryService deliveryService, final LotroCardBlueprintLibrary lotroCardBlueprintLibrary) { _playerDAO = playerDAO; _collectionDAO = collectionDAO; _deliveryService = deliveryService; + + _defaultCollection = new DefaultCardCollection(); + + // Hunters have 1-194 normal cards, 9 "O" cards, and 3 extra to cover the different culture versions of 15_60 + + Thread thr = new Thread() { + public void run() { + final int[] cardCounts = new int[]{129, 365, 122, 122, 365, 128, 128, 365, 122, 52, 122, 266, 203, 203, 15, 207, 6, 157, 149, 40}; + + for (int i = 0; i <= 19; i++) { + System.out.println("Loading set " + i); + for (int j = 1; j <= cardCounts[i]; j++) { + String blueprintId = i + "_" + j; + try { + if (lotroCardBlueprintLibrary.getBaseBlueprintId(blueprintId).equals(blueprintId)) { + LotroCardBlueprint cardBlueprint = lotroCardBlueprintLibrary.getLotroCardBlueprint(blueprintId); + CardType cardType = cardBlueprint.getCardType(); + if (cardType == CardType.SITE || cardType == CardType.THE_ONE_RING) + _defaultCollection.addItem(blueprintId, 1); + else + _defaultCollection.addItem(blueprintId, 4); + } + } catch (IllegalArgumentException exp) { + + } + } + } + _collectionReadyLatch.countDown(); + } + }; + thr.start(); + } + + public CardCollection getDefaultCollection() { + try { + _collectionReadyLatch.await(); + } catch (InterruptedException exp) { + throw new RuntimeException("Error while awaiting loading a default colleciton", exp); + } + return _defaultCollection; } public void clearDBCache() { @@ -36,6 +81,9 @@ public class CollectionsManager { if (collectionType.contains("+")) return createSumCollection(player, collectionType.split("\\+")); + if (collectionType.equals("default")) + return getDefaultCollection(); + Map playerCollections = _collections.get(player.getName()); if (playerCollections != null) { final CardCollection cardCollection = playerCollections.get(collectionType); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DeckDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DeckDAO.java index 0e7fac1e8..d8c1897d8 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DeckDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DeckDAO.java @@ -23,11 +23,11 @@ public class DeckDAO { _library = library; } - public void clearCache() { + public synchronized void clearCache() { _decks.clear(); } - public LotroDeck getDeckForPlayer(Player player, String name) { + public synchronized LotroDeck getDeckForPlayer(Player player, String name) { Map deckMap = getPlayerDecks(player); return deckMap.get(name); } @@ -59,7 +59,7 @@ public class DeckDAO { return deck; } - public Set getPlayerDeckNames(Player player) { + public synchronized Set getPlayerDeckNames(Player player) { return Collections.unmodifiableSet(getPlayerDecks(player).keySet()); } @@ -137,7 +137,7 @@ public class DeckDAO { // } // } - public LotroDeck buildDeckFromContents(String deckName, String contents) { + public synchronized LotroDeck buildDeckFromContents(String deckName, String contents) { if (contents.contains("|")) { return DeckSerialization.buildDeckFromContents(deckName, contents); } else { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java index 31ba62ee5..1fb59a2fe 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java @@ -21,12 +21,12 @@ public class PlayerDAO { _dbAccess = dbAccess; } - public void clearCache() { + public synchronized void clearCache() { _playersByName.clear(); _playersById.clear(); } - public Player getPlayer(int id) { + public synchronized Player getPlayer(int id) { if (_playersById.containsKey(id)) return _playersById.get(id); @@ -40,7 +40,7 @@ public class PlayerDAO { } } - public Player getPlayer(String playerName) { + public synchronized Player getPlayer(String playerName) { if (_playersByName.containsKey(playerName)) return _playersByName.get(playerName); try { @@ -53,7 +53,7 @@ public class PlayerDAO { } } - public Player loginUser(String login, String password) throws SQLException { + public synchronized Player loginUser(String login, String password) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { PreparedStatement statement = conn.prepareStatement("select id, name, type, last_login_reward from player where name=? and password=?"); @@ -84,7 +84,7 @@ public class PlayerDAO { } } - public void setLastReward(Player player, int currentReward) throws SQLException { + public synchronized void setLastReward(Player player, int currentReward) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { PreparedStatement statement = conn.prepareStatement("update player set last_login_reward =? where id=?"); @@ -101,7 +101,7 @@ public class PlayerDAO { } } - public boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException { + public synchronized boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { PreparedStatement statement = conn.prepareStatement("update player set last_login_reward =? where id=? and last_login_reward=?"); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java index 7be0d7352..ebc42e514 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java @@ -17,11 +17,13 @@ public class DefaultCardCollection implements MutableCardCollection { _currency = cardCollection.getCurrency(); } - public void addCurrency(int currency) { + @Override + public synchronized void addCurrency(int currency) { _currency += currency; } - public boolean removeCurrency(int currency) { + @Override + public synchronized boolean removeCurrency(int currency) { if (_currency < currency) return false; _currency -= currency; @@ -29,12 +31,12 @@ public class DefaultCardCollection implements MutableCardCollection { } @Override - public int getCurrency() { + public synchronized int getCurrency() { return _currency; } @Override - public void addItem(String itemId, int toAdd) { + public synchronized void addItem(String itemId, int toAdd) { Item oldCount = _counts.get(itemId); if (oldCount == null) _counts.put(itemId, Item.createItem(itemId, toAdd)); @@ -43,7 +45,7 @@ public class DefaultCardCollection implements MutableCardCollection { } @Override - public boolean removeItem(String itemId, int toRemove) { + public synchronized boolean removeItem(String itemId, int toRemove) { Item oldCount = _counts.get(itemId); if (oldCount == null || oldCount.getCount() < toRemove) return false; @@ -54,14 +56,6 @@ public class DefaultCardCollection implements MutableCardCollection { return true; } - private boolean hasSelection(String packId, String selection, PacksStorage packsStorage) { - for (Item item : packsStorage.openPack(packId)) { - if (item.getBlueprintId().equals(selection)) - return true; - } - return false; - } - @Override public synchronized CardCollection openPack(String packId, String selection, PacksStorage packsStorage) { Item count = _counts.get(packId); @@ -96,15 +90,23 @@ public class DefaultCardCollection implements MutableCardCollection { } @Override - public Map getAll() { + public synchronized Map getAll() { return Collections.unmodifiableMap(_counts); } @Override - public int getItemCount(String blueprintId) { + public synchronized int getItemCount(String blueprintId) { Item count = _counts.get(blueprintId); if (count == null) return 0; return count.getCount(); } + + private boolean hasSelection(String packId, String selection, PacksStorage packsStorage) { + for (Item item : packsStorage.openPack(packId)) { + if (item.getBlueprintId().equals(selection)) + return true; + } + return false; + } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringChatRoomListener.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringChatRoomListener.java index ac2562acf..e3c29ece4 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringChatRoomListener.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringChatRoomListener.java @@ -12,18 +12,18 @@ public class GatheringChatRoomListener implements ChatRoomListener { private Date _lastConsumed = new Date(); @Override - public void messageReceived(ChatMessage message) { + public synchronized void messageReceived(ChatMessage message) { _messages.add(message); } - public List consumeMessages() { + public synchronized List consumeMessages() { List messages = _messages; _messages = new LinkedList(); _lastConsumed = new Date(); return messages; } - public Date getLastConsumed() { + public synchronized Date getLastConsumed() { return _lastConsumed; } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java index 5f86a3a84..119a4b143 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java @@ -2,17 +2,15 @@ package com.gempukku.lotro.game; import com.gempukku.lotro.AbstractServer; import com.gempukku.lotro.chat.ChatServer; -import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.db.DeckDAO; import com.gempukku.lotro.logic.timing.GameResultListener; import com.gempukku.lotro.logic.vo.LotroDeck; import org.apache.log4j.Logger; -import java.io.IOException; -import java.io.InputStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class LotroServer extends AbstractServer { private static final Logger log = Logger.getLogger(LotroServer.class); @@ -29,72 +27,24 @@ public class LotroServer extends AbstractServer { private int _nextGameId = 1; private DeckDAO _deckDao; - private GameHistoryService _gameHistoryService; - - private DefaultCardCollection _defaultCollection; - private CountDownLatch _collectionReadyLatch = new CountDownLatch(1); private ChatServer _chatServer; - private boolean _test; private GameRecorder _gameRecorder; - public LotroServer(DeckDAO deckDao, GameHistoryService gameHistoryService, LotroCardBlueprintLibrary library, ChatServer chatServer, boolean test) { + private ReadWriteLock _lock = new ReentrantReadWriteLock(); + + public LotroServer(DeckDAO deckDao, LotroCardBlueprintLibrary library, ChatServer chatServer, GameRecorder gameRecorder) { _deckDao = deckDao; - _gameHistoryService = gameHistoryService; _lotroCardBlueprintLibrary = library; _chatServer = chatServer; - _test = test; - _defaultCollection = new DefaultCardCollection(); - - // Hunters have 1-194 normal cards, 9 "O" cards, and 3 extra to cover the different culture versions of 15_60 - - Thread thr = new Thread() { - public void run() { - final int[] cardCounts = new int[]{129, 365, 122, 122, 365, 128, 128, 365, 122, 52, 122, 266, 203, 203, 15, 207, 6, 157, 149, 40}; - - for (int i = 0; i <= 19; i++) { - System.out.println("Loading set " + i); - for (int j = 1; j <= cardCounts[i]; j++) { - String blueprintId = i + "_" + j; - try { - if (_lotroCardBlueprintLibrary.getBaseBlueprintId(blueprintId).equals(blueprintId)) { - LotroCardBlueprint cardBlueprint = _lotroCardBlueprintLibrary.getLotroCardBlueprint(blueprintId); - CardType cardType = cardBlueprint.getCardType(); - if (cardType == CardType.SITE || cardType == CardType.THE_ONE_RING) - _defaultCollection.addItem(blueprintId, 1); - else - _defaultCollection.addItem(blueprintId, 4); - } - } catch (IllegalArgumentException exp) { - - } - } - } - _collectionReadyLatch.countDown(); - } - }; - thr.start(); - - _gameRecorder = new GameRecorder(_gameHistoryService); - } - - public InputStream getGameRecording(String playerId, String gameId) throws IOException { - return _gameRecorder.getRecordedGame(playerId, gameId); - } - - public CardCollection getDefaultCollection() { - try { - _collectionReadyLatch.await(); - } catch (InterruptedException exp) { - throw new RuntimeException("Error while awaiting loading a default colleciton", exp); - } - return _defaultCollection; + _gameRecorder = gameRecorder; } protected void cleanup() { - long currentTime = System.currentTimeMillis(); + _lock.writeLock().lock(); + try { + long currentTime = System.currentTimeMillis(); - synchronized (_finishedGamesTime) { LinkedHashMap copy = new LinkedHashMap(_finishedGamesTime); for (Map.Entry finishedGame : copy.entrySet()) { String gameId = finishedGame.getKey(); @@ -112,81 +62,103 @@ public class LotroServer extends AbstractServer { break; } } - } - for (LotroGameMediator lotroGameMediator : _runningGames.values()) - lotroGameMediator.cleanup(); + for (LotroGameMediator lotroGameMediator : _runningGames.values()) + lotroGameMediator.cleanup(); + } finally { + _lock.writeLock().unlock(); + } } private String getChatRoomName(String gameId) { return "Game" + gameId; } - public synchronized String createNewGame(LotroFormat lotroFormat, String tournamentName, final LotroGameParticipant[] participants, boolean allowSpectators, boolean allowCancelling, boolean muteSpectators, boolean competitiveTime - ) { - if (participants.length < 2) - throw new IllegalArgumentException("There has to be at least two players"); - final String gameId = String.valueOf(_nextGameId); + public String createNewGame(LotroFormat lotroFormat, String tournamentName, final LotroGameParticipant[] participants, boolean allowSpectators, boolean allowCancelling, boolean muteSpectators, boolean competitiveTime) { + _lock.writeLock().lock(); + try { + if (participants.length < 2) + throw new IllegalArgumentException("There has to be at least two players"); + final String gameId = String.valueOf(_nextGameId); - if (muteSpectators) { - Set allowedUsers = new HashSet(); - for (LotroGameParticipant participant : participants) - allowedUsers.add(participant.getPlayerId()); - _chatServer.createVoicedChatRoom(getChatRoomName(gameId), allowedUsers, 30); - } else - _chatServer.createChatRoom(getChatRoomName(gameId), 30); + if (muteSpectators) { + Set allowedUsers = new HashSet(); + for (LotroGameParticipant participant : participants) + allowedUsers.add(participant.getPlayerId()); + _chatServer.createVoicedChatRoom(getChatRoomName(gameId), allowedUsers, 30); + } else + _chatServer.createChatRoom(getChatRoomName(gameId), 30); - LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary, - competitiveTime ? 60 * 40 : 60 * 80, !allowSpectators, allowCancelling); - lotroGameMediator.addGameResultListener( - new GameResultListener() { - @Override - public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { - synchronized (_finishedGamesTime) { - _finishedGamesTime.put(gameId, new Date()); + LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary, + competitiveTime ? 60 * 40 : 60 * 80, !allowSpectators, allowCancelling); + lotroGameMediator.addGameResultListener( + new GameResultListener() { + @Override + public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { + _lock.writeLock().lock(); + try { + _finishedGamesTime.put(gameId, new Date()); + } finally { + _lock.writeLock().unlock(); + } + } + + @Override + public void gameCancelled() { + _lock.writeLock().lock(); + try { + _finishedGamesTime.put(gameId, new Date()); + } finally { + _lock.writeLock().unlock(); + } + } + }); + lotroGameMediator.sendMessageToPlayers("You're starting a game of " + lotroFormat.getName()); + + StringBuffer players = new StringBuffer(); + Map deckNames = new HashMap(); + for (LotroGameParticipant participant : participants) { + deckNames.put(participant.getPlayerId(), participant.getDeck().getDeckName()); + if (players.length() > 0) + players.append(", "); + players.append(participant.getPlayerId()); + } + + lotroGameMediator.sendMessageToPlayers("Players in the game are: " + players.toString()); + + final GameRecorder.GameRecordingInProgress gameRecordingInProgress = _gameRecorder.recordGame(lotroGameMediator, lotroFormat.getName(), tournamentName, deckNames); + lotroGameMediator.addGameResultListener( + new GameResultListener() { + @Override + public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { + _lock.writeLock().lock(); + try { + final Map.Entry loserEntry = loserPlayerIdsWithReasons.entrySet().iterator().next(); + + gameRecordingInProgress.finishRecording(winnerPlayerId, winReason, loserEntry.getKey(), loserEntry.getValue()); + } finally { + _lock.writeLock().unlock(); + } + } + + @Override + public void gameCancelled() { + _lock.writeLock().lock(); + try { + gameRecordingInProgress.finishRecording(participants[0].getPlayerId(), "Game cancelled due to error", participants[1].getPlayerId(), "Game cancelled due to error"); + } finally { + _lock.writeLock().unlock(); + } } } + ); - @Override - public void gameCancelled() { - synchronized (_finishedGamesTime) { - _finishedGamesTime.put(gameId, new Date()); - } - } - }); - lotroGameMediator.sendMessageToPlayers("You're starting a game of " + lotroFormat.getName()); - - StringBuffer players = new StringBuffer(); - Map deckNames = new HashMap(); - for (LotroGameParticipant participant : participants) { - deckNames.put(participant.getPlayerId(), participant.getDeck().getDeckName()); - if (players.length() > 0) - players.append(", "); - players.append(participant.getPlayerId()); + _runningGames.put(gameId, lotroGameMediator); + _nextGameId++; + return gameId; + } finally { + _lock.writeLock().unlock(); } - - lotroGameMediator.sendMessageToPlayers("Players in the game are: " + players.toString()); - - final GameRecorder.GameRecordingInProgress gameRecordingInProgress = _gameRecorder.recordGame(lotroGameMediator, lotroFormat.getName(), tournamentName, deckNames); - lotroGameMediator.addGameResultListener( - new GameResultListener() { - @Override - public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { - final Map.Entry loserEntry = loserPlayerIdsWithReasons.entrySet().iterator().next(); - - gameRecordingInProgress.finishRecording(winnerPlayerId, winReason, loserEntry.getKey(), loserEntry.getValue()); - } - - @Override - public void gameCancelled() { - gameRecordingInProgress.finishRecording(participants[0].getPlayerId(), "Game cancelled due to error", participants[1].getPlayerId(), "Game cancelled due to error"); - } - } - ); - - _runningGames.put(gameId, lotroGameMediator); - _nextGameId++; - return gameId; } public LotroDeck getParticipantDeck(Player player, String deckName) { @@ -217,7 +189,12 @@ public class LotroServer extends AbstractServer { } public LotroGameMediator getGameById(String gameId) { - return _runningGames.get(gameId); + _lock.readLock().lock(); + try { + return _runningGames.get(gameId); + } finally { + _lock.readLock().unlock(); + } } } 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 1804ff3e7..969bb6d61 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 @@ -99,10 +99,6 @@ public class HallServer extends AbstractServer { } } - public Map getSupportedFormats() { - return _formatLibrary.getHallFormats(); - } - private void cancelWaitingTables() { _awaitingTables.clear(); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java index be0aa1610..db5cb1e2b 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java @@ -41,7 +41,7 @@ public class LeagueService { _collectionsManager = collectionsManager; } - public void clearCache() { + public synchronized void clearCache() { _leagueSerieStandings.clear(); _leagueStandings.clear(); _activeLeaguesLoadedDate = 0; @@ -68,7 +68,7 @@ public class LeagueService { } } - public List getActiveLeagues() { + public synchronized List getActiveLeagues() { if (DateUtils.getCurrentDate() == _activeLeaguesLoadedDate) return Collections.unmodifiableList(_activeLeagues); else { @@ -86,11 +86,11 @@ public class LeagueService { } } - public boolean isPlayerInLeague(League league, Player player) { + public synchronized boolean isPlayerInLeague(League league, Player player) { return _leagueParticipationDAO.getUsersParticipating(league.getType()).contains(player.getName()); } - public boolean playerJoinsLeague(League league, Player player) { + public synchronized boolean playerJoinsLeague(League league, Player player) { if (isPlayerInLeague(league, player)) return false; int cost = league.getCost(); @@ -106,7 +106,7 @@ public class LeagueService { } } - public League getLeagueByType(String type) { + public synchronized League getLeagueByType(String type) { for (League league : getActiveLeagues()) { if (league.getType().equals(type)) return league; @@ -114,7 +114,7 @@ public class LeagueService { return null; } - public CollectionType getCollectionTypeByCode(String collectionTypeCode) { + public synchronized CollectionType getCollectionTypeByCode(String collectionTypeCode) { for (League league : getActiveLeagues()) { for (LeagueSerieData leagueSerieData : league.getLeagueData().getSeries()) { CollectionType collectionType = leagueSerieData.getCollectionType(); @@ -125,7 +125,7 @@ public class LeagueService { return null; } - public LeagueSerieData getCurrentLeagueSerie(League league) { + public synchronized LeagueSerieData getCurrentLeagueSerie(League league) { final int currentDate = DateUtils.getCurrentDate(); for (LeagueSerieData leagueSerieData : league.getLeagueData().getSeries()) { @@ -136,7 +136,7 @@ public class LeagueService { return null; } - public void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) { + public synchronized void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) { _leagueMatchDao.addPlayedMatch(league.getType(), serie.getName(), winner, loser); _leagueStandings.remove(LeagueMapKeys.getLeagueMapKey(league)); @@ -173,7 +173,7 @@ public class LeagueService { return result; } - public List getLeagueStandings(League league) { + public synchronized List getLeagueStandings(League league) { List leagueStandings = _leagueStandings.get(LeagueMapKeys.getLeagueMapKey(league)); if (leagueStandings == null) { synchronized (this) { @@ -184,7 +184,7 @@ public class LeagueService { return leagueStandings; } - public List getLeagueSerieStandings(League league, LeagueSerieData leagueSerie) { + public synchronized List getLeagueSerieStandings(League league, LeagueSerieData leagueSerie) { List serieStandings = _leagueSerieStandings.get(LeagueMapKeys.getLeagueSerieMapKey(league, leagueSerie)); if (serieStandings == null) { synchronized (this) { @@ -219,7 +219,7 @@ public class LeagueService { return StandingsProducer.produceStandings(playersParticipating, matches, 2, 1, Collections.emptyMap()); } - public boolean canPlayRankedGame(League league, LeagueSerieData season, String player) { + public synchronized boolean canPlayRankedGame(League league, LeagueSerieData season, String player) { int maxMatches = season.getMaxMatches(); Collection playedInSeason = getPlayerMatchesInSerie(league, season, player); if (playedInSeason.size() >= maxMatches) @@ -227,7 +227,7 @@ public class LeagueService { return true; } - public boolean canPlayRankedGameAgainst(League league, LeagueSerieData season, String playerOne, String playerTwo) { + public synchronized boolean canPlayRankedGameAgainst(League league, LeagueSerieData season, String playerOne, String playerTwo) { Collection playedInSeason = getPlayerMatchesInSerie(league, season, playerOne); for (LeagueMatchResult leagueMatch : playedInSeason) { if (playerTwo.equals(leagueMatch.getWinner()) || playerTwo.equals(leagueMatch.getLoser())) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java index 438e87851..e015d56d5 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationRecurringQueue.java @@ -98,7 +98,7 @@ public class SingleEliminationRecurringQueue implements TournamentQueue { } @Override - public void leaveAllPlayers(CollectionsManager collectionsManager) { + public synchronized void leaveAllPlayers(CollectionsManager collectionsManager) { if (_cost > 0) { for (String player : _playerDecks.keySet()) collectionsManager.addCurrencyToPlayerCollection(player, _currencyCollection, _cost); diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/CollectionResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/CollectionResource.java index 6dd42501b..ac2c430b2 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/CollectionResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/CollectionResource.java @@ -167,10 +167,7 @@ public class CollectionResource extends AbstractResource { } private CardCollection getCollection(Player player, String collectionType) { - if (collectionType.equals("default")) - return _lotroServer.getDefaultCollection(); - else - return _collectionsManager.getPlayerCollection(player, collectionType); + return _collectionsManager.getPlayerCollection(player, collectionType); } @Path("/{collectionType}") diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java index 1926f8047..fba32a160 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java @@ -3,6 +3,7 @@ package com.gempukku.lotro.server; import com.gempukku.lotro.common.Side; import com.gempukku.lotro.db.DeckDAO; import com.gempukku.lotro.game.*; +import com.gempukku.lotro.game.formats.LotroFormatLibrary; import com.gempukku.lotro.hall.HallServer; import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.vo.LotroDeck; @@ -36,6 +37,8 @@ public class DeckResource extends AbstractResource { private LotroCardBlueprintLibrary _library; @Context private DeckDAO _deckDao; + @Context + private LotroFormatLibrary _formatLibrary; private SortAndFilterCards _sortAndFilterCards = new SortAndFilterCards(); @@ -217,7 +220,7 @@ public class DeckResource extends AbstractResource { StringBuilder sb = new StringBuilder(); sb.append("Free People: " + fpCount + ", Shadow: " + shadowCount + "
"); - for (LotroFormat format : _hallServer.getSupportedFormats().values()) { + for (LotroFormat format : _formatLibrary.getHallFormats().values()) { try { format.validateDeck(resourceOwner, deck); sb.append("" + format.getName() + ": valid
"); 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 f77b0b09a..bf52dcbc3 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 @@ -130,7 +130,7 @@ public class HallResource extends AbstractResource { hall.setAttribute("motd", motd); _hallServer.processHall(resourceOwner, new SerializeHallInfoVisitor(doc, hall)); - for (Map.Entry format : _hallServer.getSupportedFormats().entrySet()) { + for (Map.Entry format : _formatLibrary.getHallFormats().entrySet()) { Element formatElem = doc.createElement("format"); formatElem.setAttribute("type", format.getKey()); formatElem.appendChild(doc.createTextNode(format.getValue().getName())); diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/ServerResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/ServerResource.java index 6e539d9d6..caa1ba3ce 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/ServerResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/ServerResource.java @@ -47,6 +47,8 @@ public class ServerResource extends AbstractResource { private ChatServer _chatServer; @Context private GameHistoryService _gameHistoryService; + @Context + private GameRecorder _gameRecorder; public ServerResource() { if (!_test) @@ -126,7 +128,7 @@ public class ServerResource extends AbstractResource { return new StreamingOutput() { @Override public void write(OutputStream outputStream) throws IOException, WebApplicationException { - final InputStream recordedGame = _lotroServer.getGameRecording(split[0], split[1]); + final InputStream recordedGame = _gameRecorder.getRecordedGame(split[0], split[1]); if (recordedGame == null) throw new WebApplicationException(Response.Status.NOT_FOUND); try { diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/DaoProvider.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/DaoProvider.java index 4964848ba..2c68f2768 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/DaoProvider.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/DaoProvider.java @@ -34,13 +34,12 @@ public class DaoProvider implements InjectableProvider { private DbAccess _dbAccess; private CollectionSerializer _collectionSerializer; + @Context private LotroCardBlueprintLibrary _library; public DaoProvider() { _dbAccess = new DbAccess(); _collectionSerializer = new CollectionSerializer(); - - _library = new LotroCardBlueprintLibrary(); } @Override diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/ServerProvider.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/ServerProvider.java index 67ca2e238..18829c8a2 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/ServerProvider.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/provider/ServerProvider.java @@ -5,6 +5,7 @@ import com.gempukku.lotro.collection.CollectionsManager; import com.gempukku.lotro.collection.DeliveryService; import com.gempukku.lotro.db.*; import com.gempukku.lotro.game.GameHistoryService; +import com.gempukku.lotro.game.GameRecorder; import com.gempukku.lotro.game.LotroCardBlueprintLibrary; import com.gempukku.lotro.game.LotroServer; import com.gempukku.lotro.game.formats.LotroFormatLibrary; @@ -37,6 +38,7 @@ public class ServerProvider implements InjectableProvider { private Injectable _collectionsManagerInjectable; private Injectable _deliveryServiceInjectable; private Injectable _lotroFormatLibraryInjectable; + private Injectable _gameRecorderInjectable; @Context private PlayerDAO _playerDao; @@ -85,6 +87,8 @@ public class ServerProvider implements InjectableProvider { return getMerchantServiceInjectable(); if (type.equals(TournamentService.class)) return getTournamentServiceInjectable(); + if (type.equals(GameRecorder.class)) + return getGameRecorderInjectable(); return null; } @@ -135,6 +139,19 @@ public class ServerProvider implements InjectableProvider { return _gameHistoryServiceInjectable; } + private synchronized Injectable getGameRecorderInjectable() { + if (_gameRecorderInjectable == null) { + final GameRecorder gameRecorder = new GameRecorder(getGameHistoryServiceInjectable().getValue()); + _gameRecorderInjectable = new Injectable() { + @Override + public GameRecorder getValue() { + return gameRecorder; + } + }; + } + return _gameRecorderInjectable; + } + private synchronized Injectable getMerchantServiceInjectable() { if (_merchantServiceInjectable == null) { final MerchantService merchantService = new MerchantService(_library, getCollectionsManagerInjectable().getValue(), _merchantDao); @@ -208,7 +225,7 @@ public class ServerProvider implements InjectableProvider { private synchronized Injectable getLotroServerInjectable() { if (_lotroServerInjectable == null) { - final LotroServer lotroServer = new LotroServer(_deckDao, getGameHistoryServiceInjectable().getValue(), _library, getChatServerInjectable().getValue(), false); + final LotroServer lotroServer = new LotroServer(_deckDao, _library, getChatServerInjectable().getValue(), getGameRecorderInjectable().getValue()); lotroServer.startServer(); _lotroServerInjectable = new Injectable() { @Override @@ -236,7 +253,7 @@ public class ServerProvider implements InjectableProvider { private synchronized Injectable getCollectionsManagerInjectable() { if (_collectionsManagerInjectable == null) { - final CollectionsManager collectionsManager = new CollectionsManager(_playerDao, _collectionDao, getDeliveryServiceInjectable().getValue()); + final CollectionsManager collectionsManager = new CollectionsManager(_playerDao, _collectionDao, getDeliveryServiceInjectable().getValue(), _library); _collectionsManagerInjectable = new Injectable() { @Override public CollectionsManager getValue() {