Caching league match data.

This commit is contained in:
marcins78@gmail.com
2012-04-19 11:02:45 +00:00
parent e289ac8ee7
commit f8e867a1fc
6 changed files with 110 additions and 69 deletions

View File

@@ -0,0 +1,34 @@
package com.gempukku.lotro.cache;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Guarantees that only one instance of the object will exists, via a synchronized double-check.
*
* @param <T>
* @param <U>
*/
public class ExpireObjectCache<T, U> {
private Map<T, U> _cachedObjects = new ConcurrentHashMap<T, U>();
public U getCachedObject(T key, Producable<T, U> producable) {
U result = _cachedObjects.get(key);
if (result != null)
return result;
synchronized (this) {
result = _cachedObjects.get(key);
if (result != null)
return result;
result = producable.produce(key);
_cachedObjects.put(key, result);
return result;
}
}
public synchronized void clearCache() {
_cachedObjects.clear();
}
}

View File

@@ -0,0 +1,5 @@
package com.gempukku.lotro.cache;
public interface Producable<T, U> {
public U produce(T key);
}

View File

@@ -41,21 +41,20 @@ public class LeagueDAO {
public List<League> loadActiveLeagues(int currentTime) throws SQLException, IOException { public List<League> loadActiveLeagues(int currentTime) throws SQLException, IOException {
Connection conn = _dbAccess.getDataSource().getConnection(); Connection conn = _dbAccess.getDataSource().getConnection();
try { try {
PreparedStatement statement = conn.prepareStatement("select id, name, type, class, parameters, status, cost from league where end>=? order by start desc"); PreparedStatement statement = conn.prepareStatement("select name, type, class, parameters, status, cost from league where end>=? order by start desc");
try { try {
statement.setInt(1, currentTime); statement.setInt(1, currentTime);
ResultSet rs = statement.executeQuery(); ResultSet rs = statement.executeQuery();
try { try {
List<League> activeLeagues = new ArrayList<League>(); List<League> activeLeagues = new ArrayList<League>();
while (rs.next()) { while (rs.next()) {
int id = rs.getInt(1); String name = rs.getString(1);
String name = rs.getString(2); String type = rs.getString(2);
String type = rs.getString(3); String clazz = rs.getString(3);
String clazz = rs.getString(4); String parameters = rs.getString(4);
String parameters = rs.getString(5); int status = rs.getInt(5);
int status = rs.getInt(6); int cost = rs.getInt(6);
int cost = rs.getInt(7); activeLeagues.add(new League(cost, name, type, clazz, parameters, status));
activeLeagues.add(new League(id, cost, name, type, clazz, parameters, status));
} }
return activeLeagues; return activeLeagues;
} finally { } finally {
@@ -73,12 +72,12 @@ public class LeagueDAO {
try { try {
Connection connection = _dbAccess.getDataSource().getConnection(); Connection connection = _dbAccess.getDataSource().getConnection();
try { try {
String sql = "update league set status=? where id=?"; String sql = "update league set status=? where type=?";
PreparedStatement statement = connection.prepareStatement(sql); PreparedStatement statement = connection.prepareStatement(sql);
try { try {
statement.setInt(1, newStatus); statement.setInt(1, newStatus);
statement.setInt(2, league.getId()); statement.setString(2, league.getType());
statement.execute(); statement.execute();
} finally { } finally {
statement.close(); statement.close();

View File

@@ -8,7 +8,9 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class LeagueMatchDAO { public class LeagueMatchDAO {
private DbAccess _dbAccess; private DbAccess _dbAccess;
@@ -80,41 +82,7 @@ public class LeagueMatchDAO {
} }
} }
public Collection<LeagueMatch> getPlayerMatchesPlayedOn(League league, LeagueSerieData leagueSeason, String player) { public void addPlayedMatch(League league, LeagueSerieData leagueSeason, LeagueMatch match) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("select winner, loser from league_match where league_type=? and season_type=? and (winner=? or loser=?)");
try {
statement.setString(1, league.getType());
statement.setString(2, leagueSeason.getName());
statement.setString(3, player);
statement.setString(4, player);
ResultSet rs = statement.executeQuery();
try {
Set<LeagueMatch> result = new HashSet<LeagueMatch>();
while (rs.next()) {
String winner = rs.getString(1);
String loser = rs.getString(2);
result.add(new LeagueMatch(winner, loser));
}
return result;
} finally {
rs.close();
}
} finally {
statement.close();
}
} finally {
conn.close();
}
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
}
public void addPlayedMatch(League league, LeagueSerieData leagueSeason, String winner, String loser) {
try { try {
Connection conn = _dbAccess.getDataSource().getConnection(); Connection conn = _dbAccess.getDataSource().getConnection();
try { try {
@@ -122,8 +90,8 @@ public class LeagueMatchDAO {
try { try {
statement.setString(1, league.getType()); statement.setString(1, league.getType());
statement.setString(2, leagueSeason.getName()); statement.setString(2, leagueSeason.getName());
statement.setString(3, winner); statement.setString(3, match.getWinner());
statement.setString(4, loser); statement.setString(4, match.getLoser());
statement.execute(); statement.execute();
} finally { } finally {
statement.close(); statement.close();
@@ -135,9 +103,4 @@ public class LeagueMatchDAO {
throw new RuntimeException(exp); throw new RuntimeException(exp);
} }
} }
private int getCurrentDate() {
Calendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
return date.get(Calendar.YEAR) * 10000 + (date.get(Calendar.MONTH) + 1) * 100 + date.get(Calendar.DAY_OF_MONTH);
}
} }

View File

@@ -5,7 +5,6 @@ import com.gempukku.lotro.league.LeagueData;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
public class League { public class League {
private int _id;
private int _cost; private int _cost;
private String _name; private String _name;
private String _type; private String _type;
@@ -13,8 +12,7 @@ public class League {
private String _parameters; private String _parameters;
private int _status; private int _status;
public League(int id, int cost, String name, String type, String clazz, String parameters, int status) { public League(int cost, String name, String type, String clazz, String parameters, int status) {
_id = id;
_cost = cost; _cost = cost;
_name = name; _name = name;
_type = type; _type = type;
@@ -23,10 +21,6 @@ public class League {
_status = status; _status = status;
} }
public int getId() {
return _id;
}
public int getCost() { public int getCost() {
return _cost; return _cost;
} }
@@ -60,13 +54,13 @@ public class League {
League league = (League) o; League league = (League) o;
if (_id != league._id) return false; if (_type != null ? !_type.equals(league._type) : league._type != null) return false;
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return _id; return _type != null ? _type.hashCode() : 0;
} }
} }

View File

@@ -1,6 +1,8 @@
package com.gempukku.lotro.league; package com.gempukku.lotro.league;
import com.gempukku.lotro.DateUtils; import com.gempukku.lotro.DateUtils;
import com.gempukku.lotro.cache.ExpireObjectCache;
import com.gempukku.lotro.cache.Producable;
import com.gempukku.lotro.collection.CollectionsManager; import com.gempukku.lotro.collection.CollectionsManager;
import com.gempukku.lotro.db.LeagueDAO; import com.gempukku.lotro.db.LeagueDAO;
import com.gempukku.lotro.db.LeagueMatchDAO; import com.gempukku.lotro.db.LeagueMatchDAO;
@@ -18,6 +20,7 @@ import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
public class LeagueService { public class LeagueService {
private Comparator<LeagueStanding> LEAGUE_STANDING_COMPARATOR = private Comparator<LeagueStanding> LEAGUE_STANDING_COMPARATOR =
@@ -38,6 +41,9 @@ public class LeagueService {
private Map<League, Set<String>> _playersParticipating = new ConcurrentHashMap<League, Set<String>>(); private Map<League, Set<String>> _playersParticipating = new ConcurrentHashMap<League, Set<String>>();
private Map<League, Set<String>> _playersNotParticipating = new ConcurrentHashMap<League, Set<String>>(); private Map<League, Set<String>> _playersNotParticipating = new ConcurrentHashMap<League, Set<String>>();
private ExpireObjectCache<League, Collection<LeagueMatch>> _cachedLeagueMatches = new ExpireObjectCache<League, Collection<LeagueMatch>>();
private ExpireObjectCache<LeagueSerieData, Collection<LeagueMatch>> _cachedSerieMatches = new ExpireObjectCache<LeagueSerieData, Collection<LeagueMatch>>();
private int _activeLeaguesLoadedDate; private int _activeLeaguesLoadedDate;
private List<League> _activeLeagues; private List<League> _activeLeagues;
@@ -59,6 +65,8 @@ public class LeagueService {
private synchronized void ensureLoadedCurrentLeagues() { private synchronized void ensureLoadedCurrentLeagues() {
int currentDate = DateUtils.getCurrentDate(); int currentDate = DateUtils.getCurrentDate();
if (currentDate != _activeLeaguesLoadedDate) { if (currentDate != _activeLeaguesLoadedDate) {
_cachedLeagueMatches.clearCache();
try { try {
_activeLeagues = _leagueDao.loadActiveLeagues(currentDate); _activeLeagues = _leagueDao.loadActiveLeagues(currentDate);
_activeLeaguesLoadedDate = currentDate; _activeLeaguesLoadedDate = currentDate;
@@ -71,6 +79,26 @@ public class LeagueService {
} }
} }
private Collection<LeagueMatch> getLeagueMatches(final League league) {
return _cachedLeagueMatches.getCachedObject(league,
new Producable<League, Collection<LeagueMatch>>() {
@Override
public Collection<LeagueMatch> produce(League key) {
return new CopyOnWriteArraySet<LeagueMatch>(_leagueMatchDao.getLeagueMatches(league));
}
});
}
private Collection<LeagueMatch> getLeagueSerieMatches(final League league, final LeagueSerieData serie) {
return _cachedSerieMatches.getCachedObject(serie,
new Producable<LeagueSerieData, Collection<LeagueMatch>>() {
@Override
public Collection<LeagueMatch> produce(LeagueSerieData key) {
return new CopyOnWriteArraySet<LeagueMatch>(_leagueMatchDao.getLeagueSerieMatches(league, serie));
}
});
}
public List<League> getActiveLeagues() { public List<League> getActiveLeagues() {
if (DateUtils.getCurrentDate() == _activeLeaguesLoadedDate) if (DateUtils.getCurrentDate() == _activeLeaguesLoadedDate)
return Collections.unmodifiableList(_activeLeagues); return Collections.unmodifiableList(_activeLeagues);
@@ -174,7 +202,8 @@ public class LeagueService {
} }
public void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) { public void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) {
_leagueMatchDao.addPlayedMatch(league, serie, winner, loser); addMatch(league, serie, winner, loser);
_leaguePointsDao.addPoints(league, serie, winner, 2); _leaguePointsDao.addPoints(league, serie, winner, 2);
_leaguePointsDao.addPoints(league, serie, loser, 1); _leaguePointsDao.addPoints(league, serie, loser, 1);
_leagueStandings.remove(league); _leagueStandings.remove(league);
@@ -184,9 +213,16 @@ public class LeagueService {
awardPrizesToPlayer(league, serie, loser, false); awardPrizesToPlayer(league, serie, loser, false);
} }
private void addMatch(League league, LeagueSerieData serie, String winner, String loser) {
LeagueMatch match = new LeagueMatch(winner, loser);
_leagueMatchDao.addPlayedMatch(league, serie, match);
getLeagueMatches(league).add(match);
getLeagueSerieMatches(league, serie).add(match);
}
private void awardPrizesToPlayer(League league, LeagueSerieData serie, String player, boolean winner) { private void awardPrizesToPlayer(League league, LeagueSerieData serie, String player, boolean winner) {
int count = 0; int count = 0;
Collection<LeagueMatch> playerMatchesPlayedOn = _leagueMatchDao.getPlayerMatchesPlayedOn(league, serie, player); Collection<LeagueMatch> playerMatchesPlayedOn = getPlayerMatchesInSerie(league, serie, player);
for (LeagueMatch leagueMatch : playerMatchesPlayedOn) { for (LeagueMatch leagueMatch : playerMatchesPlayedOn) {
if (leagueMatch.getWinner().equals(player)) if (leagueMatch.getWinner().equals(player))
count++; count++;
@@ -201,6 +237,16 @@ public class LeagueService {
_collectionsManager.addItemsToPlayerCollection(player, new CollectionType("permanent", "My cards"), prize.getAll()); _collectionsManager.addItemsToPlayerCollection(player, new CollectionType("permanent", "My cards"), prize.getAll());
} }
private Collection<LeagueMatch> getPlayerMatchesInSerie(League league, LeagueSerieData serie, String player) {
final Collection<LeagueMatch> allMatches = getLeagueSerieMatches(league, serie);
Set<LeagueMatch> result = new HashSet<LeagueMatch>();
for (LeagueMatch match : allMatches) {
if (match.getWinner().equals(player) || match.getLoser().equals(player))
result.add(match);
}
return result;
}
public List<LeagueStanding> getLeagueStandings(League league) { public List<LeagueStanding> getLeagueStandings(League league) {
List<LeagueStanding> leagueStandings = _leagueStandings.get(league); List<LeagueStanding> leagueStandings = _leagueStandings.get(league);
if (leagueStandings == null) { if (leagueStandings == null) {
@@ -225,14 +271,14 @@ public class LeagueService {
private List<LeagueStanding> createLeagueSerieStandings(League league, LeagueSerieData leagueSerie) { private List<LeagueStanding> createLeagueSerieStandings(League league, LeagueSerieData leagueSerie) {
final Map<String, LeaguePointsDAO.Points> points = _leaguePointsDao.getLeagueSeriePoints(league, leagueSerie); final Map<String, LeaguePointsDAO.Points> points = _leaguePointsDao.getLeagueSeriePoints(league, leagueSerie);
final Collection<LeagueMatch> matches = _leagueMatchDao.getLeagueSerieMatches(league, leagueSerie); final Collection<LeagueMatch> matches = getLeagueSerieMatches(league, leagueSerie);
return createStandingsForMatchesAndPoints(points, matches); return createStandingsForMatchesAndPoints(points, matches);
} }
private List<LeagueStanding> createLeagueStandings(League league) { private List<LeagueStanding> createLeagueStandings(League league) {
final Map<String, LeaguePointsDAO.Points> points = _leaguePointsDao.getLeaguePoints(league); final Map<String, LeaguePointsDAO.Points> points = _leaguePointsDao.getLeaguePoints(league);
final Collection<LeagueMatch> matches = _leagueMatchDao.getLeagueMatches(league); final Collection<LeagueMatch> matches = getLeagueMatches(league);
return createStandingsForMatchesAndPoints(points, matches); return createStandingsForMatchesAndPoints(points, matches);
} }
@@ -304,14 +350,14 @@ public class LeagueService {
public boolean canPlayRankedGame(League league, LeagueSerieData season, String player) { public boolean canPlayRankedGame(League league, LeagueSerieData season, String player) {
int maxMatches = season.getMaxMatches(); int maxMatches = season.getMaxMatches();
Collection<LeagueMatch> playedInSeason = _leagueMatchDao.getPlayerMatchesPlayedOn(league, season, player); Collection<LeagueMatch> playedInSeason = getPlayerMatchesInSerie(league, season, player);
if (playedInSeason.size() >= maxMatches) if (playedInSeason.size() >= maxMatches)
return false; return false;
return true; return true;
} }
public boolean canPlayRankedGame(League league, LeagueSerieData season, String playerOne, String playerTwo) { public boolean canPlayRankedGame(League league, LeagueSerieData season, String playerOne, String playerTwo) {
Collection<LeagueMatch> playedInSeason = _leagueMatchDao.getPlayerMatchesPlayedOn(league, season, playerOne); Collection<LeagueMatch> playedInSeason = getPlayerMatchesInSerie(league, season, playerOne);
for (LeagueMatch leagueMatch : playedInSeason) { for (LeagueMatch leagueMatch : playedInSeason) {
if (playerTwo.equals(leagueMatch.getWinner()) || playerTwo.equals(leagueMatch.getLoser())) if (playerTwo.equals(leagueMatch.getWinner()) || playerTwo.equals(leagueMatch.getLoser()))
return false; return false;