Start SessionTable (not finished)

This commit is contained in:
Rsl1122 2017-08-22 17:32:19 +03:00
parent 44c9ee3925
commit 8895aca0ff
6 changed files with 169 additions and 330 deletions

View File

@ -25,10 +25,11 @@ import java.util.List;
*/ */
public class Session { public class Session {
private final WorldTimes worldTimes; private Long sessionID;
private WorldTimes worldTimes;
private final long sessionStart; private final long sessionStart;
private long sessionEnd; private long sessionEnd;
private final List<KillData> playerKills; private List<KillData> playerKills;
private int mobKills; private int mobKills;
private int deaths; private int deaths;
@ -52,7 +53,8 @@ public class Session {
* @param sessionStart Epoch millisecond the session was started. * @param sessionStart Epoch millisecond the session was started.
* @param sessionEnd Epoch millisecond the session ended. * @param sessionEnd Epoch millisecond the session ended.
*/ */
public Session(long sessionStart, long sessionEnd, WorldTimes worldTimes, List<KillData> playerKills, int mobKills, int deaths) { public Session(long id, long sessionStart, long sessionEnd, int mobKills, int deaths) {
this.sessionID = id;
this.sessionStart = sessionStart; this.sessionStart = sessionStart;
this.sessionEnd = sessionEnd; this.sessionEnd = sessionEnd;
this.worldTimes = worldTimes; this.worldTimes = worldTimes;
@ -173,4 +175,26 @@ public class Session {
public static Session start(long time, String world, String gm) { public static Session start(long time, String world, String gm) {
return new Session(time, world, gm); return new Session(time, world, gm);
} }
public boolean isFetchedFromDB() {
return sessionID != null;
}
public void setWorldTimes(WorldTimes worldTimes) {
this.worldTimes = worldTimes;
}
public void setPlayerKills(List<KillData> playerKills) {
this.playerKills = playerKills;
}
/**
* Used to get the ID of the session in the Database.
*
* @return ID if present.
* @throws NullPointerException if Session was not fetched from DB. Check using {@code isFetchedFromDB}
*/
public long getSessionID() {
return sessionID;
}
} }

View File

@ -1,26 +1,28 @@
package main.java.com.djrapitops.plan.database.tables; package main.java.com.djrapitops.plan.database.tables;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.database.databases.SQLDB; import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.database.sql.Select;
import main.java.com.djrapitops.plan.database.sql.Sql; import main.java.com.djrapitops.plan.database.sql.Sql;
import main.java.com.djrapitops.plan.database.sql.TableSqlParser; import main.java.com.djrapitops.plan.database.sql.TableSqlParser;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/** /**
* @author Rsl1122 * @author Rsl1122
*/ */
public class IPsTable extends UserIDTable { public class IPsTable extends UserIDTable {
// TODO Write tests
private final String columnIP = "ip"; private final String columnIP = "ip";
private final String columnGeolocation = "geolocation"; // TODO private final String columnGeolocation = "geolocation";
/** /**
* @param db The database * @param db The database
@ -40,6 +42,7 @@ public class IPsTable extends UserIDTable {
execute(TableSqlParser.createTable(tableName) execute(TableSqlParser.createTable(tableName)
.column(columnUserID, Sql.INT).notNull() .column(columnUserID, Sql.INT).notNull()
.column(columnIP, Sql.varchar(20)).notNull() .column(columnIP, Sql.varchar(20)).notNull()
.column(columnGeolocation, Sql.varchar(50)).notNull()
.foreignKey(columnUserID, usersTable.getTableName(), usersTable.getColumnID()) .foreignKey(columnUserID, usersTable.getTableName(), usersTable.getColumnID())
.toString() .toString()
); );
@ -59,176 +62,81 @@ public class IPsTable extends UserIDTable {
} }
/** /**
* @param userId The User ID from which the IPs should be retrieved from * @param uuid UUID of the user.
* @return The retrieved IPs * @return Users's Login Geolocations.
* @throws SQLException when an error at retrieval happens * @throws SQLException when an error at retrieval happens
*/ */
public List<InetAddress> getIPAddresses(int userId) throws SQLException { public List<String> getGeolocations(UUID uuid) throws SQLException {
return getStringList(uuid, columnGeolocation);
}
public List<String> getIps(UUID uuid) throws SQLException {
return getStringList(uuid, columnIP);
}
private List<String> getStringList(UUID uuid, String column) throws SQLException {
PreparedStatement statement = null; PreparedStatement statement = null;
ResultSet set = null; ResultSet set = null;
try { try {
List<InetAddress> ips = new ArrayList<>(); List<String> stringList = new ArrayList<>();
statement = prepareStatement("SELECT * FROM " + tableName + " WHERE UPPER(" + columnUserID + ") LIKE UPPER(?)"); statement = prepareStatement(Select.from(tableName, column)
statement.setInt(1, userId); .where(columnUserID + "=" + usersTable.statementSelectID)
.toString());
statement.setString(1, uuid.toString());
set = statement.executeQuery(); set = statement.executeQuery();
while (set.next()) { while (set.next()) {
String ipAddressName = set.getString(columnIP); stringList.add(set.getString(column));
try {
ips.add(InetAddress.getByName(ipAddressName));
} catch (UnknownHostException e) {
Log.error("Host not found at getIPAddresses: " + ipAddressName); //Shouldn't ever happen
}
} }
return ips; return stringList;
} finally { } finally {
close(set, statement); close(set, statement);
} }
} }
/** public void updateIP(UUID uuid, String ip, String geolocation) throws SQLException {
* @param userId The User ID for which the IPs should be saved for List<String> ips = getIps(uuid);
* @param ips The IPs if (ips.contains(ip)) {
* @throws SQLException when an error at saving happens
*/
public void saveIPList(int userId, Set<InetAddress> ips) throws SQLException {
if (ips == null) {
return;
}
ips.removeAll(getIPAddresses(userId));
if (ips.isEmpty()) {
return; return;
} }
insertIp(uuid, ip, geolocation);
}
private void insertIp(UUID uuid, String ip, String geolocation) throws SQLException {
PreparedStatement statement = null; PreparedStatement statement = null;
try { try {
statement = prepareStatement("INSERT INTO " + tableName + " (" statement = prepareStatement("INSERT INTO " + tableName + " ("
+ columnUserID + ", " + columnUserID + ", "
+ columnIP + columnIP + ", "
+ ") VALUES (?, ?)"); + columnGeolocation
boolean commitRequired = false; + ") VALUES ("
+ usersTable.statementSelectID + ", "
for (InetAddress ip : ips) { + "?, ?)");
if (ip == null) { statement.setString(1, uuid.toString());
continue; statement.setString(2, ip);
} statement.setString(3, geolocation);
statement.execute();
statement.setInt(1, userId);
statement.setString(2, ip.getHostAddress());
statement.addBatch();
commitRequired = true;
}
if (commitRequired) {
statement.executeBatch();
}
} finally { } finally {
close(statement); close(statement);
} }
} }
/** public Optional<String> getGeolocation(String ip) throws SQLException {
* @param ids The User IDs for which the IPs should be retrieved for
* @return The User IDs corresponding with their used IPs
* @throws SQLException when an error at retrieval happens
*/
public Map<Integer, Set<InetAddress>> getIPList(Collection<Integer> ids) throws SQLException {
if (Verify.isEmpty(ids)) {
return new HashMap<>();
}
Benchmark.start("Get Ips Multiple");
PreparedStatement statement = null; PreparedStatement statement = null;
ResultSet set = null; ResultSet set = null;
try { try {
statement = prepareStatement("SELECT * FROM " + tableName); statement = prepareStatement(Select.from(tableName, columnGeolocation)
.where(columnIP + "=?")
.toString());
statement.setString(1, ip);
set = statement.executeQuery(); set = statement.executeQuery();
Map<Integer, Set<InetAddress>> ips = new HashMap<>(); if (set.next()) {
return Optional.of(set.getString(columnGeolocation));
for (Integer id : ids) {
ips.put(id, new HashSet<>());
} }
return Optional.empty();
while (set.next()) {
Integer id = set.getInt(columnUserID);
if (!ids.contains(id)) {
continue;
}
String ipAddressName = set.getString(columnIP);
try {
ips.get(id).add(InetAddress.getByName(ipAddressName));
} catch (UnknownHostException e) {
Log.error("Host not found at getIPAddresses: " + ipAddressName); //Shouldn't ever happen
}
}
return ips;
} finally { } finally {
close(set, statement); close(set, statement);
Benchmark.stop("Database", "Get Ips Multiple");
}
}
/**
* @param ips The User IDs corresponding to their IPs used
* @throws SQLException when an error at saving happens
*/
public void saveIPList(Map<Integer, Set<InetAddress>> ips) throws SQLException {
if (Verify.isEmpty(ips)) {
return;
}
Benchmark.start("Save Ips Multiple");
Map<Integer, Set<InetAddress>> saved = getIPList(ips.keySet());
PreparedStatement statement = null;
try {
statement = prepareStatement("INSERT INTO " + tableName + " ("
+ columnUserID + ", "
+ columnIP
+ ") VALUES (?, ?)");
boolean commitRequired = false;
for (Map.Entry<Integer, Set<InetAddress>> entrySet : ips.entrySet()) {
Integer id = entrySet.getKey();
Set<InetAddress> ipAddresses = entrySet.getValue();
Set<InetAddress> s = saved.get(id);
if (s != null) {
ipAddresses.removeAll(s);
}
if (ipAddresses.isEmpty()) {
continue;
}
for (InetAddress ip : ipAddresses) {
if (ip == null) {
continue;
}
statement.setInt(1, id);
statement.setString(2, ip.getHostAddress());
statement.addBatch();
commitRequired = true;
}
}
if (commitRequired) {
statement.executeBatch();
}
} finally {
close(statement);
Benchmark.stop("Database", "Save Ips Multiple");
} }
} }
} }

View File

@ -18,14 +18,12 @@ import java.util.*;
*/ */
public class KillsTable extends Table { public class KillsTable extends Table {
private final String columnKillerUserID; private final String columnKillerUserID = "killer_id";
private final String columnVictimUserID; private final String columnVictimUserID = "victim_id";
private final String columnWeapon; private final String columnWeapon = "weapon";
private final String columnDate; private final String columnDate = "date";
private final String columnServerID; //TODO private final String columnServerID = "server_id"; //TODO
private final String columnSessionID; //TODO private final String columnSessionID = "session_id"; //TODO
// TODO Automatic UserID Retrieval from UsersTable.
/** /**
* @param db * @param db
@ -33,12 +31,6 @@ public class KillsTable extends Table {
*/ */
public KillsTable(SQLDB db, boolean usingMySQL) { public KillsTable(SQLDB db, boolean usingMySQL) {
super("plan_kills", db, usingMySQL); super("plan_kills", db, usingMySQL);
columnWeapon = "weapon";
columnDate = "date";
columnKillerUserID = "killer_id";
columnVictimUserID = "victim_id";
columnServerID = "server_id";
columnSessionID = "session_id";
} }
/** /**
@ -236,4 +228,8 @@ public class KillsTable extends Table {
Benchmark.stop("Database", "Save Kills multiple"); Benchmark.stop("Database", "Save Kills multiple");
} }
} }
public void savePlayerKills(UUID uuid, List<KillData> playerKills) {
// TODO savePlayerKills
}
} }

View File

@ -13,10 +13,7 @@ import main.java.com.djrapitops.plan.database.sql.*;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/** /**
* Table for managing multiple server's data in the database. * Table for managing multiple server's data in the database.
@ -42,10 +39,12 @@ public class ServerTable extends Table {
private final String columnInstalled = "is_installed"; private final String columnInstalled = "is_installed";
public final String statementSelectServerID; public final String statementSelectServerID;
public final String statementSelectServerNameID;
public ServerTable(SQLDB db, boolean usingMySQL) { public ServerTable(SQLDB db, boolean usingMySQL) {
super("plan_servers", db, usingMySQL); super("plan_servers", db, usingMySQL);
statementSelectServerID = "(" + Select.from(tableName, tableName + "." + columnServerID).where(columnServerUUID + "=?").toString() + ")"; statementSelectServerID = "(" + Select.from(tableName, tableName + "." + columnServerID).where(columnServerUUID + "=?").toString() + ")";
statementSelectServerNameID = "(" + Select.from(tableName, tableName + "." + columnServerName).where(columnServerID + "=?").toString() + ")";
} }
@Override @Override
@ -181,6 +180,25 @@ public class ServerTable extends Table {
} }
} }
public Map<Integer, String> getServerNames() throws SQLException {
Map<Integer, String> names = new HashMap<>();
PreparedStatement statement = null;
ResultSet set = null;
try {
statement = prepareStatement(Select.from(tableName,
columnServerName)
.toString());
set = statement.executeQuery();
while (set.next()) {
int id = set.getInt(columnServerID);
names.put(id, set.getString(columnServerName));
}
return names;
} finally {
close(set, statement);
}
}
/** /**
* Used to get BungeeCord WebServer info if present. * Used to get BungeeCord WebServer info if present.
* *

View File

@ -1,12 +1,12 @@
package main.java.com.djrapitops.plan.database.tables; package main.java.com.djrapitops.plan.database.tables;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.Session; import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.database.Container;
import main.java.com.djrapitops.plan.database.databases.SQLDB; import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.database.sql.Select;
import main.java.com.djrapitops.plan.database.sql.Sql; import main.java.com.djrapitops.plan.database.sql.Sql;
import main.java.com.djrapitops.plan.database.sql.TableSqlParser; import main.java.com.djrapitops.plan.database.sql.TableSqlParser;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -18,12 +18,14 @@ import java.util.*;
*/ */
public class SessionsTable extends UserIDTable { public class SessionsTable extends UserIDTable {
private final String columnSessionID = "id"; //TODO private final String columnSessionID = "id";
private final String columnSessionStart = "session_start"; private final String columnSessionStart = "session_start";
private final String columnSessionEnd = "session_end"; private final String columnSessionEnd = "session_end";
private final String columnServerID = "server_id"; //TODO private final String columnServerID = "server_id";
private final String columnMobKills = "mob_kills"; //TODO private final String columnMobKills = "mob_kills";
private final String columnDeaths = "deaths"; //TODO private final String columnDeaths = "deaths";
private final ServerTable serverTable;
/** /**
* @param db * @param db
@ -31,6 +33,7 @@ public class SessionsTable extends UserIDTable {
*/ */
public SessionsTable(SQLDB db, boolean usingMySQL) { public SessionsTable(SQLDB db, boolean usingMySQL) {
super("plan_sessions", db, usingMySQL); super("plan_sessions", db, usingMySQL);
serverTable = db.getServerTable();
} }
/** /**
@ -39,12 +42,17 @@ public class SessionsTable extends UserIDTable {
@Override @Override
public boolean createTable() { public boolean createTable() {
try { try {
UsersTable usersTable = db.getUsersTable();
execute(TableSqlParser.createTable(tableName) execute(TableSqlParser.createTable(tableName)
.primaryKeyIDColumn(usingMySQL, columnServerID, Sql.LONG)
.column(columnUserID, Sql.INT).notNull() .column(columnUserID, Sql.INT).notNull()
.column(columnServerID, Sql.INT).notNull()
.column(columnSessionStart, Sql.LONG).notNull() .column(columnSessionStart, Sql.LONG).notNull()
.column(columnSessionEnd, Sql.LONG).notNull() .column(columnSessionEnd, Sql.LONG).notNull()
.column(columnMobKills, Sql.INT).notNull()
.column(columnDeaths, Sql.INT).notNull()
.foreignKey(columnUserID, usersTable.getTableName(), usersTable.getColumnID()) .foreignKey(columnUserID, usersTable.getTableName(), usersTable.getColumnID())
.foreignKey(columnServerID, serverTable.getTableName(), serverTable.getColumnID())
.primaryKey(usingMySQL, columnSessionID)
.toString() .toString()
); );
return true; return true;
@ -55,31 +63,10 @@ public class SessionsTable extends UserIDTable {
} }
/** /**
* @param userId * Removes User's Sessions from the Database.
* @return * <p>
* @throws SQLException * // TODO KILLS SHOULD BE REMOVED FIRST.
*/ *
public List<Session> getSessionData(int userId) throws SQLException {
PreparedStatement statement = null;
ResultSet set = null;
try {
statement = prepareStatement("SELECT * FROM " + tableName + " WHERE (" + columnUserID + "=?)");
statement.setInt(1, userId);
set = statement.executeQuery();
List<Session> sessions = new ArrayList<>();
while (set.next()) {
// sessions.add(new Session(set.getLong(columnSessionStart), set.getLong(columnSessionEnd)));
}
set.close();
statement.close();
return sessions;
} finally {
close(set);
close(statement);
}
}
/**
* @param userId * @param userId
* @return * @return
*/ */
@ -87,161 +74,62 @@ public class SessionsTable extends UserIDTable {
return super.removeDataOf(userId); return super.removeDataOf(userId);
} }
/** public void saveSessionInformation(UUID uuid, Session session) throws SQLException {
* @param userId
* @param sessions
* @throws SQLException
*/
public void saveSessionData(int userId, List<Session> sessions) throws SQLException {
if (sessions == null) {
return;
}
sessions.removeAll(getSessionData(userId));
if (sessions.isEmpty()) {
return;
}
PreparedStatement statement = null; PreparedStatement statement = null;
try { try {
statement = prepareStatement("INSERT INTO " + tableName + " (" statement = prepareStatement("INSERT INTO " + tableName + " ("
+ columnUserID + ", " + columnUserID + ", "
+ columnSessionStart + ", " + columnSessionStart + ", "
+ columnSessionEnd + columnSessionEnd + ", "
+ ") VALUES (?, ?, ?)"); + columnDeaths + ", "
for (Session session : sessions) { + columnMobKills + ", "
long end = session.getSessionEnd(); + columnServerID
long start = session.getSessionStart(); + ") VALUES ("
if (end < start) { + columnUserID + "=" + usersTable.statementSelectID + ", "
continue; + "?, ?, ?, ?, "
} + serverTable.statementSelectServerID + ")");
statement.setString(1, uuid.toString());
statement.setInt(1, userId); statement.setLong(2, session.getSessionStart());
statement.setLong(2, start); statement.setLong(3, session.getSessionEnd());
statement.setLong(3, end); statement.setInt(4, session.getDeaths());
statement.addBatch(); statement.setInt(5, session.getMobKills());
}
statement.executeBatch(); statement.setString(6, Plan.getServerUUID().toString());
statement.execute();
} finally { } finally {
close(statement); close(statement);
} }
db.getWorldTimesTable().saveWorldTimes(session.getWorldTimes());
db.getKillsTable().savePlayerKills(uuid, session.getPlayerKills());
} }
/** public Map<String, List<Session>> getSessions(UUID uuid) throws SQLException {
* @param ids Map<Integer, String> serverNames = serverTable.getServerNames();
* @return Map<String, List<Session>> sessionsByServer = new HashMap<>();
* @throws SQLException
*/
public Map<Integer, List<Session>> getSessionData(Collection<Integer> ids) throws SQLException {
if (ids == null || ids.isEmpty()) {
return new HashMap<>();
}
Benchmark.start("Get Sessions multiple");
PreparedStatement statement = null; PreparedStatement statement = null;
ResultSet set = null; ResultSet set = null;
try { try {
Map<Integer, List<Session>> sessions = new HashMap<>(); statement = prepareStatement(Select.from(tableName, "*")
statement = prepareStatement("SELECT * FROM " + tableName); .where(columnUserID + "=" + usersTable.statementSelectID)
.toString());
statement.setString(1, uuid.toString());
set = statement.executeQuery(); set = statement.executeQuery();
for (Integer id : ids) {
sessions.put(id, new ArrayList<>());
}
while (set.next()) { while (set.next()) {
Integer id = set.getInt(columnUserID); long id = set.getLong(columnSessionID);
if (!ids.contains(id)) { long start = set.getLong(columnSessionStart);
continue; long end = set.getLong(columnSessionEnd);
} String serverName = serverNames.get(set.getInt(columnServerID));
long sessionStart = set.getLong(columnSessionStart); int deaths = set.getInt(columnDeaths);
long sessionEnd = set.getLong(columnSessionEnd); int mobKills = set.getInt(columnMobKills);
List<Session> sessions = sessionsByServer.getOrDefault(serverName, new ArrayList<>());
// sessions.get(id).add(new Session(sessionStart, sessionEnd)); sessions.add(new Session(id, start, end, deaths, mobKills));
} }
return sessionsByServer;
return sessions;
} finally { } finally {
close(set); close(set, statement);
close(statement);
Benchmark.stop("Database", "Get Sessions multiple");
} }
} }
/**
* @param sessions
* @throws SQLException
*/
public void saveSessionData(Map<Integer, List<Session>> sessions) throws SQLException {
if (sessions == null || sessions.isEmpty()) {
return;
}
Benchmark.start("Save Sessions multiple");
Map<Integer, List<Session>> saved = getSessionData(sessions.keySet());
for (Map.Entry<Integer, List<Session>> entrySet : sessions.entrySet()) {
Integer id = entrySet.getKey();
List<Session> sessionList = entrySet.getValue();
List<Session> s = saved.get(id);
if (s != null) {
sessionList.removeAll(s);
}
if (sessionList.isEmpty()) {
continue;
}
saved.put(id, sessionList);
}
List<List<Container<Session>>> batches = splitIntoBatches(sessions);
batches.forEach(batch -> {
try {
saveSessionBatch(batch);
} catch (SQLException e) {
Log.toLog("SessionsTable.saveSessionData", e);
}
});
Benchmark.stop("Database", "Save Sessions multiple");
}
private void saveSessionBatch(List<Container<Session>> batch) throws SQLException {
if (batch.isEmpty()) {
return;
}
PreparedStatement statement = null;
try {
statement = prepareStatement("INSERT INTO " + tableName + " ("
+ columnUserID + ", "
+ columnSessionStart + ", "
+ columnSessionEnd
+ ") VALUES (?, ?, ?)");
for (Container<Session> data : batch) {
Session session = data.getObject();
int id = data.getId();
statement.setInt(1, id);
statement.setLong(2, session.getSessionStart());
statement.setLong(3, session.getSessionEnd());
statement.addBatch();
}
statement.executeBatch();
} finally {
close(statement);
}
}
public void clean() {
// TODO Clean sessions before Configurable time span
}
} }

View File

@ -2,6 +2,7 @@ package main.java.com.djrapitops.plan.database.tables;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import main.java.com.djrapitops.plan.database.databases.SQLDB; 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.Sql;
import main.java.com.djrapitops.plan.database.sql.TableSqlParser; import main.java.com.djrapitops.plan.database.sql.TableSqlParser;
@ -312,4 +313,8 @@ public class WorldTimesTable extends UserIDTable {
close(statement); close(statement);
} }
} }
public void saveWorldTimes(WorldTimes worldTimes) {
// TODO saveWorldTimes (INSERT)
}
} }