mirror of
https://github.com/itHotL/PlayerStats.git
synced 2024-11-26 12:36:16 +01:00
Improved loading-speed for loading offlinePlayers (#63), fixed ban-list-filtering taking a long time (#61), started implementing MyLogger for more advanced debugging (#62)
This commit is contained in:
parent
523fd589fb
commit
3e968232c6
@ -68,8 +68,4 @@ public class Main extends JavaPlugin {
|
||||
}
|
||||
this.getLogger().info("Disabled PlayerStats!");
|
||||
}
|
||||
|
||||
public void logTimeTaken(String className, String methodName, long previousTime) {
|
||||
getLogger().info(className + ", " + methodName + ": " + (System.currentTimeMillis() - previousTime) + "ms");
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,16 @@ import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread;
|
||||
import com.gmail.artemis.the.gr8.playerstats.statistic.StatRequest;
|
||||
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
||||
public class ThreadManager {
|
||||
|
||||
private static final int threshold = 10;
|
||||
private final int threshold = 10;
|
||||
private int statThreadID;
|
||||
private int reloadThreadID;
|
||||
|
||||
private final Main plugin;
|
||||
private final BukkitAudiences adventure;
|
||||
@ -28,16 +31,27 @@ public class ThreadManager {
|
||||
messageFactory = m;
|
||||
plugin = p;
|
||||
|
||||
startReloadThread(null, true);
|
||||
statThreadID = 0;
|
||||
reloadThreadID = 0;
|
||||
startReloadThread(null);
|
||||
}
|
||||
|
||||
public void startReloadThread(CommandSender sender, boolean firstTimeLoading) {
|
||||
reloadThread = new ReloadThread(adventure, config, messageFactory, plugin, threshold, firstTimeLoading, statThread, sender);
|
||||
reloadThread.start();
|
||||
public void startReloadThread(CommandSender sender) {
|
||||
if (reloadThread == null || !reloadThread.isAlive()) {
|
||||
reloadThreadID += 1;
|
||||
|
||||
reloadThread = new ReloadThread(adventure, config, messageFactory, plugin, threshold, reloadThreadID, statThread, sender);
|
||||
reloadThread.start();
|
||||
}
|
||||
else {
|
||||
MyLogger.threadAlreadyRunning(reloadThread.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void startStatThread(StatRequest request) {
|
||||
statThread = new StatThread(adventure, config, messageFactory, plugin, threshold, request, reloadThread);
|
||||
statThreadID += 1;
|
||||
|
||||
statThread = new StatThread(adventure, config, messageFactory, plugin, statThreadID, threshold, request, reloadThread);
|
||||
statThread.start();
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ public class ReloadCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
threadManager.startReloadThread(sender, false);
|
||||
threadManager.startReloadThread(sender);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ public class StatCommand implements CommandExecutor {
|
||||
request.setPlayerName(sender.getName());
|
||||
request.setSelection(Query.PLAYER);
|
||||
}
|
||||
else if (OfflinePlayerHandler.isOfflinePlayerName(arg) && request.getPlayerName() == null) {
|
||||
else if (OfflinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) {
|
||||
request.setPlayerName(arg);
|
||||
request.setSelection(Query.PLAYER);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.gmail.artemis.the.gr8.playerstats.config;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.Main;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Query;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
@ -24,15 +25,27 @@ public class ConfigHandler {
|
||||
configVersion = 3.1;
|
||||
|
||||
checkConfigVersion();
|
||||
MyLogger.setDebugLevel(debugLevel());
|
||||
}
|
||||
|
||||
/** Reloads the config from file, or creates a new file with default values if there is none. */
|
||||
/** Returns the desired debugging level.
|
||||
<p>1 = low (only show unexpected errors)</p>
|
||||
<p>2 = medium (show all encountered exceptions, log main tasks and show time taken)</p>
|
||||
<p>3 = high (log all tasks and time taken)</p>
|
||||
<p>Default: 1</p>*/
|
||||
public int debugLevel() {
|
||||
return config.getInt("debug-level", 1);
|
||||
}
|
||||
|
||||
/** Reloads the config from file, or creates a new file with default values if there is none.
|
||||
Also reads the value for debug-level and passes it on to MyLogger. */
|
||||
public boolean reloadConfig() {
|
||||
try {
|
||||
if (!configFile.exists()) {
|
||||
saveDefaultConfig();
|
||||
}
|
||||
config = YamlConfiguration.loadConfiguration(configFile);
|
||||
MyLogger.setDebugLevel(debugLevel());
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.enums;
|
||||
|
||||
public enum DebugLevel {
|
||||
LOW, MEDIUM, HIGH
|
||||
}
|
@ -16,7 +16,7 @@ public class JoinListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||
if (!joinEvent.getPlayer().hasPlayedBefore()) {
|
||||
threadManager.startReloadThread(null, false);
|
||||
threadManager.startReloadThread(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.reload;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.UnixTimeHandler;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
@ -15,40 +16,33 @@ public class ReloadAction extends RecursiveAction {
|
||||
private final int start;
|
||||
private final int end;
|
||||
|
||||
private final boolean whitelistOnly;
|
||||
private final boolean excludeBanned;
|
||||
private final int lastPlayedLimit;
|
||||
private final ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
|
||||
|
||||
/** Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers that should be included in statistic calculations.
|
||||
* @param threshold the maximum length of OfflinePlayers to process in one task
|
||||
* @param players array of all OfflinePlayers (straight from Bukkit)
|
||||
* @param whitelistOnly whether to limit players based on the whitelist
|
||||
* @param excludeBanned whether to exclude banned players
|
||||
* @param lastPlayedLimit whether to set a limit based on last-played-date
|
||||
* @param offlinePlayerUUIDs the ConcurrentHashMap to put resulting playerNames and UUIDs on
|
||||
*/
|
||||
public ReloadAction(int threshold, OfflinePlayer[] players,
|
||||
boolean whitelistOnly, boolean excludeBanned, int lastPlayedLimit,
|
||||
ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {
|
||||
int lastPlayedLimit, ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {
|
||||
|
||||
this(threshold, players, 0, players.length,
|
||||
whitelistOnly, excludeBanned, lastPlayedLimit, offlinePlayerUUIDs);
|
||||
this(threshold, players, 0, players.length, lastPlayedLimit, offlinePlayerUUIDs);
|
||||
}
|
||||
|
||||
protected ReloadAction(int threshold, OfflinePlayer[] players, int start, int end,
|
||||
boolean whitelistOnly, boolean excludeBanned, int lastPlayedLimit,
|
||||
ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {
|
||||
int lastPlayedLimit, ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {
|
||||
|
||||
this.threshold = threshold;
|
||||
this.players = players;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
||||
this.whitelistOnly = whitelistOnly;
|
||||
this.excludeBanned = excludeBanned;
|
||||
this.lastPlayedLimit = lastPlayedLimit;
|
||||
this.offlinePlayerUUIDs = offlinePlayerUUIDs;
|
||||
|
||||
MyLogger.subActionCreated(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,9 +54,9 @@ public class ReloadAction extends RecursiveAction {
|
||||
else {
|
||||
final int split = length / 2;
|
||||
final ReloadAction subTask1 = new ReloadAction(threshold, players, start, (start + split),
|
||||
whitelistOnly, excludeBanned, lastPlayedLimit, offlinePlayerUUIDs);
|
||||
lastPlayedLimit, offlinePlayerUUIDs);
|
||||
final ReloadAction subTask2 = new ReloadAction(threshold, players, (start + split), end,
|
||||
whitelistOnly, excludeBanned, lastPlayedLimit, offlinePlayerUUIDs);
|
||||
lastPlayedLimit, offlinePlayerUUIDs);
|
||||
|
||||
//queue and compute all subtasks in the right order
|
||||
invokeAll(subTask1, subTask2);
|
||||
@ -72,11 +66,11 @@ public class ReloadAction extends RecursiveAction {
|
||||
private void process() {
|
||||
for (int i = start; i < end; i++) {
|
||||
OfflinePlayer player = players[i];
|
||||
if (player.getName() != null &&
|
||||
(!whitelistOnly || player.isWhitelisted()) &&
|
||||
(!excludeBanned || !player.isBanned()) &&
|
||||
String playerName = player.getName();
|
||||
MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 1);
|
||||
if (playerName != null &&
|
||||
(lastPlayedLimit == 0 || UnixTimeHandler.hasPlayedSince(lastPlayedLimit, player.getLastPlayed()))) {
|
||||
offlinePlayerUUIDs.put(player.getName(), player.getUniqueId());
|
||||
offlinePlayerUUIDs.put(playerName, player.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
|
||||
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -13,7 +14,9 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
@ -21,6 +24,7 @@ import java.util.concurrent.ForkJoinPool;
|
||||
public class ReloadThread extends Thread {
|
||||
|
||||
private final int threshold;
|
||||
private final int reloadThreadID;
|
||||
|
||||
private final BukkitAudiences adventure;
|
||||
private static ConfigHandler config;
|
||||
@ -29,10 +33,11 @@ public class ReloadThread extends Thread {
|
||||
|
||||
private final StatThread statThread;
|
||||
private final CommandSender sender;
|
||||
private final boolean firstTimeLoading;
|
||||
|
||||
public ReloadThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, boolean firstTime, @Nullable StatThread s, @Nullable CommandSender se) {
|
||||
public ReloadThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, int ID, @Nullable StatThread s, @Nullable CommandSender se) {
|
||||
this.threshold = threshold;
|
||||
reloadThreadID = ID;
|
||||
|
||||
adventure = a;
|
||||
config = c;
|
||||
messageFactory = m;
|
||||
@ -40,18 +45,21 @@ public class ReloadThread extends Thread {
|
||||
|
||||
statThread = s;
|
||||
sender = se;
|
||||
firstTimeLoading = firstTime;
|
||||
|
||||
this.setName("ReloadThread-" + reloadThreadID);
|
||||
MyLogger.threadCreated(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long time = System.currentTimeMillis();
|
||||
MyLogger.threadStart(this.getName());
|
||||
|
||||
//if reload is triggered by /statreload...
|
||||
if (!firstTimeLoading) {
|
||||
//if reload is triggered by /statreload (aka this thread does not have ID number 1)...
|
||||
if (reloadThreadID != 1) {
|
||||
if (statThread != null && statThread.isAlive()) {
|
||||
try {
|
||||
plugin.getLogger().info("Waiting for statThread to finish up...");
|
||||
MyLogger.waitingForOtherThread(this.getName(), statThread.getName());
|
||||
statThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
plugin.getLogger().warning(e.toString());
|
||||
@ -62,7 +70,7 @@ public class ReloadThread extends Thread {
|
||||
if (config.reloadConfig()) {
|
||||
|
||||
try {
|
||||
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(false));
|
||||
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap());
|
||||
}
|
||||
catch (ConcurrentModificationException e) {
|
||||
plugin.getLogger().warning("The request could not be fully executed due to a ConcurrentModificationException");
|
||||
@ -71,7 +79,7 @@ public class ReloadThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
plugin.logTimeTaken("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
|
||||
MyLogger.logTimeTakenDefault("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
|
||||
if (sender != null) {
|
||||
adventure.sender(sender).sendMessage(messageFactory.reloadedConfig(sender instanceof ConsoleCommandSender));
|
||||
}
|
||||
@ -79,26 +87,36 @@ public class ReloadThread extends Thread {
|
||||
}
|
||||
//during first start-up...
|
||||
else {
|
||||
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(true));
|
||||
plugin.logTimeTaken("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
|
||||
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap());
|
||||
MyLogger.logTimeTakenDefault("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
|
||||
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);
|
||||
}
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String, UUID> getPlayerMap(boolean firstTimeLoading) {
|
||||
OfflinePlayer[] offlinePlayers = Bukkit.getOfflinePlayers();
|
||||
|
||||
int size;
|
||||
if (firstTimeLoading) {
|
||||
size = offlinePlayers.length;
|
||||
private ConcurrentHashMap<String, UUID> getPlayerMap() {
|
||||
long time = System.currentTimeMillis();
|
||||
OfflinePlayer[] offlinePlayers;
|
||||
if (config.whitelistOnly()) {
|
||||
offlinePlayers = Bukkit.getWhitelistedPlayers().toArray(OfflinePlayer[]::new);
|
||||
MyLogger.logTimeTaken("ReloadThread", "getting white-list-only list", time);
|
||||
}
|
||||
else if (config.excludeBanned()) {
|
||||
Set<OfflinePlayer> bannedPlayers = Bukkit.getBannedPlayers();
|
||||
offlinePlayers = Arrays.stream(Bukkit.getOfflinePlayers())
|
||||
.parallel()
|
||||
.filter(offlinePlayer -> !bannedPlayers.contains(offlinePlayer)).toArray(OfflinePlayer[]::new);
|
||||
MyLogger.logTimeTaken("ReloadThread", "getting excluding-banned-players list", time);
|
||||
}
|
||||
else {
|
||||
size = OfflinePlayerHandler.getOfflinePlayerCount() != 0 ? OfflinePlayerHandler.getOfflinePlayerCount() : 16;
|
||||
offlinePlayers = Bukkit.getOfflinePlayers();
|
||||
MyLogger.logTimeTaken("ReloadThread", "getting regular player list", time);
|
||||
}
|
||||
|
||||
int size = offlinePlayers != null ? offlinePlayers.length : 16;
|
||||
ConcurrentHashMap<String, UUID> playerMap = new ConcurrentHashMap<>(size);
|
||||
|
||||
ReloadAction task = new ReloadAction(threshold, offlinePlayers, config.whitelistOnly(), config.excludeBanned(), config.lastPlayedLimit(), playerMap);
|
||||
ReloadAction task = new ReloadAction(threshold, offlinePlayers, config.lastPlayedLimit(), playerMap);
|
||||
MyLogger.actionCreated((offlinePlayers != null) ? offlinePlayers.length : 0);
|
||||
ForkJoinPool commonPool = ForkJoinPool.commonPool();
|
||||
|
||||
try {
|
||||
@ -106,6 +124,8 @@ public class ReloadThread extends Thread {
|
||||
} catch (ConcurrentModificationException e) {
|
||||
throw new ConcurrentModificationException(e.toString());
|
||||
}
|
||||
|
||||
MyLogger.actionFinished(1);
|
||||
return playerMap;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.gmail.artemis.the.gr8.playerstats.enums.Query;
|
||||
import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread;
|
||||
import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
|
||||
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@ -23,6 +24,7 @@ import java.util.stream.Collectors;
|
||||
public class StatThread extends Thread {
|
||||
|
||||
private final int threshold;
|
||||
|
||||
private final StatRequest request;
|
||||
private final ReloadThread reloadThread;
|
||||
|
||||
@ -32,8 +34,9 @@ public class StatThread extends Thread {
|
||||
private final Main plugin;
|
||||
|
||||
//constructor (called on thread creation)
|
||||
public StatThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, StatRequest s, @Nullable ReloadThread r) {
|
||||
public StatThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int ID, int threshold, StatRequest s, @Nullable ReloadThread r) {
|
||||
this.threshold = threshold;
|
||||
|
||||
request = s;
|
||||
reloadThread = r;
|
||||
|
||||
@ -41,11 +44,16 @@ public class StatThread extends Thread {
|
||||
config = c;
|
||||
messageFactory = m;
|
||||
plugin = p;
|
||||
|
||||
this.setName("StatThread-" + ID);
|
||||
MyLogger.threadCreated(this.getName());
|
||||
}
|
||||
|
||||
//what the thread will do once started
|
||||
@Override
|
||||
public void run() throws IllegalStateException, NullPointerException {
|
||||
MyLogger.threadStart(this.getName());
|
||||
|
||||
if (messageFactory == null || plugin == null) {
|
||||
throw new IllegalStateException("Not all classes off the plugin are running!");
|
||||
}
|
||||
@ -54,8 +62,10 @@ public class StatThread extends Thread {
|
||||
}
|
||||
if (reloadThread != null && reloadThread.isAlive()) {
|
||||
try {
|
||||
plugin.getLogger().info("Waiting for reloadThread to finish up...");
|
||||
adventure.sender(request.getCommandSender()).sendMessage(messageFactory.stillReloading(request.getCommandSender() instanceof ConsoleCommandSender));
|
||||
MyLogger.waitingForOtherThread(this.getName(), reloadThread.getName());
|
||||
adventure.sender(request.getCommandSender())
|
||||
.sendMessage(messageFactory
|
||||
.stillReloading(request.getCommandSender() instanceof ConsoleCommandSender));
|
||||
reloadThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
plugin.getLogger().warning(e.toString());
|
||||
@ -128,10 +138,11 @@ public class StatThread extends Thread {
|
||||
int size = OfflinePlayerHandler.getOfflinePlayerCount() != 0 ? (int) (OfflinePlayerHandler.getOfflinePlayerCount() * 1.05) : 16;
|
||||
ConcurrentHashMap<String, Integer> playerStats = new ConcurrentHashMap<>(size);
|
||||
ImmutableList<String> playerNames = ImmutableList.copyOf(OfflinePlayerHandler.getOfflinePlayerNames());
|
||||
TopStatAction task = new TopStatAction(threshold, playerNames,
|
||||
request, playerStats);
|
||||
|
||||
TopStatAction task = new TopStatAction(threshold, playerNames, request, playerStats);
|
||||
MyLogger.actionCreated(playerNames.size());
|
||||
ForkJoinPool commonPool = ForkJoinPool.commonPool();
|
||||
|
||||
try {
|
||||
commonPool.invoke(task);
|
||||
} catch (ConcurrentModificationException e) {
|
||||
@ -140,8 +151,9 @@ public class StatThread extends Thread {
|
||||
throw new ConcurrentModificationException(e.toString());
|
||||
}
|
||||
|
||||
MyLogger.actionFinished(2);
|
||||
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);
|
||||
plugin.logTimeTaken("StatThread", "calculated all stats", time);
|
||||
MyLogger.logTimeTakenDefault("StatThread", "calculated all stats", time);
|
||||
|
||||
return playerStats;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.statistic;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
@ -31,6 +32,8 @@ public class TopStatAction extends RecursiveAction {
|
||||
|
||||
this.request = statRequest;
|
||||
this.playerStats = playerStats;
|
||||
|
||||
MyLogger.subActionCreated(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,6 +56,7 @@ public class TopStatAction extends RecursiveAction {
|
||||
if (iterator.hasNext()) {
|
||||
do {
|
||||
String playerName = iterator.next();
|
||||
MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 2);
|
||||
OfflinePlayer player = OfflinePlayerHandler.getOfflinePlayer(playerName);
|
||||
if (player != null) {
|
||||
int statistic = 0;
|
||||
|
@ -0,0 +1,166 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.utils;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.DebugLevel;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MyLogger {
|
||||
|
||||
private static final Logger logger;
|
||||
private static DebugLevel debugLevel;
|
||||
|
||||
private static final String[] processedPlayers;
|
||||
private static final AtomicInteger playersIndex;
|
||||
private static ConcurrentHashMap<String, Integer> threadNames;
|
||||
|
||||
static{
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin("PlayerStats");
|
||||
|
||||
logger = plugin != null ? plugin.getLogger() : Bukkit.getLogger();
|
||||
debugLevel = DebugLevel.LOW;
|
||||
|
||||
processedPlayers = new String[10];
|
||||
playersIndex = new AtomicInteger(0);
|
||||
threadNames = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private MyLogger() {
|
||||
}
|
||||
|
||||
/** Accesses the playersIndex to up it by 1 and return its previous value. */
|
||||
private static int nextPlayersIndex() {
|
||||
return playersIndex.getAndIncrement();
|
||||
}
|
||||
|
||||
/** Returns true if the playersIndex is 10, or any subsequent increment of 10. */
|
||||
private static boolean incrementOfTen() {
|
||||
return (playersIndex.get() == 10 || (playersIndex.get() > 10 && playersIndex.get() % 10 == 0));
|
||||
}
|
||||
|
||||
/** Sets the desired debugging level.
|
||||
<p>1 = low (only show unexpected errors)</p>
|
||||
<p>2 = medium (show all encountered exceptions, log main tasks and show time taken)</p>
|
||||
<p>3 = high (log all tasks and time taken)</p>
|
||||
<p>Default: 1</p>*/
|
||||
public static void setDebugLevel(int level) {
|
||||
if (level == 2) {
|
||||
debugLevel = DebugLevel.MEDIUM;
|
||||
}
|
||||
else if (level == 3) {
|
||||
debugLevel = DebugLevel.HIGH;
|
||||
}
|
||||
else {
|
||||
debugLevel = DebugLevel.LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/** Output to console that the given thread has been created (but not started yet).*/
|
||||
public static void threadCreated(String threadName) {
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
logger.info(threadName + " created!");
|
||||
}
|
||||
}
|
||||
|
||||
/** Output to console that the given thread has been started. */
|
||||
public static void threadStart(String threadName) {
|
||||
if (debugLevel == DebugLevel.MEDIUM || debugLevel == DebugLevel.HIGH) {
|
||||
logger.info(threadName + " started!");
|
||||
}
|
||||
}
|
||||
|
||||
/** Output to console that another reloadThread is already running. */
|
||||
public static void threadAlreadyRunning(String threadName) {
|
||||
logger.info("Another reloadThread is already running! (" + threadName + ")");
|
||||
}
|
||||
|
||||
/** Output to console that the executingThread is waiting for otherThread to finish up. */
|
||||
public static void waitingForOtherThread(String executingThread, String otherThread) {
|
||||
logger.info(executingThread + ": Waiting for " + otherThread + " to finish up...");
|
||||
}
|
||||
|
||||
/** If DebugLevel is MEDIUM or HIGH, output to console that an action has started.
|
||||
@param taskLength Length of the action (in terms of units-to-process)*/
|
||||
public static void actionCreated(int taskLength) {
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
threadNames = new ConcurrentHashMap<>();
|
||||
playersIndex.set(0);
|
||||
logger.info("Initial Action created for " + taskLength + " Players. Start Index is " + playersIndex.get() + ". Processing...");
|
||||
}
|
||||
}
|
||||
|
||||
/** Internally save the name of the executing thread for later logging of this action.
|
||||
The list of names is reset upon the start of every new action.
|
||||
@param threadName Name of the executing thread*/
|
||||
public static void subActionCreated(String threadName) {
|
||||
if (debugLevel == DebugLevel.HIGH) {
|
||||
if (!threadNames.containsKey(threadName)) {
|
||||
threadNames.put(threadName, threadNames.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Internally save the name of the executing thread and processed player for logging,
|
||||
and for the ReloadThread, if DebugLevel is HIGH, output the last 10 processed players once
|
||||
there have been 10 names saved in MyLogger. This method is synchronized.
|
||||
@param threadName Name of the executing thread
|
||||
@param playerName Name of the player that was processed in this action
|
||||
@param thread 1 for ReloadThread, 2 for StatThread */
|
||||
public static synchronized void actionRunning(String threadName, String playerName, int thread) {
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
if (!threadNames.containsKey(threadName)) {
|
||||
threadNames.put(threadName, threadNames.size());
|
||||
}
|
||||
if (thread == 1 && debugLevel == DebugLevel.HIGH) {
|
||||
if (incrementOfTen()) {
|
||||
logger.info(Arrays.asList(processedPlayers).toString());
|
||||
}
|
||||
processedPlayers[nextPlayersIndex() % 10] = playerName;
|
||||
}
|
||||
else if (debugLevel == DebugLevel.MEDIUM) {
|
||||
nextPlayersIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Output to console that an action has finished.
|
||||
<p>For the ReloadThread, if DebugLevel is HIGH, output the left-over processed players.
|
||||
For both threads, if DebugLevel is MEDIUM or HIGH, output the names of the threads that were used.</p>
|
||||
@param thread 1 for ReloadThread, 2 for StatThread */
|
||||
public static void actionFinished(int thread) {
|
||||
if (thread == 1 && debugLevel == DebugLevel.HIGH) {
|
||||
ArrayList<String> leftOvers = new ArrayList<>(Arrays.asList(processedPlayers).subList(playersIndex.intValue() % 10, 10));
|
||||
logger.info(leftOvers.toString());
|
||||
}
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
logger.info("Finished Recursive Action! In total " +
|
||||
threadNames.size() + " Threads were used to process " +
|
||||
playersIndex.get() + " Players: " +
|
||||
Collections.list(threadNames.keys()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Output to console how long a certain task has taken if DebugLevel is MEDIUM or HIGH.
|
||||
@param className Name of the class executing the task
|
||||
@param methodName Name or description of the task
|
||||
@param startTime Timestamp marking the beginning of the task */
|
||||
public static void logTimeTaken(String className, String methodName, long startTime) {
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
logger.info(className + " " + methodName + ": " + (System.currentTimeMillis() - startTime) + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
/** Output to console how long a certain task has taken (regardless of DebugLevel).
|
||||
@param className Name of the class executing the task
|
||||
@param methodName Name or description of the task
|
||||
@param startTime Timestamp marking the beginning of the task */
|
||||
public static void logTimeTakenDefault(String className, String methodName, long startTime) {
|
||||
logger.info(className + " " + methodName + ":" + (System.currentTimeMillis() - startTime) + "ms");
|
||||
}
|
||||
}
|
@ -12,18 +12,23 @@ public class OfflinePlayerHandler {
|
||||
private static ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
|
||||
private static ArrayList<String> playerNames;
|
||||
|
||||
static{
|
||||
offlinePlayerUUIDs = new ConcurrentHashMap<>();
|
||||
playerNames = new ArrayList<>();
|
||||
}
|
||||
|
||||
private OfflinePlayerHandler() {
|
||||
}
|
||||
|
||||
/** Checks if a given playerName is on the private HashMap of players that should be included in statistic calculations
|
||||
@param playerName String, case-sensitive */
|
||||
public static boolean isOfflinePlayerName(String playerName) {
|
||||
public static boolean isRelevantPlayer(String playerName) {
|
||||
return offlinePlayerUUIDs.containsKey(playerName);
|
||||
}
|
||||
|
||||
/** Returns the number of OfflinePlayers that are included in statistic calculations */
|
||||
public static int getOfflinePlayerCount() {
|
||||
return offlinePlayerUUIDs != null ? offlinePlayerUUIDs.size() : 0;
|
||||
return offlinePlayerUUIDs.size();
|
||||
}
|
||||
|
||||
/** Get an ArrayList of names from all OfflinePlayers that should be included in statistic calculations */
|
||||
|
@ -8,6 +8,12 @@ config-version: 3.1
|
||||
# # General # #
|
||||
# # ------------------------------- # #
|
||||
|
||||
# How much output in console you'll get while PlayerStats is processing
|
||||
# 1 = low (only show unexpected errors)
|
||||
# 2 = medium (show all encountered exceptions, log main tasks and show time taken)
|
||||
# 3 = high (log all tasks and time taken)
|
||||
debug-level: 1
|
||||
|
||||
# Filtering options to control which players should be included in statistic calculations
|
||||
include-whitelist-only: false
|
||||
exclude-banned-players: false
|
||||
|
Loading…
Reference in New Issue
Block a user