Better caching for league participation (separate class).

This commit is contained in:
marcins78@gmail.com
2012-05-02 15:29:57 +00:00
parent 4f76524220
commit e562f68e44
5 changed files with 162 additions and 98 deletions

View File

@@ -0,0 +1,79 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.game.Player;
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;
public class CachedLeagueParticipationDAO implements LeagueParticipationDAO {
private LeagueParticipationDAO _leagueParticipationDAO;
private ReadWriteLock _readWriteLock = new ReentrantReadWriteLock();
private Map<String, Set<String>> _cachedParticipants = new ConcurrentHashMap<String, Set<String>>();
public CachedLeagueParticipationDAO(LeagueParticipationDAO leagueParticipationDAO) {
_leagueParticipationDAO = leagueParticipationDAO;
}
private String getLeagueCacheKey(League league) {
return league.getType();
}
@Override
public void userJoinsLeague(League league, Player player) {
_readWriteLock.writeLock().lock();
try {
getLeagueParticipantsInWriteLock(league).add(player.getName());
_leagueParticipationDAO.userJoinsLeague(league, player);
} finally {
_readWriteLock.writeLock().unlock();
}
}
@Override
public Collection<String> getUsersParticipating(League league) {
_readWriteLock.readLock().lock();
try {
Collection<String> leagueParticipants = _cachedParticipants.get(getLeagueCacheKey(league));
if (leagueParticipants == null) {
_readWriteLock.readLock().unlock();
_readWriteLock.writeLock().lock();
try {
leagueParticipants = getLeagueParticipantsInWriteLock(league);
} finally {
_readWriteLock.readLock().lock();
_readWriteLock.writeLock().unlock();
}
}
return Collections.unmodifiableCollection(leagueParticipants);
} finally {
_readWriteLock.readLock().unlock();
}
}
private Collection<String> getLeagueParticipantsInWriteLock(League league) {
Set<String> leagueParticipants;
leagueParticipants = _cachedParticipants.get(getLeagueCacheKey(league));
if (leagueParticipants == null) {
leagueParticipants = new CopyOnWriteArraySet<String>(_leagueParticipationDAO.getUsersParticipating(league));
_cachedParticipants.put(getLeagueCacheKey(league), leagueParticipants);
}
return leagueParticipants;
}
public void clearCache() {
_readWriteLock.writeLock().lock();
try {
_cachedParticipants.clear();
} finally {
_readWriteLock.writeLock().unlock();
}
}
}

View File

@@ -0,0 +1,67 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.game.Player;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class DbLeagueParticipationDAO implements LeagueParticipationDAO {
private DbAccess _dbAccess;
public DbLeagueParticipationDAO(DbAccess dbAccess) {
_dbAccess = dbAccess;
}
public void userJoinsLeague(League league, Player player) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("insert into league_participation (league_type, player_name) values (?,?)");
try {
statement.setString(1, league.getType());
statement.setString(2, player.getName());
statement.execute();
} finally {
statement.close();
}
} finally {
conn.close();
}
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
}
public Collection<String> getUsersParticipating(League league) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("select player_name from league_participation where league_type=?");
try {
statement.setString(1, league.getType());
final ResultSet rs = statement.executeQuery();
try {
Set<String> result = new HashSet<String>();
while (rs.next())
result.add(rs.getString(1));
return result;
} finally {
rs.close();
}
} finally {
statement.close();
}
} finally {
conn.close();
}
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
}
}

View File

@@ -3,55 +3,10 @@ package com.gempukku.lotro.db;
import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.game.Player;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
public class LeagueParticipationDAO {
private DbAccess _dbAccess;
public interface LeagueParticipationDAO {
public void userJoinsLeague(League league, Player player);
public LeagueParticipationDAO(DbAccess dbAccess) {
_dbAccess = dbAccess;
}
public void userJoinsLeague(League league, Player player) throws SQLException {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("insert into league_participation (league_type, player_name) values (?,?)");
try {
statement.setString(1, league.getType());
statement.setString(2, player.getName());
statement.execute();
} finally {
statement.close();
}
} finally {
conn.close();
}
}
public boolean isUserParticipating(League league, Player player) throws SQLException {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("select count(*) from league_participation where league_type=? and player_name=?");
try {
statement.setString(1, league.getType());
statement.setString(2, player.getName());
final ResultSet rs = statement.executeQuery();
try {
if (rs.next())
return (rs.getInt(1) > 0);
else
return false;
} finally {
rs.close();
}
} finally {
statement.close();
}
} finally {
conn.close();
}
}
public Collection<String> getUsersParticipating(League league);
}

View File

