Merge pull request #275 from Fuzzlemann/master

PR for 4.0.0 (Fuzzlemann) (8)
This commit is contained in:
Rsl1122 2017-08-25 12:50:01 +03:00 committed by GitHub
commit b597eb5789
14 changed files with 820 additions and 38 deletions

View File

@ -40,7 +40,8 @@ public class MySQLDB extends SQLDB {
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setMaxTotal(8);
dataSource.setInitialSize(1);
dataSource.setMaxTotal(120);
}
/**

View File

@ -63,7 +63,6 @@ public abstract class SQLDB extends Database {
*/
@Override
public boolean init() {
super.init();
setStatus("Init");
String benchName = "Init " + getConfigName();
Benchmark.start(benchName);
@ -73,6 +72,7 @@ public abstract class SQLDB extends Database {
if (!setupDatabase()) {
return false;
}
clean();
return true;
} catch (SQLException e) {
@ -108,14 +108,20 @@ public abstract class SQLDB extends Database {
return false;
}
if (newDatabase || getVersion() < 8) {
int version = getVersion();
boolean newVersion = version < 8;
if (newDatabase || newVersion) {
setVersion(8);
}
try (Statement statement = getConnection().createStatement()) {
statement.execute("DROP TABLE IF EXISTS plan_locations");
endTransaction(statement.getConnection());
if (newVersion) {
try (Statement statement = getConnection().createStatement()) {
statement.execute("DROP TABLE IF EXISTS plan_locations");
endTransaction(statement.getConnection());
}
}
return true;
}
@ -258,7 +264,6 @@ public abstract class SQLDB extends Database {
public void clean() {
Log.info("Cleaning the database.");
try {
setupDatabase();
tpsTable.clean();
Log.info("Clean complete.");
} catch (SQLException e) {

View File

@ -56,6 +56,7 @@ public class UsersTable extends UserIDTable {
try {
Set<UUID> uuids = new HashSet<>();
statement = prepareStatement(Select.from(tableName, columnUUID).toString());
statement.setFetchSize(2000);
set = statement.executeQuery();
while (set.next()) {
UUID uuid = UUID.fromString(set.getString(columnUUID));

View File

@ -1,5 +1,6 @@
package main.java.com.djrapitops.plan.database.tables;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.database.sql.Sql;
import main.java.com.djrapitops.plan.database.sql.TableSqlParser;
@ -46,7 +47,7 @@ public class VersionTable extends Table {
set = statement.executeQuery();
return set.next();
return !set.next();
} finally {
endTransaction(statement);
close(set, statement);
@ -69,7 +70,7 @@ public class VersionTable extends Table {
}
return version;
} catch (Exception exc) {
exc.printStackTrace();
Log.toLog("VersionsTable.getVersion", exc);
} finally {
endTransaction(statement);
close(set, statement);

View File

@ -0,0 +1,50 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.systems.info;
import main.java.com.djrapitops.plan.systems.processing.importing.importers.Importer;
import java.util.ArrayList;
import java.util.List;
/**
* @author Fuzzlemann
*/
public class ImporterManager {
/**
* Constructor used to hide the public constructor
*/
private ImporterManager() {
throw new IllegalStateException("Utility class");
}
private static final List<Importer> registry = new ArrayList<>();
public static void registerImporter(Importer importer) {
String firstName = importer.getNames().get(0);
if (getImporter(firstName) != null) {
removeImporter(firstName);
}
registry.add(importer);
}
public static List<Importer> getImporters() {
return registry;
}
public static Importer getImporter(String name) {
return registry.stream()
.filter(importer -> importer.getNames().contains(name))
.findAny()
.orElse(null);
}
public static void removeImporter(String name) {
registry.removeIf(importer -> importer.getNames().contains(name));
}
}

View File

@ -1,11 +0,0 @@
package main.java.com.djrapitops.plan.systems.processing.importing;
/**
* Abstract class used for importing data from other plugins.
*
* @author Rsl1122
* @since 4.0.0
*/
public abstract class Importer {
// TODO write new Importer
}

View File

@ -1,15 +0,0 @@
package main.java.com.djrapitops.plan.systems.processing.importing;
/**
* Imports all players who have not joined since Plan was installed.
*
* @author Rsl1122
* @since 3.5.0
*/
public class OfflinePlayerImporter extends Importer {
public OfflinePlayerImporter() {
// TODO Rewrite
}
}

View File

@ -0,0 +1,82 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.systems.processing.importing;
import main.java.com.djrapitops.plan.data.TPS;
import java.util.*;
/**
* @author Fuzzlemann
*/
public class ServerImportData {
private Map<String, Integer> commandUsages;
private List<TPS> tpsData;
private ServerImportData(Map<String, Integer> commandUsages, List<TPS> tpsData) {
this.commandUsages = commandUsages;
this.tpsData = tpsData;
}
public static ServerImportDataBuilder builder() {
return new ServerImportDataBuilder();
}
public Map<String, Integer> getCommandUsages() {
return commandUsages;
}
public void setCommandUsages(Map<String, Integer> commandUsages) {
this.commandUsages = commandUsages;
}
public List<TPS> getTpsData() {
return tpsData;
}
public void setTpsData(List<TPS> tpsData) {
this.tpsData = tpsData;
}
public static final class ServerImportDataBuilder {
private final Map<String, Integer> commandUsages = new HashMap<>();
private final List<TPS> tpsData = new ArrayList<>();
private ServerImportDataBuilder() {
throw new IllegalStateException("Builder class");
}
public ServerImportDataBuilder commandUsage(String command, Integer usages) {
this.commandUsages.put(command, usages);
return this;
}
public ServerImportDataBuilder commandUsages(Map<String, Integer> commandUsages) {
this.commandUsages.putAll(commandUsages);
return this;
}
public ServerImportDataBuilder tpsData(long date, double ticksPerSecond, int players, double cpuUsage, long usedMemory, int entityCount, int chunksLoaded) {
TPS tps = new TPS(date, ticksPerSecond, players, cpuUsage, usedMemory, entityCount, chunksLoaded);
this.tpsData.add(tps);
return this;
}
public ServerImportDataBuilder tpsData(TPS... tpsData) {
this.tpsData.addAll(Arrays.asList(tpsData));
return this;
}
public ServerImportDataBuilder tpsData(Collection<TPS> tpsData) {
this.tpsData.addAll(tpsData);
return this;
}
public ServerImportData build() {
return new ServerImportData(commandUsages, tpsData);
}
}
}

View File

@ -0,0 +1,276 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.systems.processing.importing;
import main.java.com.djrapitops.plan.data.PlayerKill;
import main.java.com.djrapitops.plan.data.time.GMTimes;
import java.util.*;
/**
* @author Fuzzlemann
* @since 4.0.0
*/
public class UserImportData {
private String name;
private String uuid;
private List<String> nicknames;
private long registered;
private boolean op;
private boolean banned;
private int timesKicked;
private List<String> ips;
private Map<String, GMTimes> worldTimes;
private List<PlayerKill> kills;
private int mobKills;
private int deaths;
private UserImportData(String name, String uuid, List<String> nicknames, long registered, boolean op, boolean banned, int timesKicked, List<String> ips, Map<String, GMTimes> worldTimes, List<PlayerKill> kills, int mobKills, int deaths) {
this.name = name;
this.uuid = uuid;
this.nicknames = nicknames;
this.registered = registered;
this.op = op;
this.banned = banned;
this.timesKicked = timesKicked;
this.ips = ips;
this.worldTimes = worldTimes;
this.kills = kills;
this.mobKills = mobKills;
this.deaths = deaths;
}
public static UserImportDataBuilder builder() {
return new UserImportDataBuilder();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public List<String> getNicknames() {
return nicknames;
}
public void setNicknames(List<String> nicknames) {
this.nicknames = nicknames;
}
public long getRegistered() {
return registered;
}
public void setRegistered(long registered) {
this.registered = registered;
}
public boolean isOp() {
return op;
}
public void setOp(boolean op) {
this.op = op;
}
public boolean isBanned() {
return banned;
}
public void setBanned(boolean banned) {
this.banned = banned;
}
public int getTimesKicked() {
return timesKicked;
}
public void setTimesKicked(int timesKicked) {
this.timesKicked = timesKicked;
}
public List<String> getIps() {
return ips;
}
public void setIps(List<String> ips) {
this.ips = ips;
}
public Map<String, GMTimes> getWorldTimes() {
return worldTimes;
}
public void setWorldTimes(Map<String, GMTimes> worldTimes) {
this.worldTimes = worldTimes;
}
public List<PlayerKill> getKills() {
return kills;
}
public void setKills(List<PlayerKill> kills) {
this.kills = kills;
}
public int getMobKills() {
return mobKills;
}
public void setMobKills(int mobKills) {
this.mobKills = mobKills;
}
public int getDeaths() {
return deaths;
}
public void setDeaths(int deaths) {
this.deaths = deaths;
}
public static final class UserImportDataBuilder {
private String name;
private String uuid;
private long registered;
private boolean op;
private final List<String> nicknames = new ArrayList<>();
private boolean banned;
private int timesKicked;
private final List<String> ips = new ArrayList<>();
private final Map<String, GMTimes> worldTimes = new HashMap<>();
private final List<PlayerKill> kills = new ArrayList<>();
private int mobKills;
private int deaths;
private UserImportDataBuilder() {
throw new IllegalStateException("Builder class");
}
public UserImportDataBuilder name(String name) {
this.name = name;
return this;
}
public UserImportDataBuilder uuid(UUID uuid) {
return uuid(uuid.toString());
}
public UserImportDataBuilder uuid(String uuid) {
this.uuid = uuid;
return this;
}
public UserImportDataBuilder registered(long registered) {
this.registered = registered;
return this;
}
public UserImportDataBuilder op() {
return op(true);
}
public UserImportDataBuilder op(boolean op) {
this.op = op;
return this;
}
public UserImportDataBuilder nicknames(String... nicknames) {
this.nicknames.addAll(Arrays.asList(nicknames));
return this;
}
public UserImportDataBuilder nickNames(Collection<String> nicknames) {
this.nicknames.addAll(nicknames);
return this;
}
public UserImportDataBuilder banned() {
return banned(true);
}
public UserImportDataBuilder banned(boolean banned) {
this.banned = banned;
return this;
}
public UserImportDataBuilder timesKicked(int timesKicked) {
this.timesKicked += timesKicked;
return this;
}
public UserImportDataBuilder ips(String... ips) {
this.ips.addAll(Arrays.asList(ips));
return this;
}
public UserImportDataBuilder ips(Collection<String> ips) {
this.ips.addAll(ips);
return this;
}
public UserImportDataBuilder worldTimes(String worldName, long... times) {
GMTimes gmTimes = new GMTimes();
gmTimes.setAllGMTimes(times);
this.worldTimes.put(worldName, gmTimes);
return this;
}
public UserImportDataBuilder worldTimes(String worldName, GMTimes gmTimes) {
this.worldTimes.put(worldName, gmTimes);
return this;
}
public UserImportDataBuilder worldTimes(Map<String, GMTimes> worldTimes) {
this.worldTimes.putAll(worldTimes);
return this;
}
public UserImportDataBuilder kills(PlayerKill... kills) {
this.kills.addAll(Arrays.asList(kills));
return this;
}
public UserImportDataBuilder kills(Collection<PlayerKill> kills) {
this.kills.addAll(kills);
return this;
}
public UserImportDataBuilder mobKills(int mobKills) {
this.mobKills += mobKills;
return this;
}
public UserImportDataBuilder deaths(int deaths) {
this.deaths += deaths;
return this;
}
public UserImportData build() {
return new UserImportData(name, uuid, nicknames, registered, op, banned, timesKicked, ips, worldTimes, kills, mobKills, deaths);
}
}
}

View File

@ -0,0 +1,253 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.systems.processing.importing;
import com.djrapitops.plugin.utilities.player.UUIDFetcher;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import java.util.*;
import java.util.stream.Collectors;
/**
* A class for refining the {@link UserImportData}s
* so no {@code null} is left in any field.
* It also removes invalid data.
*
* @author Fuzzlemann
* @since 4.0.0
*/
public class UserImportRefiner {
private final Plan plugin;
private final boolean onlineMode;
private final Vector<UserImportData> importers = new Vector<>();
private final Map<String, Boolean> worlds = new Hashtable<>();
private final Map<UserImportData, String> uuidsMissing = new Hashtable<>();
private final Map<UserImportData, String> namesMissing = new Hashtable<>();
private final Map<UserImportData, String> foundUUIDs = new Hashtable<>();
private final Map<UserImportData, String> foundNames = new Hashtable<>();
public UserImportRefiner(Plan plugin, List<UserImportData> importers) {
this.plugin = plugin;
this.importers.addAll(importers);
onlineMode = plugin.getServer().getOnlineMode();
}
public List<UserImportData> refineData() {
String benchmarkName = "Refining UserImportData";
Benchmark.start(benchmarkName);
processMissingIdentifiers();
processOldWorlds();
Benchmark.stop(benchmarkName);
return importers;
}
private void processOldWorlds() {
String benchmarkName = "Processing old worlds";
Benchmark.start(benchmarkName);
importers.parallelStream()
.flatMap(importer -> importer.getWorldTimes().keySet().stream())
.forEach(this::checkOldWorld);
if (!worlds.containsValue(true)) {
return;
}
worlds.values().removeIf(old -> false);
importers.parallelStream()
.forEach(importer -> importer.getWorldTimes().keySet().removeAll(worlds.keySet()));
Benchmark.stop(benchmarkName);
}
private void checkOldWorld(String worldName) {
if (worlds.containsKey(worldName)) {
return;
}
World world = plugin.getServer().getWorld(worldName);
boolean old = world == null;
worlds.put(worldName, old);
}
private void processMissingIdentifiers() {
String benchmarkName = "Processing missing identifiers";
Benchmark.start(benchmarkName);
Vector<UserImportData> invalidData = new Vector<>();
importers.parallelStream().forEach(importer -> {
String name = importer.getName();
String uuid = importer.getUuid();
boolean nameNull = name == null;
boolean uuidNull = uuid == null;
if (nameNull && uuidNull) {
invalidData.add(importer);
}
if (nameNull) {
namesMissing.put(importer, uuid);
} else if (uuidNull) {
uuidsMissing.put(importer, name);
}
});
importers.removeAll(invalidData);
processMissingUUIDs();
processMissingNames();
Benchmark.stop(benchmarkName);
}
private void processMissingUUIDs() {
String benchmarkName = "Processing missing UUIDs";
Benchmark.start(benchmarkName);
if (onlineMode) {
addMissingUUIDsOverFetcher();
addMissingUUIDsOverOfflinePlayer();
} else {
addMissingUUIDsOverOfflinePlayer();
addMissingUUIDsOverFetcher();
}
foundUUIDs.entrySet().parallelStream().forEach(entry -> entry.getKey().setUuid(entry.getValue()));
importers.removeAll(uuidsMissing.keySet());
Benchmark.stop(benchmarkName);
}
private void addMissingUUIDsOverFetcher() {
UUIDFetcher uuidFetcher = new UUIDFetcher(new ArrayList<>(uuidsMissing.values()));
Map<String, String> result;
try {
result = uuidFetcher.call().entrySet().parallelStream()
.collect(Collectors.toMap(entry -> entry.getValue().toString(), Map.Entry::getKey));
} catch (Exception e) {
Log.toLog(this.getClass().getName(), e);
return;
}
addFoundUUIDs(result);
}
private void addMissingUUIDsOverOfflinePlayer() {
Map<String, String> result = new Hashtable<>();
for (String name : uuidsMissing.values()) {
String uuid = getUuidByOfflinePlayer(name);
if (uuid == null) {
continue;
}
result.put(name, uuid);
}
addFoundUUIDs(result);
}
private void addFoundUUIDs(Map<String, String> foundUUIDs) {
Vector<UserImportData> found = new Vector<>();
uuidsMissing.entrySet().parallelStream().forEach((entry) -> {
UserImportData importer = entry.getKey();
String name = entry.getValue();
String uuid = foundUUIDs.get(name);
this.foundUUIDs.put(importer, uuid);
found.add(importer);
});
uuidsMissing.keySet().removeAll(found);
}
@SuppressWarnings("deprecation")
private String getUuidByOfflinePlayer(String name) {
OfflinePlayer player = plugin.getServer().getOfflinePlayer(name);
if (!player.hasPlayedBefore()) {
return null;
}
return player.getUniqueId().toString();
}
private void processMissingNames() {
String benchmarkNames = "Processing missing names";
Benchmark.start(benchmarkNames);
addMissingNames();
foundNames.entrySet().parallelStream().forEach(entry -> entry.getKey().setName(entry.getValue()));
importers.removeAll(namesMissing.keySet());
Benchmark.stop(benchmarkNames);
}
private void addMissingNames() {
Map<String, String> result = new Hashtable<>();
namesMissing.values().parallelStream().forEach(uuid -> {
String name = getNameByOfflinePlayer(uuid);
result.put(uuid, name);
});
addFoundNames(result);
}
private void addFoundNames(Map<String, String> foundNames) {
Vector<UserImportData> found = new Vector<>();
namesMissing.entrySet().parallelStream().forEach(entry -> {
UserImportData importer = entry.getKey();
String uuid = entry.getValue();
String name = foundNames.get(uuid);
this.foundNames.put(importer, name);
found.add(importer);
});
namesMissing.keySet().removeAll(found);
}
private String getNameByOfflinePlayer(String uuid) {
OfflinePlayer player = plugin.getServer().getOfflinePlayer(UUID.fromString(uuid));
if (!player.hasPlayedBefore()) {
return null;
}
return player.getName();
}
}

View File

@ -0,0 +1,91 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.systems.processing.importing.importers;
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.systems.processing.importing.ServerImportData;
import main.java.com.djrapitops.plan.systems.processing.importing.UserImportData;
import main.java.com.djrapitops.plan.systems.processing.importing.UserImportRefiner;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.util.List;
/**
* @author Fuzzlemann
* @since 4.0.0
*/
public abstract class Importer {
public abstract List<String> getNames();
public abstract ServerImportData getServerImportData();
public abstract List<UserImportData> getUserImportData();
public void processImport() {
String benchmarkName = "Import processing";
String serverBenchmarkName = "Server Data processing";
String userDataBenchmarkName = "User Data processing";
Benchmark.start(benchmarkName);
Benchmark.start(serverBenchmarkName);
processServerData();
Benchmark.stop(serverBenchmarkName);
Benchmark.start(userDataBenchmarkName);
processUserData();
Benchmark.stop(userDataBenchmarkName);
Benchmark.stop(benchmarkName);
}
private void processServerData() {
String benchmarkName = "Processing Server Data";
String getDataBenchmarkName = "Getting Server Data";
Benchmark.start(benchmarkName);
Benchmark.start(getDataBenchmarkName);
ServerImportData serverImportData = getServerImportData();
Benchmark.stop(getDataBenchmarkName);
if (serverImportData == null) {
Log.debug("Server Import Data null, skipping");
return;
}
//TODO
Benchmark.start(benchmarkName);
}
private void processUserData() {
String benchmarkName = "Processing User Data";
String getDataBenchmarkName = "Getting User Data";
Benchmark.start(benchmarkName);
Benchmark.start(getDataBenchmarkName);
List<UserImportData> userImportData = getUserImportData();
Benchmark.stop(getDataBenchmarkName);
if (Verify.isEmpty(userImportData)) {
Log.debug("User Import Data null or empty, skipping");
return;
}
UserImportRefiner userImportRefiner = new UserImportRefiner(Plan.getInstance(), userImportData);
userImportData = userImportRefiner.refineData();
//TODO
Benchmark.stop(benchmarkName);
}
}

View File

@ -0,0 +1,47 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.systems.processing.importing.importers;
import main.java.com.djrapitops.plan.systems.processing.importing.ServerImportData;
import main.java.com.djrapitops.plan.systems.processing.importing.UserImportData;
import org.bukkit.Bukkit;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
/**
* @author Fuzzlemann
* @since 4.0.0
*/
public class OfflinePlayerImporter extends Importer {
@Override
public List<String> getNames() {
return Arrays.asList("offline", "offlineplayer");
}
@Override
public ServerImportData getServerImportData() {
return null;
}
@Override
public List<UserImportData> getUserImportData() {
Vector<UserImportData> dataList = new Vector<>();
Arrays.stream(Bukkit.getOfflinePlayers()).parallel().forEach(player -> {
UserImportData.UserImportDataBuilder builder = UserImportData.builder();
builder.name(player.getName())
.uuid(player.getUniqueId())
.op(player.isOp())
.registered(player.getFirstPlayed())
.banned(player.isBanned());
dataList.add(builder.build());
});
return dataList;
}
}

View File

@ -94,8 +94,8 @@ public class TPSCountTimer extends AbsRunnable {
entityCount = getEntityCount();
// 40ms removed because the run appears to take 40-50ms, screwing the tps.
long fourtyMsAsNs = TimeAmount.MILLISECOND.ns() * 40L;
return getTPS(diff - fourtyMsAsNs, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline);
long fortyMsAsNs = TimeAmount.MILLISECOND.ns() * 40L;
return getTPS(diff - fortyMsAsNs, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline);
}
}

View File

@ -3,6 +3,7 @@ package test.java.main.java.com.djrapitops.plan.database;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.PassEncryptUtil;
@ -32,7 +33,7 @@ import static org.junit.Assert.assertTrue;
public class DatabaseCommitTest {
private Plan plan;
private SQLiteDB db;
private SQLDB db;
private int rows;
@Before