package onlinefrontlines.game; import java.sql.SQLException; import java.util.Collection; import onlinefrontlines.profiler.*; import onlinefrontlines.utils.Cache; import onlinefrontlines.utils.CacheException; import onlinefrontlines.utils.Tools; /** * This class serves as a cache for the database for GameState objects * * @author jorrit * * Copyright (C) 2009-2013 Jorrit Rouwe * * This file is part of Online Frontlines. * * Online Frontlines is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Online Frontlines is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Online Frontlines. If not, see <http://www.gnu.org/licenses/>. */ public final class GameStateCache { /** * Amount of time before game times out and is removed from memory */ public final static long TIME_OUT = 10 * 60 * 1000; /** * Singleton instance */ private final static GameStateCache instance = new GameStateCache(); /** * Get singleton instance */ public static GameStateCache getInstance() { return instance; } /** * Track amount of games in memory over time */ private final class CachedGamesTimeSeries implements TimeSeriesCallback { public double getValue() { return getValuesQuiet().size(); } } /** * Track amount of users in game over time */ private final class PlayerCountTimeSeries implements TimeSeriesCallback { public double getValue() { int count = 0; for (GameState g : getValuesQuiet()) { synchronized (g) { if (g.isPlayerConnected(Faction.f1)) ++count; if (g.isPlayerConnected(Faction.f2)) ++count; } } return count; } } /** * Register all profilers */ public void registerProfilers() { Profiler.getInstance().registerTimeSeries("Games in Memory", new CachedGamesTimeSeries()); Profiler.getInstance().registerTimeSeries("Players in Game", new PlayerCountTimeSeries()); } /** * Internal cache */ private Cache<Integer, GameState> internalCache = new Cache<Integer, GameState>("GameStateCache") { @Override protected GameState load(Integer id) throws Throwable { Sampler sampler = Profiler.getInstance().startSampler(Profiler.CATEGORY_GENERAL, "GameStateCache.load"); try { return GameStateDAO.load(id); } finally { sampler.stop(); } } }; /** * Get element from cache */ public GameState get(int id) throws SQLException, CacheException { // Check valid if (id == 0) return null; // Return game return internalCache.get(id); } /** * Put element in cache */ public void put(int id, GameState gameState) { internalCache.put(id, gameState); } /** * Get all objects in the cache */ public Collection<GameState> getValuesQuiet() { return internalCache.getValuesQuiet(); } /** * Write all pending changes to the db */ public void updateDbAll() { for (GameState gameState : getValuesQuiet()) synchronized (gameState) { try { gameState.updateDb(); } catch (SQLException e) { Tools.logException(e); } } } }