@@ -28,15 +28,13 @@ public class LeagueService {
private CachedLeaguePointsDAO _leaguePointsDao;
// Cached on this layer
private CachedLeagueMatchDAO _leagueMatchDao;
private LeagueParticipationDAO _leagueParticipationDAO;
private CachedLeagueParticipationDAO _leagueParticipationDAO;
private CollectionsManager _collectionsManager;
private Map<League, List<PlayerStanding>> _leagueStandings = new ConcurrentHashMap<League, List<PlayerStanding>>();
private Map<LeagueSerieData, List<PlayerStanding>> _leagueSerieStandings = new ConcurrentHashMap<LeagueSerieData, List<PlayerStanding>>();
private Map<League, Set<String>> _playersParticipating = new ConcurrentHashMap<League, Set<String>>();
private Map<League, Set<String>> _playersNotParticipating = new ConcurrentHashMap<League, Set<String>>();
private int _activeLeaguesLoadedDate;
private List<League> _activeLeagues;
@@ -45,7 +43,7 @@ public class LeagueService {
_leagueDao = leagueDao;
_leaguePointsDao = new CachedLeaguePointsDAO(leaguePointsDao);
_leagueMatchDao = new CachedLeagueMatchDAO(leagueMatchDao);
_leagueParticipationDAO = leagueParticipationDAO;
_leagueParticipationDAO = new CachedLeagueParticipationDAO(leagueParticipationDAO);
_collectionsManager = collectionsManager;
}
@@ -56,6 +54,7 @@ public class LeagueService {
_leagueMatchDao.clearCache();
_leaguePointsDao.clearCache();
_leagueParticipationDAO.clearCache();
}
private synchronized void ensureLoadedCurrentLeagues() {
@@ -63,6 +62,7 @@ public class LeagueService {
if (currentDate != _activeLeaguesLoadedDate) {
_leagueMatchDao.clearCache();
_leaguePointsDao.clearCache();
_leagueParticipationDAO.clearCache();
try {
_activeLeagues = _leagueDao.loadActiveLeagues(currentDate);
@@ -94,55 +94,18 @@ public class LeagueService {
}
}
public synchronized boolean isPlayerInLeague(League league, Player player) {
Set<String> playersParticipating = _playersParticipating.get(league);
if (playersParticipating != null && playersParticipating.contains(player.getName()))
return true;
Set<String> playersNotParticipating = _playersNotParticipating.get(league);
if (playersNotParticipating != null && playersNotParticipating.contains(player.getName()))
return false;
try {
final boolean userParticipating = _leagueParticipationDAO.isUserParticipating(league, player);
if (userParticipating) {
if (playersParticipating == null) {
playersParticipating = new HashSet<String>();
_playersParticipating.put(league, playersParticipating);
}
playersParticipating.add(player.getName());
} else {
if (playersNotParticipating == null) {
playersNotParticipating = new HashSet<String>();
_playersNotParticipating.put(league, playersNotParticipating);
}
playersNotParticipating.add(player.getName());
}
return userParticipating;
} catch (SQLException e) {
throw new RuntimeException("Unable to retrieve information if user is part of the league");
}
public boolean isPlayerInLeague(League league, Player player) {
return _leagueParticipationDAO.getUsersParticipating(league).contains(player.getName());
}
public synchronized boolean playerJoinsLeague(League league, Player player) {
public boolean playerJoinsLeague(League league, Player player) {
if (isPlayerInLeague(league, player))
return false;
int cost = league.getCost();
if (_collectionsManager.removeCurrencyFromPlayerCollection(player, new CollectionType("permanent", "My cards"), cost)) {
try {
_leagueParticipationDAO.userJoinsLeague(league, player);
Set<String> notParticipating = _playersNotParticipating.get(league);
if (notParticipating != null)
notParticipating.remove(player.getName());
Set<String> participating = _playersParticipating.get(league);
if (participating != null)
participating.add(player.getName());
league.getLeagueData().joinLeague(_collectionsManager, player, DateUtils.getCurrentDate());
return true;
} catch (SQLException exp) {
throw new RuntimeException("Unable to add user to league");
}
_leagueParticipationDAO.userJoinsLeague(league, player);
league.getLeagueData().joinLeague(_collectionsManager, player, DateUtils.getCurrentDate());
return true;
} else {
return false;
}

View File

@@ -62,7 +62,7 @@ public class DaoProvider implements InjectableProvider<Context, Type> {
private synchronized Injectable<LeagueParticipationDAO> getLeagueParticipationDaoSafely() {
if (_leagueParticipationDAOInjectable == null) {
final LeagueParticipationDAO leagueParticipationDAO = new LeagueParticipationDAO(_dbAccess);
final LeagueParticipationDAO leagueParticipationDAO = new DbLeagueParticipationDAO(_dbAccess);
_leagueParticipationDAOInjectable = new Injectable<LeagueParticipationDAO>() {
@Override
public LeagueParticipationDAO getValue() {