Limited the caches by collection size.

This commit is contained in:
marcins78
2012-12-12 17:33:09 +00:00
parent 4b46bcc8c6
commit 1a8235746b
17 changed files with 258 additions and 96 deletions

View File

@@ -35,6 +35,11 @@
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>

View File

@@ -0,0 +1,45 @@
package com.gempukku.lotro.collection;
import com.gempukku.lotro.db.CollectionDAO;
import com.gempukku.lotro.game.CardCollection;
import org.apache.commons.collections.map.LRUMap;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Map;
public class CachedCollectionDAO implements CollectionDAO {
private CollectionDAO _delegate;
private Map<String, CardCollection> _playerCollections = Collections.synchronizedMap(new LRUMap(100));
public CachedCollectionDAO(CollectionDAO delegate) {
_delegate = delegate;
}
@Override
public CardCollection getPlayerCollection(int playerId, String type) throws SQLException, IOException {
String key = constructCacheKey(playerId, type);
CardCollection collection = (CardCollection) _playerCollections.get(key);
if (collection == null) {
collection = _delegate.getPlayerCollection(playerId, type);
_playerCollections.put(key, collection);
}
return collection;
}
private String constructCacheKey(int playerId, String type) {
return playerId +"-"+type;
}
@Override
public Map<Integer, CardCollection> getPlayerCollectionsByType(String type) throws SQLException, IOException {
return _delegate.getPlayerCollectionsByType(type);
}
@Override
public void setPlayerCollection(int playerId, String type, CardCollection collection) throws SQLException, IOException {
_delegate.setPlayerCollection(playerId, type, collection);
_playerCollections.put(constructCacheKey(playerId, type), collection);
}
}

View File

