Removed UserData "dataCache" Map from DataCacheHandler

Removed Clear, Save & Get Queues.
Renamed DataCacheHandler to DataCache
Moved Process queue & Renamed to ProcessingQueue
This commit is contained in:
Rsl1122 2017-08-21 19:58:49 +03:00
parent 67df66cc31
commit bc7df57c40
29 changed files with 392 additions and 1096 deletions

View File

@ -30,7 +30,7 @@ import main.java.com.djrapitops.plan.command.PlanCommand;
import main.java.com.djrapitops.plan.command.commands.RegisterCommandFilter;
import main.java.com.djrapitops.plan.data.additional.HookHandler;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler;
import main.java.com.djrapitops.plan.data.cache.PageCacheHandler;
import main.java.com.djrapitops.plan.data.listeners.*;
@ -40,6 +40,8 @@ import main.java.com.djrapitops.plan.database.databases.MySQLDB;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.queue.processing.ProcessingQueue;
import main.java.com.djrapitops.plan.queue.processing.Processor;
import main.java.com.djrapitops.plan.ui.webserver.WebServer;
import main.java.com.djrapitops.plan.ui.webserver.api.bukkit.*;
import main.java.com.djrapitops.plan.utilities.Benchmark;
@ -67,7 +69,8 @@ public class Plan extends BukkitPlugin<Plan> {
private API api;
private DataCacheHandler handler;
private ProcessingQueue processingQueue;
private DataCache handler;
private InspectCacheHandler inspectCache;
private AnalysisCacheHandler analysisCache;
private HookHandler hookHandler; // Manages 3rd party data sources
@ -141,6 +144,8 @@ public class Plan extends BukkitPlugin<Plan> {
saveConfig();
Benchmark.stop("Enable", "Copy default config");
processingQueue = new ProcessingQueue();
Benchmark.start("Init Database");
Log.info(Locale.get(Msg.ENABLE_DB_INIT).toString());
if (Check.errorIfFalse(initDatabase(), Locale.get(Msg.ENABLE_DB_FAIL_DISABLE_INFO).toString())) {
@ -152,7 +157,7 @@ public class Plan extends BukkitPlugin<Plan> {
Benchmark.stop("Enable", "Init Database");
Benchmark.start("Init DataCache");
this.handler = new DataCacheHandler(this);
this.handler = new DataCache(this);
this.inspectCache = new InspectCacheHandler(this);
this.analysisCache = new AnalysisCacheHandler(this);
Benchmark.stop("Enable", "Init DataCache");
@ -161,9 +166,6 @@ public class Plan extends BukkitPlugin<Plan> {
registerListeners();
this.api = new API(this);
Benchmark.start("Handle Reload");
handler.handleReload();
Benchmark.stop("Enable", "Handle Reload");
Benchmark.start("Analysis refresh task registration");
// Analysis refresh settings
@ -392,9 +394,9 @@ public class Plan extends BukkitPlugin<Plan> {
/**
* Used to access Cache.
*
* @return Current instance of the DataCacheHandler
* @return Current instance of the DataCache
*/
public DataCacheHandler getHandler() {
public DataCache getHandler() {
return handler;
}
@ -455,4 +457,12 @@ public class Plan extends BukkitPlugin<Plan> {
public ServerVariableHolder getVariable() {
return serverVariableHolder;
}
public ProcessingQueue getProcessingQueue() {
return processingQueue;
}
public void addToProcessQueue(Processor processor) {
processingQueue.addToQueue(processor);
}
}

View File

@ -95,57 +95,6 @@ public class API {
return HtmlUtils.getInspectUrlWithProtocol(name);
}
/**
* Schedule a UserData object to be fetched from the database or cache if
* the player is online.
* <p>
* The data will not be cached if it is not already cached.
*
* @param uuid UUID of the player.
* @param processor Object implementing DBCallableProcessor, which
* process (UserData data) method will be called.
*/
@Deprecated
public void scheduleForGet(UUID uuid, DBCallableProcessor processor) {
plugin.getHandler().getUserDataForProcessing(processor, uuid, false);
}
/**
* Schedule a HandlingInfo object to be processed.
* <p>
* UserData associated with the UUID of the HandlingInfo object will be
* cached.
*
* @param info object that extends HandlingInfo.
*/
@Deprecated
public void scheduleEventHandlingInfo(HandlingInfo info) {
plugin.getHandler().addToPool(info);
}
/**
* Used to cache a UserData object.
* <p>
* If data is already cached it will be overridden.
*
* @param data UserData object. Will be placed to the data.getUuid() key in
* the cache.
*/
@Deprecated
public void placeDataToCache(UserData data) {
plugin.getHandler().cache(data);
}
/**
* Used to save the cached data to the database.
* <p>
* Should be only called from an Asynchronous thread.
*/
@Deprecated
public void saveCachedData() {
plugin.getHandler().saveCachedUserData();
}
/**
* Check if the UserData is cached to the InspectCache.
*

View File

@ -82,7 +82,7 @@ public class ManageClearCommand extends SubCommand {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
if (database.removeAllData()) {
plugin.getHandler().getDataCache().clear();
// TODO Clear active session of all users & start new ones
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_CLEAR_SUCCESS).toString());
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());

View File

@ -84,7 +84,7 @@ public class ManageRemoveCommand extends SubCommand {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
try {
plugin.getHandler().getDataCache().remove(uuid);
// TODO Clear active session of user & start new one
if (plugin.getDB().removeAccount(uuid.toString())) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_REMOVE_SUCCESS).parse(playerName, plugin.getDB().getConfigName()));
} else {

View File

@ -2,6 +2,9 @@ package main.java.com.djrapitops.plan.data;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import java.util.ArrayList;
import java.util.List;
/**
* This class is used for storing start and end of a play session inside UserData
* object.
@ -10,40 +13,48 @@ import main.java.com.djrapitops.plan.data.time.WorldTimes;
*/
public class SessionData {
private WorldTimes worldTimes; // TODO add World Times to SessionData
private final WorldTimes worldTimes; // TODO add World Times to SessionData
private final long sessionStart;
private long sessionEnd;
// TODO Add kills & deaths to SessionData
private final List<KillData> playerKills;
private int mobKills;
private int deaths;
@Deprecated // TODO Remove
public SessionData(long sessionStart) {
worldTimes = null;
this.sessionStart = 0;
playerKills = null;
}
/**
* Creates a new session with given start and end of -1.
*
* @param sessionStart Epoch millisecond the session was started.
*/
public SessionData(long sessionStart) {
public SessionData(long sessionStart, String world, String gm) {
this.worldTimes = new WorldTimes(world, gm);
this.sessionStart = sessionStart;
this.sessionEnd = -1;
playerKills = new ArrayList<>();
mobKills = 0;
deaths = 0;
}
/**
* Creates a new session with given start and end.
* Re-Creates a session data object for viewing.
*
* @param sessionStart Epoch millisecond the session was started.
* @param sessionEnd Epoch millisecond the session ended.
*/
public SessionData(long sessionStart, long sessionEnd) {
public SessionData(long sessionStart, long sessionEnd, WorldTimes worldTimes, List<KillData> playerKills, int mobKills, int deaths) {
this.sessionStart = sessionStart;
this.sessionEnd = sessionEnd;
}
/**
* Constructor for copying the object.
*
* @param s SessionData to copy.
*/
public SessionData(SessionData s) {
this.sessionStart = s.getSessionStart();
this.sessionEnd = s.getSessionEnd();
this.worldTimes = worldTimes;
this.playerKills = playerKills;
this.mobKills = mobKills;
this.deaths = deaths;
}
/**
@ -55,6 +66,16 @@ public class SessionData {
*/
public void endSession(long endOfSession) {
sessionEnd = endOfSession;
worldTimes.updateState(endOfSession);
}
/**
* Get the length of the session in milliseconds.
*
* @return Long in ms.
*/
public long getLength() {
return sessionEnd - sessionStart;
}
/**
@ -75,25 +96,12 @@ public class SessionData {
return sessionEnd;
}
/**
* Get the length of the session in milliseconds.
*
* @return Long in ms.
*/
public long getLength() {
return sessionEnd - sessionStart;
}
@Override
public String toString() {
return "s:" + sessionStart + " e:" + sessionEnd;
}
/**
* Check if the session start was before the end.
*
* @return Is the length positive?
*/
@Deprecated // TODO Remove
public boolean isValid() {
return sessionStart <= sessionEnd;
}

View File

@ -247,6 +247,7 @@ public class UserData {
*
* @param session SessionData object
*/
@Deprecated
public void addSession(SessionData session) {
if (Verify.notNull(session) && session.isValid()) {
sessions.add(session);

View File

@ -0,0 +1,232 @@
package main.java.com.djrapitops.plan.data.cache;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.queue.processing.Processor;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import org.bukkit.entity.Player;
import java.sql.SQLException;
import java.util.*;
/**
* This Class contains the Cache.
* <p>
* It is used to store command use, active sessions and Unsaved TPS objects
* objects in memory.
* <p>
* Its methods can be used to access all the data it stores and to clear them.
*
* @author Rsl1122
* @since 2.0.0
*/
public class DataCache extends SessionCache {
// Plan
private final Plan plugin;
private final Database db;
//Cache
private Map<String, Integer> commandUse;
private List<List<TPS>> unsavedTPSHistory;
// Queues
// Variables
private boolean periodicTaskIsSaving = false;
/**
* Class Constructor.
* <p>
* Gets the Database from the plugin. Starts the queues. Registers
* Asynchronous Periodic Save Task
*
* @param plugin Current instance of Plan
*/
public DataCache(Plan plugin) {
super(); // Initializes Session & Location cache.
this.plugin = plugin;
db = plugin.getDB();
commandUse = new HashMap<>();
if (!getCommandUseFromDb()) {
Log.error(Locale.get(Msg.ENABLE_DB_FAIL_DISABLE_INFO).toString());
plugin.disablePlugin();
return;
}
unsavedTPSHistory = new ArrayList<>();
startAsyncPeriodicSaveTask();
}
/**
* Used to get the initial commandUse Map from the database.
*
* @return Was the fetch successful?
*/
public boolean getCommandUseFromDb() {
try {
commandUse = db.getCommandUse();
return true;
} catch (Exception e) {
Log.toLog(this.getClass().getName(), e);
}
return false;
}
/**
* Used to start the Asynchronous Save Task.
*
* @throws IllegalArgumentException BukkitRunnable was given wrong
* parameters.
* @throws IllegalStateException BukkitScheduler is in a wrong state.
*/
public void startAsyncPeriodicSaveTask() {
DataCache handler = this;
plugin.getRunnableFactory().createNew(new AbsRunnable("PeriodicCacheSaveTask") {
private int timesSaved = 0;
@Override
public void run() {
if (periodicTaskIsSaving) {
return;
}
try {
periodicTaskIsSaving = true;
Log.debug("Database", "Periodic Cache Save");
saveCommandUse();
saveUnsavedTPSHistory();
timesSaved++;
} catch (Exception e) {
Log.toLog(this.getClass().getName() + "(" + this.getName() + ")", e);
} finally {
periodicTaskIsSaving = false;
}
}
}).runTaskTimerAsynchronously(60L * 20L * 5, 60L * 20L * 5);
}
/**
* Saves all data in the cache to Database and closes the database down.
* <p>
* Stops all tasks.
* <p>
* If processingQueue has unprocessed information, it will be processed.
*/
@Deprecated
public void saveCacheOnDisable() { // TODO Rewrite
long time = MiscUtils.getTime();
Benchmark.start("Cache: SaveOnDisable");
Benchmark.start("Cache: ProcessOnlineHandlingInfo");
List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
Log.debug("Online: " + onlinePlayers.size());
for (IPlayer p : onlinePlayers) {
UUID uuid = p.getUuid();
endSession(uuid);
String worldName = ((Player) p.getWrappedPlayerClass()).getWorld().getName();
}
// toProcess.sort(new HandlingInfoTimeComparator());
Benchmark.stop("Cache: ProcessOnlineHandlingInfo");
try {
db.saveCommandUse(commandUse);
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
saveUnsavedTPSHistory();
try {
db.close();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
Benchmark.stop("Cache: SaveOnDisable");
}
private void processUnprocessedHandlingInfo(List<Processor> toProcess) {
Log.debug("PROCESS: " + toProcess.size());
for (Processor i : toProcess) {
i.process();
}
}
/**
* Saves the cached CommandUse.
* <p>
* Should be only called from an Asynchronous Thread.
*/
public void saveCommandUse() {
try {
db.saveCommandUse(new HashMap<>(commandUse));
} catch (SQLException | NullPointerException e) {
Log.toLog(this.getClass().getName(), e);
}
}
public void saveUnsavedTPSHistory() {
List<TPS> averages = calculateAverageTpsForEachMinute();
if (averages.isEmpty()) {
return;
}
try {
Log.debug("Database", "Periodic TPS Save: " + averages.size());
db.getTpsTable().saveTPSData(averages);
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
private List<TPS> calculateAverageTpsForEachMinute() {
final List<TPS> averages = new ArrayList<>();
if (unsavedTPSHistory.isEmpty()) {
return new ArrayList<>();
}
List<List<TPS>> copy = new ArrayList<>(unsavedTPSHistory);
for (List<TPS> history : copy) {
final long lastDate = history.get(history.size() - 1).getDate();
final double averageTPS = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getTicksPerSecond)));
final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(TPS::getPlayers));
final double averageCPUUsage = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getCPUUsage)));
final long averageUsedMemory = MathUtils.averageLong(history.stream().map(TPS::getUsedMemory));
final int averageEntityCount = (int) MathUtils.averageInt(history.stream().map(TPS::getEntityCount));
final int averageChunksLoaded = (int) MathUtils.averageInt(history.stream().map(TPS::getChunksLoaded));
averages.add(new TPS(lastDate, averageTPS, averagePlayersOnline, averageCPUUsage, averageUsedMemory, averageEntityCount, averageChunksLoaded));
}
unsavedTPSHistory.removeAll(copy);
return averages;
}
/**
* Used to get the cached commandUse.
*
* @return Map with key:value - "/command":4
*/
public Map<String, Integer> getCommandUse() {
return commandUse;
}
/**
* Used to handle a command's execution.
*
* @param command "/command"
*/
public void handleCommand(String command) {
int amount = commandUse.getOrDefault(command, 0);
commandUse.put(command, amount + 1);
}
public void addTPSLastMinute(List<TPS> history) {
// Copy the contents to avoid reference, thus making the whole calculation pointless.
unsavedTPSHistory.add(new ArrayList<>(history));
}
}

View File

@ -1,531 +0,0 @@
package main.java.com.djrapitops.plan.data.cache;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.data.handling.info.LogoutInfo;
import main.java.com.djrapitops.plan.data.handling.info.ReloadInfo;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.queue.DataCacheClearQueue;
import main.java.com.djrapitops.plan.queue.DataCacheGetQueue;
import main.java.com.djrapitops.plan.queue.DataCacheProcessQueue;
import main.java.com.djrapitops.plan.queue.DataCacheSaveQueue;
import main.java.com.djrapitops.plan.queue.processing.Processor;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import org.bukkit.entity.Player;
import java.sql.SQLException;
import java.util.*;
/**
* This Class contains the Cache.
* <p>
* This class is the main processing class that initialises Save, Clear, Process
* and Get queue and Starts the asynchronous save task.
* <p>
* It is used to store command use, locations, active sessions and UserData
* objects in memory.
* <p>
* Its methods can be used to access all the data it stores and to clear them.
*
* @author Rsl1122
* @since 2.0.0
*/
public class DataCacheHandler extends SessionCache {
// Cache
private final Map<UUID, UserData> dataCache;
// Plan
private final Plan plugin;
private final Database db;
//Cache
private Map<String, Integer> commandUse;
private List<List<TPS>> unsavedTPSHistory;
// Queues
private DataCacheSaveQueue saveTask;
private DataCacheClearQueue clearTask;
private DataCacheProcessQueue processTask;
private DataCacheGetQueue getTask;
// Variables
private boolean periodicTaskIsSaving = false;
/**
* Class Constructor.
* <p>
* Gets the Database from the plugin. Starts the queues. Registers
* Asynchronous Periodic Save Task
*
* @param plugin Current instance of Plan
*/
public DataCacheHandler(Plan plugin) {
super(); // Initializes Session & Location cache.
this.plugin = plugin;
db = plugin.getDB();
dataCache = new HashMap<>();
startQueues();
commandUse = new HashMap<>();
if (!getCommandUseFromDb()) {
Log.error(Locale.get(Msg.ENABLE_DB_FAIL_DISABLE_INFO).toString());
plugin.disablePlugin();
return;
}
unsavedTPSHistory = new ArrayList<>();
startAsyncPeriodicSaveTask();
}
/**
* Used to get the initial commandUse Map from the database.
*
* @return Was the fetch successful?
*/
public boolean getCommandUseFromDb() {
try {
commandUse = db.getCommandUse();
return true;
} catch (Exception e) {
Log.toLog(this.getClass().getName(), e);
}
return false;
}
/**
* Used to start all processing Queue Threads.
*/
public void startQueues() {
getTask = new DataCacheGetQueue(plugin);
processTask = new DataCacheProcessQueue();
clearTask = new DataCacheClearQueue(this);
saveTask = new DataCacheSaveQueue(plugin, this);
}
/**
* Used to start the Asynchronous Save Task.
*
* @throws IllegalArgumentException BukkitRunnable was given wrong
* parameters.
* @throws IllegalStateException BukkitScheduler is in a wrong state.
*/
public void startAsyncPeriodicSaveTask() {
DataCacheHandler handler = this;
plugin.getRunnableFactory().createNew(new AbsRunnable("PeriodicCacheSaveTask") {
private int timesSaved = 0;
@Override
public void run() {
if (periodicTaskIsSaving) {
return;
}
try {
periodicTaskIsSaving = true;
Log.debug("Database", "Periodic Cache Save: " + dataCache.size());
handler.saveHandlerDataToCache();
handler.saveCachedUserData();
saveCommandUse();
saveUnsavedTPSHistory();
timesSaved++;
} catch (Exception e) {
Log.toLog(this.getClass().getName() + "(" + this.getName() + ")", e);
} finally {
periodicTaskIsSaving = false;
}
}
}).runTaskTimerAsynchronously(60L * 20L * 5, 60L * 20L * 5);
}
/**
* Uses Database or Cache to retrieve the UserData of a matching player.
* <p>
* Caches the data to the Cache if cache-parameter is true.
*
* @param processor DBCallableProcessor Object used to process the data
* after it was retrieved
* @param uuid Player's UUID
* @param cache Whether or not the UserData will be Cached in this instance
* of DataCacheHandler after it has been fetched (if not already fetched)
*/
public void getUserDataForProcessing(DBCallableProcessor processor, UUID uuid, boolean cache) {
UserData uData = dataCache.get(uuid);
if (uData == null) {
if (cache) {
DBCallableProcessor cacher = this::cache;
getTask.scheduleForGet(uuid, cacher, processor);
} else {
getTask.scheduleForGet(uuid, processor);
}
} else {
processor.process(uData);
}
}
/**
* Used to Cache a UserData object to the Cache.
* <p>
* If a object already exists it will be replaced.
*
* @param data UserData object with the UUID inside used as key.
*/
public void cache(UserData data) {
data.setOnline(true);
dataCache.put(data.getUuid(), data);
Log.debug("Added " + data.getUuid().toString() + " to Cache.");
}
/**
* Uses Database or Cache to retrieve the UserData of a matching player.
* <p>
* Always Caches the data after retrieval (unless already cached)
*
* @param processor DBCallableProcessor Object used to process the data
* after it was retrieved
* @param uuid Player's UUID
*/
public void getUserDataForProcessing(DBCallableProcessor processor, UUID uuid) {
getUserDataForProcessing(processor, uuid, true);
}
/**
* Saves all UserData in the cache to Database.
* <p>
* Should only be called from Async thread
*/
public void saveCachedUserData() {
Set<UserData> data = new HashSet<>();
data.addAll(dataCache.values());
try {
db.saveMultipleUserData(data);
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
/**
* Used to add event HandlingInfo to the processTask's pool.
* <p>
* Given HandlingInfo object's process method will be called.
*
* @param i Object that extends HandlingInfo.
*/
@Deprecated
public void addToPool(HandlingInfo i) {
if (i == null) {
return;
}
processTask.addToQueue(i);
}
/**
* Saves all data in the cache to Database and closes the database down.
* <p>
* Stops all tasks.
* <p>
* If processTask has unprocessed information, it will be processed.
*/
public void saveCacheOnDisable() {
long time = MiscUtils.getTime();
Benchmark.start("Cache: SaveOnDisable");
saveTask.stop();
getTask.stop();
clearTask.stop();
List<Processor> toProcess = processTask.stopAndReturnLeftovers();
Benchmark.start("Cache: ProcessOnlineHandlingInfo");
Log.debug("ToProcess size: " + toProcess.size() + " DataCache size: " + dataCache.keySet().size());
List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
Log.debug("Online: " + onlinePlayers.size());
for (IPlayer p : onlinePlayers) {
UUID uuid = p.getUuid();
endSession(uuid);
String worldName = ((Player) p.getWrappedPlayerClass()).getWorld().getName();
toProcess.add(new LogoutInfo(uuid, time, p.isBanned(), p.getGamemode().name(), getSession(uuid), worldName));
}
Log.debug("ToProcess size_AFTER: " + toProcess.size() + " DataCache size: " + dataCache.keySet().size());
// toProcess.sort(new HandlingInfoTimeComparator());
processUnprocessedHandlingInfo(toProcess);
Benchmark.stop("Cache: ProcessOnlineHandlingInfo");
List<UserData> data = new ArrayList<>();
data.addAll(dataCache.values());
Log.debug("SAVING, DataCache size: " + dataCache.keySet().size());
try {
db.saveCommandUse(commandUse);
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
try {
db.saveMultipleUserData(data);
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
saveUnsavedTPSHistory();
try {
db.close();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
Benchmark.stop("Cache: SaveOnDisable");
}
private void processUnprocessedHandlingInfo(List<Processor> toProcess) {
Log.debug("PROCESS: " + toProcess.size());
for (Processor i : toProcess) {
i.process();
}
}
/**
* Saves the cached data of matching Player if it is in the cache.
*
* @param uuid Player's UUID
*/
public void saveCachedData(UUID uuid) {
DBCallableProcessor saveProcessor = data -> {
data.access();
data.setClearAfterSave(true);
saveTask.scheduleForSave(data);
};
getUserDataForProcessing(saveProcessor, uuid);
}
/**
* Saves the cached CommandUse.
* <p>
* Should be only called from an Asynchronous Thread.
*/
public void saveCommandUse() {
try {
db.saveCommandUse(new HashMap<>(commandUse));
} catch (SQLException | NullPointerException e) {
Log.toLog(this.getClass().getName(), e);
}
}
public void saveUnsavedTPSHistory() {
List<TPS> averages = calculateAverageTpsForEachMinute();
if (averages.isEmpty()) {
return;
}
try {
Log.debug("Database", "Periodic TPS Save: " + averages.size());
db.getTpsTable().saveTPSData(averages);
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
private List<TPS> calculateAverageTpsForEachMinute() {
final List<TPS> averages = new ArrayList<>();
if (unsavedTPSHistory.isEmpty()) {
return new ArrayList<>();
}
List<List<TPS>> copy = new ArrayList<>(unsavedTPSHistory);
for (List<TPS> history : copy) {
final long lastDate = history.get(history.size() - 1).getDate();
final double averageTPS = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getTicksPerSecond)));
final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(TPS::getPlayers));
final double averageCPUUsage = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getCPUUsage)));
final long averageUsedMemory = MathUtils.averageLong(history.stream().map(TPS::getUsedMemory));
final int averageEntityCount = (int) MathUtils.averageInt(history.stream().map(TPS::getEntityCount));
final int averageChunksLoaded = (int) MathUtils.averageInt(history.stream().map(TPS::getChunksLoaded));
averages.add(new TPS(lastDate, averageTPS, averagePlayersOnline, averageCPUUsage, averageUsedMemory, averageEntityCount, averageChunksLoaded));
}
unsavedTPSHistory.removeAll(copy);
return averages;
}
/**
* Refreshes the calculations for all online players with ReloadInfo.
*/
public void saveHandlerDataToCache() {
final List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
onlinePlayers.forEach(p -> saveHandlerDataToCache(p, false));
}
private void saveHandlerDataToCache(IPlayer p, boolean pool) {
long time = MiscUtils.getTime();
UUID uuid = p.getUuid();
String worldName = ((Player) p.getWrappedPlayerClass()).getWorld().getName();
ReloadInfo info = new ReloadInfo(uuid, time, p.getAddress().getAddress(), p.isBanned(), p.getDisplayName(), p.getGamemode().name(), worldName);
if (!pool) {
UserData data = dataCache.get(uuid);
if (data != null) {
info.process(data);
return;
}
}
addToPool(info);
}
/**
* Schedules all UserData from the Cache to be cleared.
*/
public void clearCache() {
clearTask.scheduleForClear(dataCache.keySet());
}
/**
* Clears the matching UserData from the Cache if they're not online.
*
* @param uuid Player's UUID
*/
public void clearFromCache(UUID uuid) {
if (plugin.fetch().isOnline(uuid)) {
UserData data = dataCache.get(uuid);
if (data != null) {
data.setClearAfterSave(false);
}
} else {
dataCache.remove(uuid);
Log.debug("Cleared " + uuid.toString() + " from Cache.");
}
}
/**
* Schedules a matching UserData object to be cleared from the cache.
*
* @param uuid Player's UUID.
*/
public void scheduldeForClear(UUID uuid) {
clearTask.scheduleForClear(uuid);
}
/**
* Check whether or not the UserData object is being accessed by save or
* process tasks.
*
* @param uuid Player's UUID
* @return true/false
*/
public boolean isDataAccessed(UUID uuid) {
UserData userData = dataCache.get(uuid);
if (userData == null) {
return false;
}
/*TODO boolean isAccessed = (userData.isAccessed()) || saveTask.containsUUID(uuid) || processTask.containsUUID(uuid);
if (isAccessed) {
userData.setClearAfterSave(false);
}
return isAccessed;*/
return true;
}
/**
* Creates a new UserData instance and saves it to the Database.
*
* @param player Player the new UserData is created for
*/
public void newPlayer(IPlayer player) {
newPlayer(NewPlayerCreator.createNewPlayer(player));
}
/**
* Schedules a new player's data to be saved to the Database.
*
* @param data UserData object to schedule for save.
*/
public void newPlayer(UserData data) {
saveTask.scheduleNewPlayer(data);
cache(data);
}
/**
* Used to get the contents of the cache.
*
* @return The Map containing all Cached UserData
*/
public Map<UUID, UserData> getDataCache() {
return dataCache;
}
/**
* Used to get the cached commandUse.
*
* @return Map with key:value - "/command":4
*/
public Map<String, Integer> getCommandUse() {
return commandUse;
}
/**
* If /reload is run this treats every online player as a new login.
* <p>
* Calls all the methods that are ran when PlayerJoinEvent is fired
*/
public void handleReload() {
plugin.getRunnableFactory().createNew(new AbsRunnable("ReloadCacheUpdateTask") {
@Override
public void run() {
final List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
for (IPlayer player : onlinePlayers) {
UUID uuid = player.getUuid();
boolean isNewPlayer = !db.wasSeenBefore(uuid);
if (isNewPlayer) {
newPlayer(player);
}
startSession(uuid);
saveHandlerDataToCache(player, true);
}
this.cancel();
}
}).runTaskAsynchronously();
}
/**
* Used to handle a command's execution.
*
* @param command "/command"
*/
public void handleCommand(String command) {
int amount = commandUse.getOrDefault(command, 0);
commandUse.put(command, amount + 1);
}
/**
* @return The SaveTask
*/
public DataCacheSaveQueue getSaveTask() {
return saveTask;
}
/**
* @return The ClearTask
*/
public DataCacheClearQueue getClearTask() {
return clearTask;
}
/**
* @return The ProcessTask
*/
public DataCacheProcessQueue getProcessTask() {
return processTask;
}
/**
* @return The GetTask
*/
public DataCacheGetQueue getGetTask() {
return getTask;
}
public void addTPSLastMinute(List<TPS> history) {
// Copy the contents to avoid reference, thus making the whole calculation pointless.
unsavedTPSHistory.add(new ArrayList<>(history));
}
}

View File

@ -23,7 +23,7 @@ import java.util.*;
@Deprecated
public class InspectCacheHandler {
private final DataCacheHandler handler;
private final DataCache handler;
private final Map<UUID, UserData> cache;
private final Map<UUID, Long> cacheTimes;
@ -46,6 +46,7 @@ public class InspectCacheHandler {
*
* @param uuid UUID of the player.
*/
@Deprecated // Does not cache anything anymore // TODO Remove
public void cache(UUID uuid) {
DBCallableProcessor cacher = data -> {
UserData userData = new UserData(data);
@ -62,8 +63,6 @@ public class InspectCacheHandler {
Log.toLog(this.getClass().getName(), e);
}
};
handler.getUserDataForProcessing(cacher, uuid, false);
}
/**
@ -74,18 +73,7 @@ public class InspectCacheHandler {
* @throws SQLException If Database is not properly enabled
*/
public void cacheAllUserData(Database db) throws SQLException {
Set<UUID> cachedUserData = handler.getDataCache().keySet();
for (UUID uuid : cachedUserData) {
cache(uuid);
}
Set<UUID> savedUUIDs = new HashSet<>();
try {
savedUUIDs = db.getUsersTable().getSavedUUIDs();
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
savedUUIDs.removeAll(cachedUserData);
List<UserData> userDataForUUIDS = db.getUserDataForUUIDS(savedUUIDs);
List<UserData> userDataForUUIDS = db.getUserDataForUUIDS(db.getUsersTable().getSavedUUIDs());
long time = MiscUtils.getTime();
for (UserData uData : userDataForUUIDS) {
UUID uuid = uData.getUuid();

View File

@ -2,7 +2,6 @@ package main.java.com.djrapitops.plan.data.cache;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.util.HashMap;
import java.util.Map;
@ -22,6 +21,18 @@ public class SessionCache {
* Class Constructor.
*/
public SessionCache() {
}
public void cacheSession(UUID uuid, SessionData session) {
activeSessions.put(uuid, session);
}
public void endSession(UUID uuid, long time) {
SessionData session = activeSessions.get(uuid);
if (session == null) {
return;
}
session.endSession(time);
}
@ -30,9 +41,8 @@ public class SessionCache {
*
* @param uuid UUID of the player.
*/
@Deprecated
public void startSession(UUID uuid) {
SessionData session = new SessionData(MiscUtils.getTime());
activeSessions.put(uuid, session);
}
/**
@ -40,11 +50,8 @@ public class SessionCache {
*
* @param uuid UUID of the player.
*/
@Deprecated
public void endSession(UUID uuid) {
SessionData currentSession = activeSessions.get(uuid);
if (currentSession != null) {
currentSession.endSession(MiscUtils.getTime());
}
}
/**
@ -53,6 +60,7 @@ public class SessionCache {
* @param uuid UUID of the player.
* @return SessionData or null if not cached.
*/
@Deprecated
public SessionData getSession(UUID uuid) {
return activeSessions.get(uuid);
}
@ -62,6 +70,7 @@ public class SessionCache {
*
* @param data UserData object a session should be added to.
*/
@Deprecated
public void addSession(UserData data) {
UUID uuid = data.getUuid();
SessionData currentSession = activeSessions.get(uuid);
@ -78,6 +87,7 @@ public class SessionCache {
*
* @return key:value UUID:SessionData
*/
@Deprecated
public Map<UUID, SessionData> getActiveSessions() {
return activeSessions;
}

View File

@ -5,7 +5,7 @@ import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.database.Database;
@ -51,7 +51,7 @@ public abstract class Importer {
plan.getAnalysisCache().disableAnalysisTemporarily();
String processName = "Import, " + getClass().getSimpleName();
try {
DataCacheHandler handler = plan.getHandler();
DataCache handler = plan.getHandler();
Database db = plan.getDB();
Benchmark.start(processName);
@ -103,7 +103,7 @@ public abstract class Importer {
plan.getDB().saveMultipleUserData(newUsers);
for (UUID uuid : uuids) {
handler.addToPool(importData(uuid, args));
Plan.getInstance().addToProcessQueue(importData(uuid, args));
}
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.queue.processing.Processor;
@ -14,6 +13,7 @@ import java.util.UUID;
* @author Rsl1122
* @since 3.0.0
*/
// TODO Rewrite all HandlingInfo objects to only extend Processor
public abstract class HandlingInfo extends Processor<UUID> implements DBCallableProcessor {
final UUID uuid;
@ -63,7 +63,6 @@ public abstract class HandlingInfo extends Processor<UUID> implements DBCallable
}
public void process() {
Plan.getInstance().getHandler().getUserDataForProcessing(this, uuid);
}
/**

View File

@ -1,7 +1,6 @@
package main.java.com.djrapitops.plan.data.listeners;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.ChatInfo;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -16,7 +15,7 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
*/
public class PlanChatListener implements Listener {
private final DataCacheHandler handler;
private Plan plugin;
/**
* Class Constructor.
@ -24,7 +23,7 @@ public class PlanChatListener implements Listener {
* @param plugin Current instance of Plan
*/
public PlanChatListener(Plan plugin) {
handler = plugin.getHandler();
this.plugin = plugin;
}
/**
@ -39,6 +38,6 @@ public class PlanChatListener implements Listener {
}
Player p = event.getPlayer();
handler.addToPool(new ChatInfo(p.getUniqueId(), p.getDisplayName()));
plugin.addToProcessQueue(new ChatInfo(p.getUniqueId(), p.getDisplayName()));
}
}

View File

@ -4,7 +4,7 @@ import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -20,7 +20,7 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class PlanCommandPreprocessListener implements Listener {
private final Plan plugin;
private final DataCacheHandler handler;
private final DataCache handler;
/**
* Class Constructor.

View File

@ -1,7 +1,6 @@
package main.java.com.djrapitops.plan.data.listeners;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.KillHandling;
import main.java.com.djrapitops.plan.data.handling.info.DeathInfo;
import main.java.com.djrapitops.plan.data.handling.info.KillInfo;
@ -22,7 +21,7 @@ import org.bukkit.event.entity.EntityDeathEvent;
*/
public class PlanDeathEventListener implements Listener {
private final DataCacheHandler handler;
private final Plan plugin;
/**
* Class Constructor.
@ -30,7 +29,7 @@ public class PlanDeathEventListener implements Listener {
* @param plugin Current instance of Plan
*/
public PlanDeathEventListener(Plan plugin) {
this.handler = plugin.getHandler();
this.plugin = plugin;
}
/**
@ -45,7 +44,7 @@ public class PlanDeathEventListener implements Listener {
LivingEntity dead = event.getEntity();
if (dead instanceof Player) {
handler.addToPool(new DeathInfo(dead.getUniqueId()));
plugin.addToProcessQueue(new DeathInfo(dead.getUniqueId()));
}
EntityDamageEvent entityDamageEvent = dead.getLastDamageCause();
@ -69,7 +68,7 @@ public class PlanDeathEventListener implements Listener {
}
}
handler.addToPool(new KillInfo(killer.getUniqueId(), time, dead, KillHandling.normalizeMaterialName(itemInHand)));
plugin.addToProcessQueue(new KillInfo(killer.getUniqueId(), time, dead, KillHandling.normalizeMaterialName(itemInHand)));
return;
}
@ -86,7 +85,7 @@ public class PlanDeathEventListener implements Listener {
return;
}
handler.addToPool(new KillInfo(owner.getUniqueId(), time, dead, "Wolf"));
plugin.addToProcessQueue(new KillInfo(owner.getUniqueId(), time, dead, "Wolf"));
}
}
}

View File

@ -1,7 +1,6 @@
package main.java.com.djrapitops.plan.data.listeners;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.data.handling.info.PlaytimeDependentInfo;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
@ -20,7 +19,7 @@ import java.util.UUID;
*/
public class PlanGamemodeChangeListener implements Listener {
private final DataCacheHandler handler;
private final Plan plugin;
/**
* Class Constructor.
@ -28,7 +27,7 @@ public class PlanGamemodeChangeListener implements Listener {
* @param plugin Current instance of Plan
*/
public PlanGamemodeChangeListener(Plan plugin) {
handler = plugin.getHandler();
this.plugin = plugin;
}
/**
@ -48,6 +47,6 @@ public class PlanGamemodeChangeListener implements Listener {
String gameMode = event.getNewGameMode().name();
String worldName = p.getWorld().getName();
handler.addToPool(new PlaytimeDependentInfo(uuid, InfoType.GM, time, gameMode, worldName));
plugin.addToProcessQueue(new PlaytimeDependentInfo(uuid, InfoType.GM, time, gameMode, worldName));
}
}

View File

@ -6,7 +6,7 @@ import com.djrapitops.plugin.utilities.player.Gamemode;
import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.data.handling.info.KickInfo;
import main.java.com.djrapitops.plan.data.handling.info.LoginInfo;
import main.java.com.djrapitops.plan.data.handling.info.LogoutInfo;
@ -32,7 +32,7 @@ import java.util.UUID;
public class PlanPlayerListener implements Listener {
private final Plan plugin;
private final DataCacheHandler handler;
private final DataCache handler;
/**
* Class Constructor.
@ -80,9 +80,9 @@ public class PlanPlayerListener implements Listener {
if (isNewPlayer) {
UserData newUserData = NewPlayerCreator.createNewPlayer(iPlayer);
loginInfo.process(newUserData);
handler.newPlayer(newUserData);
// TODO Rewrite Register & Login system handler.newPlayer(newUserData);
} else {
handler.addToPool(loginInfo);
// handler.addToPool(loginInfo);
}
this.cancel();
}
@ -98,6 +98,7 @@ public class PlanPlayerListener implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent event) {
// TODO Rewrite Logout system
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
handler.endSession(uuid);
@ -107,8 +108,7 @@ public class PlanPlayerListener implements Listener {
Gamemode gm = Gamemode.wrap(player.getGameMode());
String worldName = player.getWorld().getName();
handler.addToPool(new LogoutInfo(uuid, time, banned, gm.name(), handler.getSession(uuid), worldName));
handler.saveCachedData(uuid);
plugin.addToProcessQueue(new LogoutInfo(uuid, time, banned, gm.name(), handler.getSession(uuid), worldName));
}
/**
@ -134,8 +134,7 @@ public class PlanPlayerListener implements Listener {
Gamemode gm = Gamemode.wrap(player.getGameMode());
String worldName = player.getWorld().getName();
handler.addToPool(new LogoutInfo(uuid, time, banned, gm.name(), handler.getSession(uuid), worldName));
handler.addToPool(new KickInfo(uuid));
handler.saveCachedData(uuid);
plugin.addToProcessQueue(new LogoutInfo(uuid, time, banned, gm.name(), handler.getSession(uuid), worldName));
plugin.addToProcessQueue(new KickInfo(uuid));
}
}

View File

@ -1,7 +1,6 @@
package main.java.com.djrapitops.plan.data.listeners;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.data.handling.info.PlaytimeDependentInfo;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
@ -14,10 +13,10 @@ import org.bukkit.event.player.PlayerChangedWorldEvent;
import java.util.UUID;
public class PlanWorldChangeListener implements Listener {
private final DataCacheHandler handler;
private final Plan plugin;
public PlanWorldChangeListener(Plan plugin) {
this.handler = plugin.getHandler();
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.MONITOR)
@ -34,6 +33,6 @@ public class PlanWorldChangeListener implements Listener {
String gameMode = p.getGameMode().name();
long time = MiscUtils.getTime();
handler.addToPool(new PlaytimeDependentInfo(uuid, InfoType.WORLD, time, gameMode, worldName));
plugin.addToProcessQueue(new PlaytimeDependentInfo(uuid, InfoType.WORLD, time, gameMode, worldName));
}
}

View File

@ -5,7 +5,7 @@ import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import org.bukkit.World;
@ -23,7 +23,7 @@ import java.util.List;
public class TPSCountTimer extends AbsRunnable {
private final Plan plugin;
private final DataCacheHandler handler;
private final DataCache handler;
private final List<TPS> history;
private long lastCheckNano;

View File

@ -43,6 +43,16 @@ public class WorldTimes {
worldTimes.put(worldName, new GMTimes(gameMode, changeTime));
}
/**
* Updates the state at the end of the session.
* Does not change world or GameMode.
*
* @param changeTime epoch ms session ended.
*/
public void updateState(long changeTime) {
updateState(currentWorld, currentGamemode, changeTime);
}
/**
* Updates the time status to match the new state.
*

View File

@ -75,7 +75,7 @@ public class SessionsTable extends UserIDTable {
set = statement.executeQuery();
List<SessionData> sessions = new ArrayList<>();
while (set.next()) {
sessions.add(new SessionData(set.getLong(columnSessionStart), set.getLong(columnSessionEnd)));
// sessions.add(new SessionData(set.getLong(columnSessionStart), set.getLong(columnSessionEnd)));
}
set.close();
statement.close();
@ -169,7 +169,7 @@ public class SessionsTable extends UserIDTable {
long sessionStart = set.getLong(columnSessionStart);
long sessionEnd = set.getLong(columnSessionEnd);
sessions.get(id).add(new SessionData(sessionStart, sessionEnd));
// sessions.get(id).add(new SessionData(sessionStart, sessionEnd));
}
return sessions;

View File

@ -1,102 +0,0 @@
package main.java.com.djrapitops.plan.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;
/**
* This Class contains the Clear Queue Thread, which is clearing data from the DataCache.
*
* @author Rsl1122
* @since 3.0.0
*/
@Deprecated
public class DataCacheClearQueue extends Queue<UUID> {
/**
* Class constructor, starts the new Thread for clearing.
*
* @param handler current instance of DataCacheHandler.
*/
public DataCacheClearQueue(DataCacheHandler handler) {
super(new ArrayBlockingQueue<>(20000));
setup = new ClearSetup(queue, handler);
setup.go();
}
/**
* Used to schedule UserData to be cleared from the cache.
*
* @param uuid UUID of the UserData object (Player's UUID)
*/
public void scheduleForClear(UUID uuid) {
queue.add(uuid);
}
/**
* Used to schedule multiple UserData objects to be cleared from the cache.
*
* @param uuids UUIDs of the UserData object (Players' UUIDs)
*/
public void scheduleForClear(Collection<UUID> uuids) {
if (Verify.isEmpty(uuids)) {
return;
}
try {
queue.addAll(uuids.stream().filter(Objects::nonNull).collect(Collectors.toList()));
} catch (IllegalStateException e) {
Log.error(Locale.get(Msg.RUN_WARN_QUEUE_SIZE).parse("Clear Queue", 20000));
}
}
}
@Deprecated
class ClearConsumer extends Consumer<UUID> implements Runnable {
private DataCacheHandler handler;
ClearConsumer(BlockingQueue<UUID> q, DataCacheHandler handler) {
super(q, "ClearQueueConsumer");
this.handler = handler;
}
@Override
protected void consume(UUID uuid) {
if (!Verify.notNull(handler, uuid)) {
return;
}
try {
if (handler.isDataAccessed(uuid)) {
queue.add(uuid);
} else {
handler.clearFromCache(uuid);
}
// if online remove from clear list
} catch (Exception ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
@Override
protected void clearVariables() {
if (handler != null) {
handler = null;
}
}
}
@Deprecated
class ClearSetup extends Setup<UUID> {
ClearSetup(BlockingQueue<UUID> q, DataCacheHandler handler) {
super(new ClearConsumer(q, handler));
}
}

View File

@ -1,98 +0,0 @@
package main.java.com.djrapitops.plan.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Get Queue Thread, that fetches data from DataCache.
*
* @author Rsl1122
* @since 3.0.0
*/
@Deprecated
public class DataCacheGetQueue extends Queue<Map<UUID, List<DBCallableProcessor>>> {
/**
* Class constructor, starts the new Thread for fetching.
*
* @param plugin current instance of Plan
*/
public DataCacheGetQueue(Plan plugin) {
super(new ArrayBlockingQueue<>(20000));
setup = new GetSetup(queue, plugin.getDB());
setup.go();
}
/**
* Schedules UserData objects to be get for the given processors.
*
* @param uuid UUID of the player whose UserData object is fetched.
* @param processors Processors which process-method will be called after
* fetch is complete, with the UserData object.
*/
public void scheduleForGet(UUID uuid, DBCallableProcessor... processors) {
try {
Map<UUID, List<DBCallableProcessor>> map = new HashMap<>();
map.put(uuid, Arrays.asList(processors));
queue.add(map);
} catch (IllegalStateException e) {
Log.error(Locale.get(Msg.RUN_WARN_QUEUE_SIZE).parse("Get Queue", 20000));
}
}
@Deprecated
class GetConsumer extends Consumer<Map<UUID, List<DBCallableProcessor>>> {
private Database db;
GetConsumer(BlockingQueue<Map<UUID, List<DBCallableProcessor>>> q, Database db) {
super(q, "GetQueueConsumer");
this.db = db;
}
@Override
protected void consume(Map<UUID, List<DBCallableProcessor>> processors) {
if (!Verify.notNull(processors, db)) {
return;
}
try {
for (Map.Entry<UUID, List<DBCallableProcessor>> entrySet : processors.entrySet()) {
UUID uuid = entrySet.getKey();
List<DBCallableProcessor> processorsList = entrySet.getValue();
if (uuid == null || Verify.isEmpty(processorsList)) {
continue;
}
Log.debug("Database", uuid + ": Get, For:" + processorsList.size());
db.giveUserDataToProcessors(uuid, processorsList);
}
} catch (Exception ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
@Override
protected void clearVariables() {
if (db != null) {
db = null;
}
}
}
@Deprecated
class GetSetup extends Setup<Map<UUID, List<DBCallableProcessor>>> {
GetSetup(BlockingQueue<Map<UUID, List<DBCallableProcessor>>> q, Database db) {
super(new GetConsumer(q, db), new GetConsumer(q, db));
}
}
}

View File

@ -1,124 +0,0 @@
package main.java.com.djrapitops.plan.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.sql.SQLException;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Save Queue Thread, that saves data to the Database.
*
* @author Rsl1122
* @since 3.0.0
*/
@Deprecated
public class DataCacheSaveQueue extends Queue<UserData> {
/**
* Class constructor, starts the new Thread for saving.
*
* @param plugin current instance of Plan
* @param handler DataCacheHandler
*/
public DataCacheSaveQueue(Plan plugin, DataCacheHandler handler) {
super(new ArrayBlockingQueue<>(20000));
setup = new SaveSetup(queue, handler, plugin.getDB());
setup.go();
}
/**
* Schedule UserData object to be saved to the database.
*
* @param data UserData object.
*/
public void scheduleForSave(UserData data) {
try {
queue.add(data);
} catch (IllegalStateException e) {
Log.error(Locale.get(Msg.RUN_WARN_QUEUE_SIZE).parse("Save Queue", 20000));
}
}
/**
* Schedule UserData object for a new player to be saved to the database.
*
* @param data UserData object.
*/
public void scheduleNewPlayer(UserData data) {
Log.debug(data.getUuid() + ": Scheduling new Player");
scheduleForSave(data);
}
/**
* Check whether or not the queue contains a UserData object with the uuid.
*
* @param uuid UUID of the player.
* @return true/false
*/
public boolean containsUUID(UUID uuid) {
return uuid != null && queue.stream().anyMatch(d -> d.getUuid().equals(uuid));
}
}
@Deprecated
class SaveConsumer extends Consumer<UserData> {
private Database db;
private DataCacheHandler handler;
SaveConsumer(BlockingQueue<UserData> q, DataCacheHandler handler, Database db) {
super(q, "SaveQueueConsumer");
this.db = db;
this.handler = handler;
run = true;
}
@Override
protected void consume(UserData data) {
if (!Verify.notNull(handler, db, data)) {
return;
}
UUID uuid = data.getUuid();
/*TODO if (handler.getProcessTask().containsUUID(uuid)) { // Wait for process queue.
queue.add(data);
return;
}*/
try {
db.saveUserData(data);
data.stopAccessing();
if (data.shouldClearAfterSave()) {
handler.getClearTask().scheduleForClear(uuid);
}
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
@Override
protected void clearVariables() {
if (db != null) {
db = null;
}
if (handler != null) {
handler = null;
}
}
}
@Deprecated
class SaveSetup extends Setup<UserData> {
SaveSetup(BlockingQueue<UserData> q, DataCacheHandler handler, Database db) {
super(new SaveConsumer(q, handler, db), new SaveConsumer(q, handler, db));
}
}

View File

@ -22,13 +22,13 @@ public abstract class Setup<T> {
this.consumers = consumers;
}
void go() {
public void go() {
for (Consumer<T> consumer : consumers) {
Plan.getInstance().getRunnableFactory().createNew(consumer).runTaskAsynchronously();
}
}
void stop() {
public void stop() {
for (Consumer<T> consumer : consumers) {
consumer.stop();
}

View File

@ -1,40 +1,37 @@
package main.java.com.djrapitops.plan.queue;
package main.java.com.djrapitops.plan.queue.processing;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.queue.processing.Processor;
import main.java.com.djrapitops.plan.queue.Consumer;
import main.java.com.djrapitops.plan.queue.Queue;
import main.java.com.djrapitops.plan.queue.Setup;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Process Queue Thread, that processes HandlingInfo
* This Class is starts the Process Queue Thread, that processes Processor
* objects.
*
* @author Rsl1122
* @since 3.0.0
*/
public class DataCacheProcessQueue extends Queue<Processor> {
public class ProcessingQueue extends Queue<Processor> {
/**
* Class constructor, starts the new Thread for processing.
*/
public DataCacheProcessQueue() {
public ProcessingQueue() {
super(new ArrayBlockingQueue<>(20000));
setup = new ProcessSetup(queue);
setup.go();
}
/**
* Used to add HandlingInfo object to be processed.
* Used to add Processor object to be processed.
*
* @param processor object that extends HandlingInfo.
* @param processor processing object.
*/
public void addToQueue(Processor processor) {
try {
queue.add(processor);
} catch (IllegalStateException e) {
Log.toLog(this.getClass().getName(), e);
}
queue.offer(processor);
}
}

View File

@ -10,7 +10,7 @@ import main.java.com.djrapitops.plan.data.additional.HookHandler;
import main.java.com.djrapitops.plan.data.additional.PluginData;
import main.java.com.djrapitops.plan.data.analysis.*;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler;
import main.java.com.djrapitops.plan.data.cache.PageCacheHandler;
import main.java.com.djrapitops.plan.database.Database;
@ -126,7 +126,7 @@ public class Analysis {
rawData.sort(new UserDataLastPlayedComparator());
List<UUID> uuids = rawData.stream().map(UserData::getUuid).collect(Collectors.toList());
Benchmark.start("Create Empty dataset");
DataCacheHandler handler = plugin.getHandler();
DataCache handler = plugin.getHandler();
Map<String, Integer> commandUse = handler.getCommandUse();
AnalysisData analysisData = new AnalysisData(commandUse, tpsData);

View File

@ -5,7 +5,7 @@
*/
package test.java.main.java.com.djrapitops.plan.data.cache;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.database.Database;
import org.bukkit.plugin.java.JavaPlugin;
import org.junit.After;
@ -18,10 +18,10 @@ import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(JavaPlugin.class)
public class DataCacheHandlerTest {
public class DataCacheTest {
private Database db;
private DataCacheHandler handler;
private DataCache handler;
private int callsToSaveCommandUse;
private int callsToSaveUserData;
@ -30,7 +30,7 @@ public class DataCacheHandlerTest {
/**
*
*/
public DataCacheHandlerTest() {
public DataCacheTest() {
}
/**

View File

@ -8,9 +8,7 @@ package test.java.main.java.com.djrapitops.plan.data.cache.queue;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
@ -30,12 +28,14 @@ import java.util.Collection;
import java.util.List;
import java.util.UUID;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.powermock.api.mockito.PowerMockito.when;
// TODO Rewrite
@RunWith(PowerMockRunner.class)
@PrepareForTest({JavaPlugin.class})
public class DataCacheQueueTest {
public class QueueTest {
private final UUID uuid1 = MockUtils.getPlayerUUID();
private final UserData data1 = MockUtils.mockUserWithMoreData();
@ -44,10 +44,10 @@ public class DataCacheQueueTest {
private int callsToSaveUserData;
private int callsToGetUserData;
private DataCacheHandler handler;
private DataCache handler;
private Database db;
public DataCacheQueueTest() {
public QueueTest() {
}
@Before
@ -89,7 +89,7 @@ public class DataCacheQueueTest {
};
db.init();
when(plan.getDB()).thenReturn(db);
handler = new DataCacheHandler(plan) {
handler = new DataCache(plan) {
@Override
public void startAsyncPeriodicSaveTask() {
}
@ -102,65 +102,21 @@ public class DataCacheQueueTest {
db.close();
}
@Test
public void testGetQueue_cache() {
List<Integer> calls = new ArrayList<>();
List<Integer> errors = new ArrayList<>();
handler.getUserDataForProcessing(data -> {
if (data.equals(data1)) {
calls.add(1);
} else {
errors.add(1);
}
}, uuid1);
while (calls.size() < 1) {
if (errors.size() > 0) {
fail();
}
}
assertEquals(1, calls.size());
assertEquals(0, errors.size());
assertEquals(1, callsToGetUserData);
assertTrue(handler.getDataCache().containsKey(uuid1));
}
@Test
public void testGetQueue_dontCache() {
List<Integer> getCalls = new ArrayList<>();
List<Integer> errors = new ArrayList<>();
handler.getUserDataForProcessing(data -> {
if (data.equals(data1)) {
getCalls.add(1);
} else {
errors.add(1);
}
}, uuid1, false);
while (getCalls.size() < 1) {
if (errors.size() > 0) {
fail();
}
}
assertEquals(1, getCalls.size());
assertEquals(0, errors.size());
assertEquals(1, callsToGetUserData);
assertTrue(!handler.getDataCache().containsKey(uuid1));
}
@Test
public void testProcessQueue() {
List<Integer> processCalls = new ArrayList<>();
List<Integer> errors = new ArrayList<>();
handler.addToPool(new HandlingInfo(uuid1, InfoType.OTHER, 0) {
@Override
public void process(UserData uData) {
if (uData.equals(data1)) {
uData.setName("TestSuccessful");
processCalls.add(1);
} else {
errors.add(1);
}
}
});
// handler.addToPool(new HandlingInfo(uuid1, InfoType.OTHER, 0) {
// @Override
// public void process(UserData uData) {
// if (uData.equals(data1)) {
// uData.setName("TestSuccessful");
// processCalls.add(1);
// } else {
// errors.add(1);
// }
// }
// });
while (processCalls.size() < 1) {
if (errors.size() > 0) {
fail();
@ -169,9 +125,5 @@ public class DataCacheQueueTest {
assertEquals(1, processCalls.size());
assertEquals(0, errors.size());
assertEquals(1, callsToGetUserData);
assertTrue(handler.getDataCache().containsKey(uuid1));
assertEquals("TestSuccessful", handler.getDataCache().get(uuid1).getName());
}
// TODO Save & Clear Queue tests
}