@@ -11,14 +11,12 @@ import org.apache.log4j.Logger;
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 {
private static Logger _logger = Logger.getLogger(CollectionsManager.class);
private ReentrantReadWriteLock _readWriteLock = new ReentrantReadWriteLock();
private Map<String, Map<String, CardCollection>> _collections = new ConcurrentHashMap<String, Map<String, CardCollection>>();
private PlayerDAO _playerDAO;
private CollectionDAO _collectionDAO;
@@ -73,10 +71,6 @@ public class CollectionsManager {
return _defaultCollection;
}
public void clearDBCache() {
_collections.clear();
}
public CardCollection getPlayerCollection(Player player, String collectionType) {
_readWriteLock.readLock().lock();
try {
@@ -86,24 +80,11 @@ public class CollectionsManager {
if (collectionType.equals("default"))
return getDefaultCollection();
Map<String, CardCollection> playerCollections = _collections.get(player.getName());
if (playerCollections != null) {
final CardCollection cardCollection = playerCollections.get(collectionType);
if (cardCollection != null)
return cardCollection;
}
final CardCollection collection = _collectionDAO.getPlayerCollection(player.getId(), collectionType);
if (collection != null) {
if (playerCollections == null) {
playerCollections = new ConcurrentHashMap<String, CardCollection>();
_collections.put(player.getName(), playerCollections);
}
playerCollections.put(collectionType, collection);
}
if (collection == null && collectionType.equals("permanent"))
return new DefaultCardCollection();
return collection;
} catch (SQLException exp) {
throw new RuntimeException("Unable to get player collection", exp);
@@ -127,12 +108,6 @@ public class CollectionsManager {
throw new IllegalArgumentException("Invalid collection type: " + collectionType);
try {
_collectionDAO.setPlayerCollection(player.getId(), collectionType, cardCollection);
Map<String, CardCollection> playerCollections = _collections.get(player.getName());
if (playerCollections == null) {
playerCollections = new ConcurrentHashMap<String, CardCollection>();
_collections.put(player.getName(), playerCollections);
}
playerCollections.put(collectionType, cardCollection);
} catch (SQLException exp) {
throw new RuntimeException("Unable to store player collection", exp);
} catch (IOException exp) {

View File

@@ -0,0 +1,76 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.game.Player;
import com.gempukku.lotro.logic.vo.LotroDeck;
import org.apache.commons.collections.map.LRUMap;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class CachedDeckDAO implements DeckDAO {
private DeckDAO _delegate;
private Map<String, Set<String>> _playerDeckNames = Collections.synchronizedMap(new LRUMap(100));
private Map<String, LotroDeck> _decks = Collections.synchronizedMap(new LRUMap(100));
public CachedDeckDAO(DeckDAO delegate) {
_delegate = delegate;
}
@Override
public LotroDeck buildDeckFromContents(String deckName, String contents) {
return _delegate.buildDeckFromContents(deckName, contents);
}
private String constructPlayerDeckNamesKey(Player player) {
return player.getName();
}
private String constructDeckKey(Player player, String name) {
return player.getName()+"-"+name;
}
@Override
public void deleteDeckForPlayer(Player player, String name) {
_delegate.deleteDeckForPlayer(player, name);
_playerDeckNames.remove(constructPlayerDeckNamesKey(player));
}
@Override
public LotroDeck getDeckForPlayer(Player player, String name) {
String key = constructDeckKey(player, name);
LotroDeck deck = (LotroDeck) _decks.get(key);
if (deck == null) {
deck = _delegate.getDeckForPlayer(player, name);
_decks.put(key, deck);
}
return deck;
}
@Override
public Set<String> getPlayerDeckNames(Player player) {
String cacheKey = constructPlayerDeckNamesKey(player);
Set<String> deckNames = (Set<String>) _playerDeckNames.get(cacheKey);
if (deckNames == null) {
deckNames = Collections.synchronizedSet(new HashSet<String>(_delegate.getPlayerDeckNames(player)));
_playerDeckNames.put(cacheKey, deckNames);
}
return deckNames;
}
@Override
public LotroDeck renameDeck(Player player, String oldName, String newName) {
LotroDeck lotroDeck = _delegate.renameDeck(player, oldName, newName);
_playerDeckNames.remove(constructPlayerDeckNamesKey(player));
_decks.remove(constructDeckKey(player, oldName));
_decks.put(constructDeckKey(player, newName), lotroDeck);
return lotroDeck;
}
@Override
public void saveDeckForPlayer(Player player, String name, LotroDeck deck) {
_delegate.saveDeckForPlayer(player, name, deck);
_decks.put(constructDeckKey(player, name), deck);
}
}

View File

@@ -0,0 +1,32 @@
package com.gempukku.lotro.db;
import org.apache.commons.collections.map.LRUMap;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
public class CachedMerchantDAO implements MerchantDAO {
private MerchantDAO _delegate;
private Map<String, Transaction> _blueprintIdLastTransaction = Collections.synchronizedMap(new LRUMap(500));
public CachedMerchantDAO(MerchantDAO delegate) {
_delegate = delegate;
}
@Override
public void addTransaction(String blueprintId, float price, Date date, TransactionType transactionType) {
_delegate.addTransaction(blueprintId, price, date, transactionType);
_blueprintIdLastTransaction.put(blueprintId, new Transaction(date, price, transactionType));
}
@Override
public Transaction getLastTransaction(String blueprintId) {
Transaction transaction = (Transaction) _blueprintIdLastTransaction.get(blueprintId);
if (transaction == null) {
transaction = _delegate.getLastTransaction(blueprintId);
_blueprintIdLastTransaction.put(blueprintId, transaction);
}
return transaction;
}
}

View File

@@ -0,0 +1,75 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.game.Player;
import org.apache.commons.collections.map.LRUMap;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Map;
public class CachedPlayerDAO implements PlayerDAO {
private PlayerDAO _delegate;
private Map<Integer, Player> _playerById = Collections.synchronizedMap(new LRUMap(500));
private Map<String, Player> _playerByName = Collections.synchronizedMap(new LRUMap(500));
public CachedPlayerDAO(PlayerDAO delegate) {
_delegate = delegate;
}
@Override
public Player getPlayer(int id) {
Player player = (Player) _playerById.get(id);
if (player == null) {
player = _delegate.getPlayer(id);
_playerById.put(id, player);
_playerByName.put(player.getName(), player);
}
return player;
}
@Override
public Player getPlayer(String playerName) {
Player player = (Player) _playerByName.get(playerName);
if (player == null) {
player = _delegate.getPlayer(playerName);
_playerById.put(player.getId(), player);
_playerByName.put(player.getName(), player);
}
return player;
}
@Override
public Player loginUser(String login, String password) throws SQLException {
return _delegate.loginUser(login, password);
}
@Override
public boolean registerUser(String login, String password, String remoteAddr) throws SQLException {
boolean registered = _delegate.registerUser(login, password, remoteAddr);
if (registered)
_playerByName.remove(login);
return registered;
}
@Override
public void setLastReward(Player player, int currentReward) throws SQLException {
_delegate.setLastReward(player, currentReward);
_playerById.remove(player.getId());
_playerByName.remove(player.getName());
}
@Override
public void updateLastLoginIp(String login, String remoteAddr) throws SQLException {
_delegate.updateLastLoginIp(login, remoteAddr);
}
@Override
public boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException {
boolean updated = _delegate.updateLastReward(player, previousReward, currentReward);
if (updated) {
_playerById.remove(player.getId());
_playerByName.remove(player.getName());
}
return updated;
}
}

View File

@@ -10,23 +10,16 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class DbDeckDAO implements DeckDAO {
private DbAccess _dbAccess;
private LotroCardBlueprintLibrary _library;
private Map<Integer, Map<String, LotroDeck>> _decks = new ConcurrentHashMap<Integer, Map<String, LotroDeck>>();
public DbDeckDAO(DbAccess dbAccess, LotroCardBlueprintLibrary library) {
_dbAccess = dbAccess;
_library = library;
}
public synchronized void clearCache() {
_decks.clear();
}
public synchronized LotroDeck getDeckForPlayer(Player player, String name) {
Map<String, LotroDeck> deckMap = getPlayerDecks(player);
return deckMap.get(name);
@@ -64,15 +57,6 @@ public class DbDeckDAO implements DeckDAO {
}
private Map<String, LotroDeck> getPlayerDecks(Player player) {
Map<String, LotroDeck> decksByName = _decks.get(player.getId());
if (decksByName == null) {
decksByName = loadPlayerDecks(player);
_decks.put(player.getId(), decksByName);
}
return decksByName;
}
private Map<String, LotroDeck> loadPlayerDecks(Player player) {
try {
return loadPlayerDecksFromDB(player.getId());
} catch (SQLException exp) {

View File

@@ -2,22 +2,14 @@ package com.gempukku.lotro.db;
import java.sql.*;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DbMerchantDAO implements MerchantDAO {
private DbAccess _dbAccess;
private Map<String, Transaction> _transactionsMap = new ConcurrentHashMap<String, Transaction>();
public DbMerchantDAO(DbAccess dbAccess) {
_dbAccess = dbAccess;
}
@Override
public void clearCache() {
_transactionsMap.clear();
}
@Override
public void addTransaction(String blueprintId, float price, Date date, TransactionType transactionType) {
final Transaction lastTransaction = getLastTransaction(blueprintId);
@@ -26,7 +18,6 @@ public class DbMerchantDAO implements MerchantDAO {
} else {
updateTransaction(blueprintId, price, date, transactionType);
}
_transactionsMap.put(blueprintId, new Transaction(date, price, transactionType));
}
private void updateTransaction(String blueprintId, float price, Date date, TransactionType transactionType) {
@@ -87,10 +78,6 @@ public class DbMerchantDAO implements MerchantDAO {
@Override
public Transaction getLastTransaction(String blueprintId) {
final Transaction transaction = _transactionsMap.get(blueprintId);
if (transaction != null)
return transaction;
try {
Connection connection = _dbAccess.getDataSource().getConnection();
try {

View File

@@ -7,33 +7,19 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DbPlayerDAO implements PlayerDAO {
private final String validLoginChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
private DbAccess _dbAccess;
private Map<String, Player> _playersByName = new ConcurrentHashMap<String, Player>();
private Map<Integer, Player> _playersById = new ConcurrentHashMap<Integer, Player>();
public DbPlayerDAO(DbAccess dbAccess) {
_dbAccess = dbAccess;
}
public synchronized void clearCache() {
_playersByName.clear();
_playersById.clear();
}
public synchronized Player getPlayer(int id) {
if (_playersById.containsKey(id))
return _playersById.get(id);
try {
final Player player = getPlayerFromDBById(id);
if (player != null)
_playersById.put(id, player);
return player;
} catch (SQLException exp) {
throw new RuntimeException("Error while retrieving player", exp);
@@ -41,12 +27,8 @@ public class DbPlayerDAO implements PlayerDAO {
}
public synchronized Player getPlayer(String playerName) {
if (_playersByName.containsKey(playerName))
return _playersByName.get(playerName);
try {
Player player = getPlayerFromDBByName(playerName);
if (player != null)
_playersByName.put(playerName, player);
return player;
} catch (SQLException exp) {
throw new RuntimeException("Unable to get player from DB", exp);

View File

@@ -6,8 +6,6 @@ import com.gempukku.lotro.logic.vo.LotroDeck;
import java.util.Set;
public interface DeckDAO {
public void clearCache();
public LotroDeck getDeckForPlayer(Player player, String name);
public void saveDeckForPlayer(Player player, String name, LotroDeck deck);

View File

@@ -7,8 +7,6 @@ public interface MerchantDAO {
public void addTransaction(String blueprintId, float price, Date date, TransactionType transactionType);
public void clearCache();
public enum TransactionType {
SELL, BUY
}

View File

@@ -5,8 +5,6 @@ import com.gempukku.lotro.game.Player;
import java.sql.SQLException;
public interface PlayerDAO {
public void clearCache();
public Player getPlayer(int id);
public Player getPlayer(String playerName);

View File

@@ -2,11 +2,11 @@ package com.gempukku.lotro.league;
import com.gempukku.lotro.db.LeagueMatchDAO;
import com.gempukku.lotro.db.vo.LeagueMatchResult;
import org.apache.commons.collections.map.LRUMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -15,7 +15,7 @@ public class CachedLeagueMatchDAO implements LeagueMatchDAO {
private LeagueMatchDAO _leagueMatchDAO;
private ReadWriteLock _readWriteLock = new ReentrantReadWriteLock();
private Map<String, Collection<LeagueMatchResult>> _cachedMatches = new ConcurrentHashMap<String, Collection<LeagueMatchResult>>();
private Map<String, Collection<LeagueMatchResult>> _cachedMatches = Collections.synchronizedMap(new LRUMap(5));
public CachedLeagueMatchDAO(LeagueMatchDAO leagueMatchDAO) {
_leagueMatchDAO = leagueMatchDAO;

View File

@@ -2,12 +2,12 @@ package com.gempukku.lotro.league;
import com.gempukku.lotro.db.LeagueParticipationDAO;
import com.gempukku.lotro.game.Player;
import org.apache.commons.collections.map.LRUMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -16,7 +16,7 @@ public class CachedLeagueParticipationDAO implements LeagueParticipationDAO {
private LeagueParticipationDAO _leagueParticipationDAO;
private ReadWriteLock _readWriteLock = new ReentrantReadWriteLock();
private Map<String, Set<String>> _cachedParticipants = new ConcurrentHashMap<String, Set<String>>();
private Map<String, Set<String>> _cachedParticipants = Collections.synchronizedMap(new LRUMap(5));
public CachedLeagueParticipationDAO(LeagueParticipationDAO leagueParticipationDAO) {
_leagueParticipationDAO = leagueParticipationDAO;

View File

@@ -24,8 +24,4 @@ public class MockMerchantDAO implements MerchantDAO {
return new Transaction(_dates.get(blueprintId), _prices.get(blueprintId), _transactionTypes.get(blueprintId));
return null;
}
@Override
public void clearCache() {
}
}

View File

@@ -59,10 +59,6 @@ public class AdminResource extends AbstractResource {
public String clearCache(@Context HttpServletRequest request) throws Exception {
validateAdmin(request);
_playerDao.clearCache();
_collectionsManager.clearDBCache();
_deckDao.clearCache();
_merchantDao.clearCache();
_leagueService.clearCache();
_tournamentService.clearCache();

View File

@@ -1,5 +1,6 @@
package com.gempukku.lotro.server.provider;
import com.gempukku.lotro.collection.CachedCollectionDAO;
import com.gempukku.lotro.collection.CachedTransferDAO;
import com.gempukku.lotro.collection.CollectionSerializer;
import com.gempukku.lotro.collection.TransferDAO;
@@ -24,12 +25,26 @@ public class DaoBuilder {
objectMap.put(TournamentDAO.class, new DbTournamentDAO(dbAccess));
objectMap.put(TournamentPlayerDAO.class, new DbTournamentPlayerDAO(dbAccess));
objectMap.put(TournamentMatchDAO.class, new DbTournamentMatchDAO(dbAccess));
objectMap.put(MerchantDAO.class, new DbMerchantDAO(dbAccess));
DbMerchantDAO dbMerchantDao = new DbMerchantDAO(dbAccess);
CachedMerchantDAO merchantDao = new CachedMerchantDAO(dbMerchantDao);
objectMap.put(MerchantDAO.class, merchantDao);
objectMap.put(LeagueDAO.class, new DbLeagueDAO(dbAccess));
objectMap.put(GameHistoryDAO.class, new DbGameHistoryDAO(dbAccess));
objectMap.put(DeckDAO.class, new DbDeckDAO(dbAccess, library));
objectMap.put(CollectionDAO.class, new DbCollectionDAO(dbAccess, collectionSerializer));
objectMap.put(PlayerDAO.class, new DbPlayerDAO(dbAccess));
DbDeckDAO dbDeckDao = new DbDeckDAO(dbAccess, library);
CachedDeckDAO deckDao = new CachedDeckDAO(dbDeckDao);
objectMap.put(DeckDAO.class, deckDao);
DbCollectionDAO dbCollectionDao = new DbCollectionDAO(dbAccess, collectionSerializer);
CachedCollectionDAO collectionDao = new CachedCollectionDAO(dbCollectionDao);
objectMap.put(CollectionDAO.class, collectionDao);
DbPlayerDAO dbPlayerDao = new DbPlayerDAO(dbAccess);
CachedPlayerDAO playerDao = new CachedPlayerDAO(dbPlayerDao);
objectMap.put(PlayerDAO.class, playerDao);
DbTransferDAO dbTransferDao = new DbTransferDAO(dbAccess);
CachedTransferDAO transferDao = new CachedTransferDAO(dbTransferDao);