Refactored SessionsTable#saveSession to an executable:

Affected:
- KillsTable#savePlayerKills
- WorldTimesTable#saveWorldTimes
- KillsTable and WorldTimesTable where execution contained duplication
  with LargeStoreQueries, mainly INSERT_STATEMENT and batch additions
- SessionCache#endSession now returns an Optional Session for future
  refactoring, when Logout transaction is being made.
This commit is contained in:
Rsl1122 2019-01-27 17:46:43 +02:00
parent dc6ce30015
commit a63ab7d65c
11 changed files with 204 additions and 290 deletions

View File

@ -103,6 +103,7 @@ public class ShutdownHook extends Thread {
if (!database.isOpen()) { if (!database.isOpen()) {
database.init(); database.init();
} }
// TODO Create a server shutdown transaction.
try { try {
database.save().session(uuid, session); database.save().session(uuid, session);
} catch (DBOpException e) { } catch (DBOpException e) {

View File

@ -16,10 +16,13 @@
*/ */
package com.djrapitops.plan.db.sql.queries; package com.djrapitops.plan.db.sql.queries;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.time.GMTimes;
import com.djrapitops.plan.db.access.ExecBatchStatement;
import com.djrapitops.plan.db.access.ExecStatement; import com.djrapitops.plan.db.access.ExecStatement;
import com.djrapitops.plan.db.access.Executable; import com.djrapitops.plan.db.access.Executable;
import com.djrapitops.plan.db.sql.tables.CommandUseTable; import com.djrapitops.plan.db.sql.tables.*;
import com.djrapitops.plan.db.sql.tables.ServerTable;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
@ -36,6 +39,13 @@ public class DataStoreQueries {
/* static method class */ /* static method class */
} }
/**
* Store the used command in the database.
*
* @param serverUUID UUID of the Plan server.
* @param commandName Name of the command that was used.
* @return Executable, use inside a {@link com.djrapitops.plan.db.access.transactions.Transaction}
*/
public static Executable storeUsedCommandInformation(UUID serverUUID, String commandName) { public static Executable storeUsedCommandInformation(UUID serverUUID, String commandName) {
return connection -> { return connection -> {
if (!updateCommandUsage(serverUUID, commandName).execute(connection)) { if (!updateCommandUsage(serverUUID, commandName).execute(connection)) {
@ -71,4 +81,52 @@ public class DataStoreQueries {
}; };
} }
/**
* Store a finished session in the database.
*
* @param session Session, of which {@link Session#endSession(long)} has been called.
* @return Executable, use inside a {@link com.djrapitops.plan.db.access.transactions.Transaction}
* @throws IllegalArgumentException If {@link Session#endSession(long)} has not yet been called.
*/
public static Executable storeSession(Session session) {
session.getValue(SessionKeys.END).orElseThrow(() -> new IllegalArgumentException("Attempted to save a session that has not ended."));
return connection -> {
storeSessionInformation(session).execute(connection);
storeSessionKills(session).execute(connection);
return storeSessionWorldTimes(session).execute(connection);
};
}
private static Executable storeSessionInformation(Session session) {
return new ExecStatement(SessionsTable.INSERT_STATEMENT) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, session.getUnsafe(SessionKeys.UUID).toString());
statement.setLong(2, session.getUnsafe(SessionKeys.START));
statement.setLong(3, session.getUnsafe(SessionKeys.END));
statement.setInt(4, session.getUnsafe(SessionKeys.DEATH_COUNT));
statement.setInt(5, session.getUnsafe(SessionKeys.MOB_KILL_COUNT));
statement.setLong(6, session.getUnsafe(SessionKeys.AFK_TIME));
statement.setString(7, session.getUnsafe(SessionKeys.SERVER_UUID).toString());
}
};
}
private static Executable storeSessionKills(Session session) {
return new ExecBatchStatement(KillsTable.INSERT_STATEMENT) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
KillsTable.addSessionKillsToBatch(statement, session);
}
};
}
private static Executable storeSessionWorldTimes(Session session) {
return new ExecBatchStatement(WorldTimesTable.INSERT_STATEMENT) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
WorldTimesTable.addSessionWorldTimesToBatch(statement, session, GMTimes.getGMKeyArray());
}
};
}
} }

View File

@ -352,8 +352,7 @@ public class LargeStoreQueries {
return connection -> { return connection -> {
storeAllSessionsWithoutKillOrWorldData(sessions).execute(connection); storeAllSessionsWithoutKillOrWorldData(sessions).execute(connection);
storeSessionKillData(sessions).execute(connection); storeSessionKillData(sessions).execute(connection);
storeSessionWorldTimeData(sessions).execute(connection); return storeSessionWorldTimeData(sessions).execute(connection);
return false;
}; };
} }
@ -362,35 +361,11 @@ public class LargeStoreQueries {
return Executable.empty(); return Executable.empty();
} }
String sql = "INSERT INTO " + KillsTable.TABLE_NAME + " (" return new ExecBatchStatement(KillsTable.INSERT_STATEMENT) {
+ KillsTable.SESSION_ID + ", "
+ KillsTable.KILLER_UUID + ", "
+ KillsTable.VICTIM_UUID + ", "
+ KillsTable.SERVER_UUID + ", "
+ KillsTable.DATE + ", "
+ KillsTable.WEAPON
+ ") VALUES (" + SessionsTable.SELECT_SESSION_ID_STATEMENT + ", ?, ?, ?, ?, ?)";
return new ExecBatchStatement(sql) {
@Override @Override
public void prepare(PreparedStatement statement) throws SQLException { public void prepare(PreparedStatement statement) throws SQLException {
for (Session session : sessions) { for (Session session : sessions) {
UUID uuid = session.getUnsafe(SessionKeys.UUID); KillsTable.addSessionKillsToBatch(statement, session);
UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID);
for (PlayerKill kill : session.getPlayerKills()) {
// Session ID select statement
statement.setString(1, uuid.toString());
statement.setString(2, serverUUID.toString());
statement.setLong(3, session.getUnsafe(SessionKeys.START));
statement.setLong(4, session.getUnsafe(SessionKeys.END));
statement.setString(5, uuid.toString());
statement.setString(6, kill.getVictim().toString());
statement.setString(7, serverUUID.toString());
statement.setLong(8, kill.getDate());
statement.setString(9, kill.getWeapon());
statement.addBatch();
}
} }
} }
}; };
@ -401,51 +376,13 @@ public class LargeStoreQueries {
return Executable.empty(); return Executable.empty();
} }
String sql = "INSERT INTO " + WorldTimesTable.TABLE_NAME + " (" + return new ExecBatchStatement(WorldTimesTable.INSERT_STATEMENT) {
WorldTimesTable.SESSION_ID + ", " +
WorldTimesTable.WORLD_ID + ", " +
WorldTimesTable.USER_UUID + ", " +
WorldTimesTable.SERVER_UUID + ", " +
WorldTimesTable.SURVIVAL + ", " +
WorldTimesTable.CREATIVE + ", " +
WorldTimesTable.ADVENTURE + ", " +
WorldTimesTable.SPECTATOR +
") VALUES ( " +
SessionsTable.SELECT_SESSION_ID_STATEMENT + ", " +
WorldTable.SELECT_WORLD_ID_STATEMENT + ", " +
"?, ?, ?, ?, ?, ?)";
return new ExecBatchStatement(sql) {
@Override @Override
public void prepare(PreparedStatement statement) throws SQLException { public void prepare(PreparedStatement statement) throws SQLException {
String[] gms = GMTimes.getGMKeyArray(); String[] gms = GMTimes.getGMKeyArray();
for (Session session : sessions) { for (Session session : sessions) {
UUID uuid = session.getUnsafe(SessionKeys.UUID); WorldTimesTable.addSessionWorldTimesToBatch(statement, session, gms);
UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID);
Map<String, GMTimes> worldTimes = session.getUnsafe(SessionKeys.WORLD_TIMES).getWorldTimes();
for (Map.Entry<String, GMTimes> worldTimesEntry : worldTimes.entrySet()) {
String worldName = worldTimesEntry.getKey();
GMTimes gmTimes = worldTimesEntry.getValue();
// Session ID select statement
statement.setString(1, uuid.toString());
statement.setString(2, serverUUID.toString());
statement.setLong(3, session.getUnsafe(SessionKeys.START));
statement.setLong(4, session.getUnsafe(SessionKeys.END));
// World ID select statement
statement.setString(5, worldName);
statement.setString(6, serverUUID.toString());
statement.setString(7, uuid.toString());
statement.setString(8, serverUUID.toString());
statement.setLong(9, gmTimes.getTime(gms[0]));
statement.setLong(10, gmTimes.getTime(gms[1]));
statement.setLong(11, gmTimes.getTime(gms[2]));
statement.setLong(12, gmTimes.getTime(gms[3]));
statement.addBatch();
}
} }
} }
}; };

View File

@ -22,7 +22,6 @@ import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.keys.SessionKeys; import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.db.DBType; import com.djrapitops.plan.db.DBType;
import com.djrapitops.plan.db.SQLDB; import com.djrapitops.plan.db.SQLDB;
import com.djrapitops.plan.db.access.ExecStatement;
import com.djrapitops.plan.db.access.QueryStatement; import com.djrapitops.plan.db.access.QueryStatement;
import com.djrapitops.plan.db.patches.KillsOptimizationPatch; import com.djrapitops.plan.db.patches.KillsOptimizationPatch;
import com.djrapitops.plan.db.patches.KillsServerIDPatch; import com.djrapitops.plan.db.patches.KillsServerIDPatch;
@ -30,7 +29,6 @@ import com.djrapitops.plan.db.patches.Version10Patch;
import com.djrapitops.plan.db.sql.parsing.CreateTableParser; import com.djrapitops.plan.db.sql.parsing.CreateTableParser;
import com.djrapitops.plan.db.sql.parsing.Sql; import com.djrapitops.plan.db.sql.parsing.Sql;
import com.djrapitops.plan.db.sql.queries.LargeFetchQueries; import com.djrapitops.plan.db.sql.queries.LargeFetchQueries;
import com.djrapitops.plugin.utilities.Verify;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -63,24 +61,18 @@ public class KillsTable extends Table {
public static final String WEAPON = "weapon"; public static final String WEAPON = "weapon";
public static final String DATE = "date"; public static final String DATE = "date";
private final UsersTable usersTable; public static final String INSERT_STATEMENT = "INSERT INTO " + TABLE_NAME + " ("
+ SESSION_ID + ", "
public KillsTable(SQLDB db) {
super(TABLE_NAME, db);
usersTable = db.getUsersTable();
sessionsTable = db.getSessionsTable();
insertStatement = "INSERT INTO " + tableName + " ("
+ KILLER_UUID + ", " + KILLER_UUID + ", "
+ VICTIM_UUID + ", " + VICTIM_UUID + ", "
+ SERVER_UUID + ", " + SERVER_UUID + ", "
+ SESSION_ID + ", "
+ DATE + ", " + DATE + ", "
+ WEAPON + WEAPON
+ ") VALUES (?, ?, ?, ?, ?, ?)"; + ") VALUES (" + SessionsTable.SELECT_SESSION_ID_STATEMENT + ", ?, ?, ?, ?, ?)";
}
private final SessionsTable sessionsTable; public KillsTable(SQLDB db) {
private String insertStatement; super(TABLE_NAME, db);
}
public static String createTableSQL(DBType dbType) { public static String createTableSQL(DBType dbType) {
return CreateTableParser.create(TABLE_NAME, dbType) return CreateTableParser.create(TABLE_NAME, dbType)
@ -95,17 +87,38 @@ public class KillsTable extends Table {
.toString(); .toString();
} }
public static void addSessionKillsToBatch(PreparedStatement statement, Session session) throws SQLException {
UUID uuid = session.getUnsafe(SessionKeys.UUID);
UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID);
for (PlayerKill kill : session.getPlayerKills()) {
// Session ID select statement parameters
statement.setString(1, uuid.toString());
statement.setString(2, serverUUID.toString());
statement.setLong(3, session.getUnsafe(SessionKeys.START));
statement.setLong(4, session.getUnsafe(SessionKeys.END));
// Kill data
statement.setString(5, uuid.toString());
statement.setString(6, kill.getVictim().toString());
statement.setString(7, serverUUID.toString());
statement.setLong(8, kill.getDate());
statement.setString(9, kill.getWeapon());
statement.addBatch();
}
}
public void addKillsToSessions(UUID uuid, Map<Integer, Session> sessions) { public void addKillsToSessions(UUID uuid, Map<Integer, Session> sessions) {
String usersUUIDColumn = usersTable + "." + UsersTable.USER_UUID; String usersUUIDColumn = UsersTable.TABLE_NAME + "." + UsersTable.USER_UUID;
String usersNameColumn = usersTable + "." + UsersTable.USER_NAME + " as victim_name"; String usersNameColumn = UsersTable.TABLE_NAME + "." + UsersTable.USER_NAME + " as victim_name";
String sql = "SELECT " + String sql = "SELECT " +
SESSION_ID + ", " + SESSION_ID + ", " +
DATE + ", " + DATE + ", " +
WEAPON + ", " + WEAPON + ", " +
VICTIM_UUID + ", " + VICTIM_UUID + ", " +
usersNameColumn + usersNameColumn +
" FROM " + tableName + " FROM " + TABLE_NAME +
" INNER JOIN " + usersTable + " on " + usersUUIDColumn + "=" + VICTIM_UUID + " INNER JOIN " + UsersTable.TABLE_NAME + " on " + usersUUIDColumn + "=" + VICTIM_UUID +
" WHERE " + KILLER_UUID + "=?"; " WHERE " + KILLER_UUID + "=?";
query(new QueryStatement<Object>(sql, 50000) { query(new QueryStatement<Object>(sql, 50000) {
@ -134,16 +147,16 @@ public class KillsTable extends Table {
} }
public void addDeathsToSessions(UUID uuid, Map<Integer, Session> sessions) { public void addDeathsToSessions(UUID uuid, Map<Integer, Session> sessions) {
String usersUUIDColumn = usersTable + "." + UsersTable.USER_UUID; String usersUUIDColumn = UsersTable.TABLE_NAME + "." + UsersTable.USER_UUID;
String usersNameColumn = usersTable + "." + UsersTable.USER_NAME + " as killer_name"; String usersNameColumn = UsersTable.TABLE_NAME + "." + UsersTable.USER_NAME + " as killer_name";
String sql = "SELECT " + String sql = "SELECT " +
SESSION_ID + ", " + SESSION_ID + ", " +
DATE + ", " + DATE + ", " +
WEAPON + ", " + WEAPON + ", " +
KILLER_UUID + ", " + KILLER_UUID + ", " +
usersNameColumn + usersNameColumn +
" FROM " + tableName + " FROM " + TABLE_NAME +
" INNER JOIN " + usersTable + " on " + usersUUIDColumn + "=" + KILLER_UUID + " INNER JOIN " + UsersTable.TABLE_NAME + " on " + usersUUIDColumn + "=" + KILLER_UUID +
" WHERE " + VICTIM_UUID + "=?"; " WHERE " + VICTIM_UUID + "=?";
query(new QueryStatement<Object>(sql, 50000) { query(new QueryStatement<Object>(sql, 50000) {
@ -171,34 +184,6 @@ public class KillsTable extends Table {
}); });
} }
public void savePlayerKills(UUID uuid, int sessionID, List<PlayerKill> playerKills) {
if (Verify.isEmpty(playerKills)) {
return;
}
executeBatch(new ExecStatement(insertStatement) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
for (PlayerKill kill : playerKills) {
UUID victim = kill.getVictim();
long date = kill.getDate();
String weapon = kill.getWeapon();
if (Verify.containsNull(victim, uuid)) {
continue;
}
statement.setString(1, uuid.toString());
statement.setString(2, victim.toString());
statement.setString(3, getServerUUID().toString());
statement.setInt(4, sessionID);
statement.setLong(5, date);
statement.setString(6, weapon);
statement.addBatch();
}
}
});
}
public void addKillsToSessions(Map<UUID, Map<UUID, List<Session>>> map) { public void addKillsToSessions(Map<UUID, Map<UUID, List<Session>>> map) {
Map<Integer, List<PlayerKill>> playerKillsBySessionID = db.query(LargeFetchQueries.fetchAllPlayerKillDataBySessionID()); Map<Integer, List<PlayerKill>> playerKillsBySessionID = db.query(LargeFetchQueries.fetchAllPlayerKillDataBySessionID());
for (UUID serverUUID : map.keySet()) { for (UUID serverUUID : map.keySet()) {

View File

@ -20,7 +20,6 @@ import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.keys.SessionKeys; import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.db.DBType; import com.djrapitops.plan.db.DBType;
import com.djrapitops.plan.db.SQLDB; import com.djrapitops.plan.db.SQLDB;
import com.djrapitops.plan.db.access.ExecStatement;
import com.djrapitops.plan.db.access.QueryAllStatement; import com.djrapitops.plan.db.access.QueryAllStatement;
import com.djrapitops.plan.db.access.QueryStatement; import com.djrapitops.plan.db.access.QueryStatement;
import com.djrapitops.plan.db.patches.SessionAFKTimePatch; import com.djrapitops.plan.db.patches.SessionAFKTimePatch;
@ -93,79 +92,6 @@ public class SessionsTable extends Table {
.toString(); .toString();
} }
/**
* Used to get the sessionID of a newly inserted row.
*
* @param uuid UUID of the player
* @param session session inserted.
* @return ID of the inserted session or -1 if session has not been inserted.
*/
private int getSessionID(UUID uuid, Session session) {
String sql = "SELECT " + ID + " FROM " + tableName +
" WHERE " + USER_UUID + "=?" +
" AND " + SESSION_START + "=?" +
" AND " + SESSION_END + "=?";
return query(new QueryStatement<Integer>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, uuid.toString());
statement.setLong(2, session.getUnsafe(SessionKeys.START));
statement.setLong(3, session.getValue(SessionKeys.END).orElse(System.currentTimeMillis()));
}
@Override
public Integer processResults(ResultSet set) throws SQLException {
if (set.next()) {
return set.getInt(ID);
}
return -1;
}
});
}
/**
* Used to save a session, with all it's information into the database.
* <p>
* Also saves WorldTimes and Kills.
*
* @param uuid UUID of the player.
* @param session Session of the player that has ended ({@code endSession} has been called)
*/
public void saveSession(UUID uuid, Session session) {
saveSessionInformation(uuid, session);
int sessionID = getSessionID(uuid, session);
if (sessionID == -1) {
throw new IllegalStateException("Session was not Saved!");
}
db.getWorldTimesTable().saveWorldTimes(uuid, sessionID, session.getUnsafe(SessionKeys.WORLD_TIMES));
db.getKillsTable().savePlayerKills(uuid, sessionID, session.getPlayerKills());
}
/**
* Saves Session's Information to the Session Table.
* <p>
* Does not save Kills or WorldTimes.
*
* @param uuid UUID of the player.
* @param session Session of the player that has ended ({@code endSession} has been called)
*/
private void saveSessionInformation(UUID uuid, Session session) {
execute(new ExecStatement(INSERT_STATEMENT) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, uuid.toString());
statement.setLong(2, session.getUnsafe(SessionKeys.START));
statement.setLong(3, session.getUnsafe(SessionKeys.END));
statement.setInt(4, session.getUnsafe(SessionKeys.DEATH_COUNT));
statement.setInt(5, session.getUnsafe(SessionKeys.MOB_KILL_COUNT));
statement.setLong(6, session.getUnsafe(SessionKeys.AFK_TIME));
statement.setString(7, getServerUUID().toString());
}
});
}
/** /**
* Returns a Map containing Lists of sessions, key as ServerName. * Returns a Map containing Lists of sessions, key as ServerName.
* <p> * <p>

View File

@ -22,7 +22,6 @@ import com.djrapitops.plan.data.time.GMTimes;
import com.djrapitops.plan.data.time.WorldTimes; import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.DBType; import com.djrapitops.plan.db.DBType;
import com.djrapitops.plan.db.SQLDB; import com.djrapitops.plan.db.SQLDB;
import com.djrapitops.plan.db.access.ExecStatement;
import com.djrapitops.plan.db.access.QueryAllStatement; import com.djrapitops.plan.db.access.QueryAllStatement;
import com.djrapitops.plan.db.access.QueryStatement; import com.djrapitops.plan.db.access.QueryStatement;
import com.djrapitops.plan.db.patches.Version10Patch; import com.djrapitops.plan.db.patches.Version10Patch;
@ -31,7 +30,6 @@ import com.djrapitops.plan.db.patches.WorldTimesSeverIDPatch;
import com.djrapitops.plan.db.patches.WorldsServerIDPatch; import com.djrapitops.plan.db.patches.WorldsServerIDPatch;
import com.djrapitops.plan.db.sql.parsing.CreateTableParser; import com.djrapitops.plan.db.sql.parsing.CreateTableParser;
import com.djrapitops.plan.db.sql.parsing.Sql; import com.djrapitops.plan.db.sql.parsing.Sql;
import com.djrapitops.plugin.utilities.Verify;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -65,26 +63,22 @@ public class WorldTimesTable extends Table {
public static final String ADVENTURE = "adventure_time"; public static final String ADVENTURE = "adventure_time";
public static final String SPECTATOR = "spectator_time"; public static final String SPECTATOR = "spectator_time";
private final WorldTable worldTable; public static final String INSERT_STATEMENT = "INSERT INTO " + WorldTimesTable.TABLE_NAME + " (" +
private final SessionsTable sessionsTable; WorldTimesTable.SESSION_ID + ", " +
private String insertStatement; WorldTimesTable.WORLD_ID + ", " +
WorldTimesTable.USER_UUID + ", " +
WorldTimesTable.SERVER_UUID + ", " +
WorldTimesTable.SURVIVAL + ", " +
WorldTimesTable.CREATIVE + ", " +
WorldTimesTable.ADVENTURE + ", " +
WorldTimesTable.SPECTATOR +
") VALUES ( " +
SessionsTable.SELECT_SESSION_ID_STATEMENT + ", " +
WorldTable.SELECT_WORLD_ID_STATEMENT + ", " +
"?, ?, ?, ?, ?, ?)";
public WorldTimesTable(SQLDB db) { public WorldTimesTable(SQLDB db) {
super(TABLE_NAME, db); super(TABLE_NAME, db);
worldTable = db.getWorldTable();
sessionsTable = db.getSessionsTable();
insertStatement = "INSERT INTO " + tableName + " (" +
USER_UUID + ", " +
WORLD_ID + ", " +
SERVER_UUID + ", " +
SESSION_ID + ", " +
SURVIVAL + ", " +
CREATIVE + ", " +
ADVENTURE + ", " +
SPECTATOR +
") VALUES (?, " +
WorldTable.SELECT_WORLD_ID_STATEMENT + ", " +
"?, ?, ?, ?, ?, ?)";
} }
public static String createTableSQL(DBType dbType) { public static String createTableSQL(DBType dbType) {
@ -103,9 +97,37 @@ public class WorldTimesTable extends Table {
.toString(); .toString();
} }
public static void addSessionWorldTimesToBatch(PreparedStatement statement, Session session, String[] gms) throws SQLException {
UUID uuid = session.getUnsafe(SessionKeys.UUID);
UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID);
Map<String, GMTimes> worldTimes = session.getUnsafe(SessionKeys.WORLD_TIMES).getWorldTimes();
for (Map.Entry<String, GMTimes> worldTimesEntry : worldTimes.entrySet()) {
String worldName = worldTimesEntry.getKey();
GMTimes gmTimes = worldTimesEntry.getValue();
// Session ID select statement
statement.setString(1, uuid.toString());
statement.setString(2, serverUUID.toString());
statement.setLong(3, session.getUnsafe(SessionKeys.START));
statement.setLong(4, session.getUnsafe(SessionKeys.END));
// World ID select statement
statement.setString(5, worldName);
statement.setString(6, serverUUID.toString());
statement.setString(7, uuid.toString());
statement.setString(8, serverUUID.toString());
statement.setLong(9, gmTimes.getTime(gms[0]));
statement.setLong(10, gmTimes.getTime(gms[1]));
statement.setLong(11, gmTimes.getTime(gms[2]));
statement.setLong(12, gmTimes.getTime(gms[3]));
statement.addBatch();
}
}
public void addWorldTimesToSessions(UUID uuid, Map<Integer, Session> sessions) { public void addWorldTimesToSessions(UUID uuid, Map<Integer, Session> sessions) {
String worldIDColumn = worldTable + "." + WorldTable.ID; String worldIDColumn = WorldTable.TABLE_NAME + "." + WorldTable.ID;
String worldNameColumn = worldTable + "." + WorldTable.NAME + " as world_name"; String worldNameColumn = WorldTable.TABLE_NAME + "." + WorldTable.NAME + " as world_name";
String sql = "SELECT " + String sql = "SELECT " +
SESSION_ID + ", " + SESSION_ID + ", " +
SURVIVAL + ", " + SURVIVAL + ", " +
@ -113,8 +135,8 @@ public class WorldTimesTable extends Table {
ADVENTURE + ", " + ADVENTURE + ", " +
SPECTATOR + ", " + SPECTATOR + ", " +
worldNameColumn + worldNameColumn +
" FROM " + tableName + " FROM " + TABLE_NAME +
" INNER JOIN " + worldTable + " on " + worldIDColumn + "=" + WORLD_ID + " INNER JOIN " + WorldTable.TABLE_NAME + " on " + worldIDColumn + "=" + WORLD_ID +
" WHERE " + USER_UUID + "=?"; " WHERE " + USER_UUID + "=?";
query(new QueryStatement<Object>(sql, 2000) { query(new QueryStatement<Object>(sql, 2000) {
@ -151,50 +173,17 @@ public class WorldTimesTable extends Table {
}); });
} }
public void saveWorldTimes(UUID uuid, int sessionID, WorldTimes worldTimes) {
Map<String, GMTimes> worldTimesMap = worldTimes.getWorldTimes();
if (Verify.isEmpty(worldTimesMap)) {
return;
}
Set<String> worldNames = worldTimesMap.keySet();
db.getWorldTable().saveWorlds(worldNames);
executeBatch(new ExecStatement(insertStatement) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
for (Map.Entry<String, GMTimes> entry : worldTimesMap.entrySet()) {
String worldName = entry.getKey();
GMTimes gmTimes = entry.getValue();
statement.setString(1, uuid.toString());
statement.setString(2, worldName);
String serverUUID = getServerUUID().toString();
statement.setString(3, serverUUID);
statement.setString(4, serverUUID);
statement.setInt(5, sessionID);
String[] gms = GMTimes.getGMKeyArray();
statement.setLong(6, gmTimes.getTime(gms[0]));
statement.setLong(7, gmTimes.getTime(gms[1]));
statement.setLong(8, gmTimes.getTime(gms[2]));
statement.setLong(9, gmTimes.getTime(gms[3]));
statement.addBatch();
}
}
});
}
public WorldTimes getWorldTimesOfUser(UUID uuid) { public WorldTimes getWorldTimesOfUser(UUID uuid) {
String worldIDColumn = worldTable + "." + WorldTable.ID; String worldIDColumn = WorldTable.TABLE_NAME + "." + WorldTable.ID;
String worldNameColumn = worldTable + "." + WorldTable.NAME + " as world_name"; String worldNameColumn = WorldTable.TABLE_NAME + "." + WorldTable.NAME + " as world_name";
String sql = "SELECT " + String sql = "SELECT " +
"SUM(" + SURVIVAL + ") as survival, " + "SUM(" + SURVIVAL + ") as survival, " +
"SUM(" + CREATIVE + ") as creative, " + "SUM(" + CREATIVE + ") as creative, " +
"SUM(" + ADVENTURE + ") as adventure, " + "SUM(" + ADVENTURE + ") as adventure, " +
"SUM(" + SPECTATOR + ") as spectator, " + "SUM(" + SPECTATOR + ") as spectator, " +
worldNameColumn + worldNameColumn +
" FROM " + tableName + " FROM " + TABLE_NAME +
" INNER JOIN " + worldTable + " on " + worldIDColumn + "=" + WORLD_ID + " INNER JOIN " + WorldTable.TABLE_NAME + " on " + worldIDColumn + "=" + WORLD_ID +
" WHERE " + USER_UUID + "=?" + " WHERE " + USER_UUID + "=?" +
" GROUP BY " + WORLD_ID; " GROUP BY " + WORLD_ID;
@ -227,8 +216,8 @@ public class WorldTimesTable extends Table {
} }
public Map<Integer, WorldTimes> getAllWorldTimesBySessionID() { public Map<Integer, WorldTimes> getAllWorldTimesBySessionID() {
String worldIDColumn = worldTable + "." + WorldTable.ID; String worldIDColumn = WorldTable.TABLE_NAME + "." + WorldTable.ID;
String worldNameColumn = worldTable + "." + WorldTable.NAME + " as world_name"; String worldNameColumn = WorldTable.TABLE_NAME + "." + WorldTable.NAME + " as world_name";
String sql = "SELECT " + String sql = "SELECT " +
SESSION_ID + ", " + SESSION_ID + ", " +
SURVIVAL + ", " + SURVIVAL + ", " +
@ -236,8 +225,8 @@ public class WorldTimesTable extends Table {
ADVENTURE + ", " + ADVENTURE + ", " +
SPECTATOR + ", " + SPECTATOR + ", " +
worldNameColumn + worldNameColumn +
" FROM " + tableName + " FROM " + TABLE_NAME +
" INNER JOIN " + worldTable + " on " + worldIDColumn + "=" + WORLD_ID; " INNER JOIN " + WorldTable.TABLE_NAME + " on " + worldIDColumn + "=" + WORLD_ID;
return query(new QueryAllStatement<Map<Integer, WorldTimes>>(sql, 50000) { return query(new QueryAllStatement<Map<Integer, WorldTimes>>(sql, 50000) {
@Override @Override
@ -285,16 +274,11 @@ public class WorldTimesTable extends Table {
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (!(o instanceof WorldTimesTable)) return false; if (!(o instanceof WorldTimesTable)) return false;
if (!super.equals(o)) return false; return super.equals(o);
WorldTimesTable that = (WorldTimesTable) o;
return Objects.equals(worldTable, that.worldTable) &&
Objects.equals(sessionsTable, that.sessionsTable) &&
Objects.equals(insertStatement, that.insertStatement);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(super.hashCode(), worldTable, sessionsTable, insertStatement); return Objects.hash(super.hashCode());
} }
} }

View File

@ -16,11 +16,13 @@
*/ */
package com.djrapitops.plan.system.cache; package com.djrapitops.plan.system.cache;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plugin.logging.error.ErrorHandler; import com.djrapitops.plugin.logging.error.ErrorHandler;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -39,8 +41,9 @@ public class ProxyDataCache extends DataCache {
} }
@Override @Override
public void endSession(UUID uuid, long time) { public Optional<Session> endSession(UUID uuid, long time) {
removeSessionFromCache(uuid); removeSessionFromCache(uuid);
/* Proxy should not save sessions so session is not removed.. */ /* Proxy should not save sessions so session is not removed.. */
return Optional.empty();
} }
} }

View File

@ -78,18 +78,17 @@ public class SessionCache {
* @param time Time the session ended. * @param time Time the session ended.
* @throws com.djrapitops.plan.api.exceptions.database.DBOpException If saving failed. * @throws com.djrapitops.plan.api.exceptions.database.DBOpException If saving failed.
*/ */
public void endSession(UUID uuid, long time) { public Optional<Session> endSession(UUID uuid, long time) {
Session session = activeSessions.get(uuid); Session session = activeSessions.get(uuid);
if (session == null) { if (session == null || session.getUnsafe(SessionKeys.START) > time) {
return; return Optional.empty();
}
if (session.getUnsafe(SessionKeys.START) > time) {
return;
} }
try { try {
session.endSession(time); session.endSession(time);
// Might throw a DBOpException // Might throw a DBOpException
// TODO Refactor to use Event transactions when available.
dbSystem.getDatabase().save().session(uuid, session); dbSystem.getDatabase().save().session(uuid, session);
return Optional.of(session);
} finally { } finally {
removeSessionFromCache(uuid); removeSessionFromCache(uuid);
} }

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.data.container.*;
import com.djrapitops.plan.data.store.objects.Nickname; import com.djrapitops.plan.data.store.objects.Nickname;
import com.djrapitops.plan.db.SQLDB; import com.djrapitops.plan.db.SQLDB;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.db.sql.queries.DataStoreQueries;
import com.djrapitops.plan.db.sql.queries.LargeStoreQueries; import com.djrapitops.plan.db.sql.queries.LargeStoreQueries;
import com.djrapitops.plan.system.database.databases.operation.SaveOperations; import com.djrapitops.plan.system.database.databases.operation.SaveOperations;
import com.djrapitops.plan.system.info.server.Server; import com.djrapitops.plan.system.info.server.Server;
@ -173,7 +174,12 @@ public class SQLSaveOps extends SQLOps implements SaveOperations {
@Override @Override
public void session(UUID uuid, Session session) { public void session(UUID uuid, Session session) {
sessionsTable.saveSession(uuid, session); db.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(DataStoreQueries.storeSession(session));
}
});
} }
@Override @Override

View File

@ -28,14 +28,12 @@ import com.djrapitops.plan.data.store.keys.*;
import com.djrapitops.plan.data.store.objects.Nickname; import com.djrapitops.plan.data.store.objects.Nickname;
import com.djrapitops.plan.data.time.GMTimes; import com.djrapitops.plan.data.time.GMTimes;
import com.djrapitops.plan.data.time.WorldTimes; import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.access.Executable;
import com.djrapitops.plan.db.access.Query; import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.transactions.*; import com.djrapitops.plan.db.access.transactions.*;
import com.djrapitops.plan.db.access.transactions.events.CommandStoreTransaction; import com.djrapitops.plan.db.access.transactions.events.CommandStoreTransaction;
import com.djrapitops.plan.db.patches.Patch; import com.djrapitops.plan.db.patches.Patch;
import com.djrapitops.plan.db.sql.queries.AggregateQueries; import com.djrapitops.plan.db.sql.queries.*;
import com.djrapitops.plan.db.sql.queries.LargeFetchQueries;
import com.djrapitops.plan.db.sql.queries.LargeStoreQueries;
import com.djrapitops.plan.db.sql.queries.OptionalFetchQueries;
import com.djrapitops.plan.db.sql.queries.containers.ContainerFetchQueries; import com.djrapitops.plan.db.sql.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.db.sql.tables.*; import com.djrapitops.plan.db.sql.tables.*;
import com.djrapitops.plan.system.PlanSystem; import com.djrapitops.plan.system.PlanSystem;
@ -133,6 +131,15 @@ public abstract class CommonDBTest {
assertEquals(serverUUID, db.getServerUUIDSupplier().get()); assertEquals(serverUUID, db.getServerUUIDSupplier().get());
} }
private void execute(Executable executable) {
db.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(executable);
}
});
}
public void commitTest() throws DBInitException { public void commitTest() throws DBInitException {
db.close(); db.close();
db.init(); db.init();
@ -351,7 +358,7 @@ public abstract class CommonDBTest {
assertEquals(expectedLength, session.getUnsafe(SessionKeys.WORLD_TIMES).getTotal()); assertEquals(expectedLength, session.getUnsafe(SessionKeys.WORLD_TIMES).getTotal());
SessionsTable sessionsTable = db.getSessionsTable(); SessionsTable sessionsTable = db.getSessionsTable();
sessionsTable.saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
commitTest(); commitTest();
@ -377,7 +384,7 @@ public abstract class CommonDBTest {
session.setPlayerKills(createKills()); session.setPlayerKills(createKills());
SessionsTable sessionsTable = db.getSessionsTable(); SessionsTable sessionsTable = db.getSessionsTable();
sessionsTable.saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
commitTest(); commitTest();
@ -508,7 +515,7 @@ public abstract class CommonDBTest {
session.setWorldTimes(createWorldTimes()); session.setWorldTimes(createWorldTimes());
session.setPlayerKills(createKills()); session.setPlayerKills(createKills());
sessionsTable.saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
nicknamesTable.saveUserName(playerUUID, new Nickname("TestNick", System.currentTimeMillis(), serverUUID)); nicknamesTable.saveUserName(playerUUID, new Nickname("TestNick", System.currentTimeMillis(), serverUUID));
geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L, "3")); geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L, "3"));
@ -567,7 +574,7 @@ public abstract class CommonDBTest {
session.setWorldTimes(createWorldTimes()); session.setWorldTimes(createWorldTimes());
session.setPlayerKills(createKills()); session.setPlayerKills(createKills());
sessionsTable.saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
nicknamesTable.saveUserName(playerUUID, new Nickname("TestNick", System.currentTimeMillis(), serverUUID)); nicknamesTable.saveUserName(playerUUID, new Nickname("TestNick", System.currentTimeMillis(), serverUUID));
geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L, geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L,
new SHA256Hash("1.2.3.4").create())); new SHA256Hash("1.2.3.4").create()));
@ -623,7 +630,7 @@ public abstract class CommonDBTest {
session.setPlayerKills(createKills()); session.setPlayerKills(createKills());
SessionsTable sessionsTable = db.getSessionsTable(); SessionsTable sessionsTable = db.getSessionsTable();
sessionsTable.saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
commitTest(); commitTest();
@ -647,7 +654,7 @@ public abstract class CommonDBTest {
Session session = createSession(); Session session = createSession();
List<PlayerKill> expected = createKills(); List<PlayerKill> expected = createKills();
session.setPlayerKills(expected); session.setPlayerKills(expected);
db.getSessionsTable().saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
commitTest(); commitTest();
@ -710,7 +717,7 @@ public abstract class CommonDBTest {
Session session = new Session(1, playerUUID, serverUUID, 12345L, 23456L, 0, 0, 0); Session session = new Session(1, playerUUID, serverUUID, 12345L, 23456L, 0, 0, 0);
session.setWorldTimes(worldTimes); session.setWorldTimes(worldTimes);
db.getSessionsTable().saveSession(playerUUID, session); execute(DataStoreQueries.storeSession(session));
Map<Integer, Session> sessions = new HashMap<>(); Map<Integer, Session> sessions = new HashMap<>();
sessions.put(1, session); sessions.put(1, session);

View File

@ -17,9 +17,11 @@
package com.djrapitops.plan.system.webserver; package com.djrapitops.plan.system.webserver;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.db.sql.queries.DataStoreQueries;
import com.djrapitops.plan.system.PlanSystem; import com.djrapitops.plan.system.PlanSystem;
import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.database.databases.operation.SaveOperations;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.WebserverSettings; import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.djrapitops.plan.system.webserver.cache.PageId; import com.djrapitops.plan.system.webserver.cache.PageId;
@ -76,12 +78,18 @@ public class JSErrorRegressionTest {
private static void savePlayerData() { private static void savePlayerData() {
DBSystem dbSystem = bukkitSystem.getDatabaseSystem(); DBSystem dbSystem = bukkitSystem.getDatabaseSystem();
SaveOperations save = dbSystem.getDatabase().save(); Database database = dbSystem.getDatabase();
UUID uuid = TestConstants.PLAYER_ONE_UUID; UUID uuid = TestConstants.PLAYER_ONE_UUID;
save.registerNewUser(uuid, 1000L, "TestPlayer"); database.save().registerNewUser(uuid, 1000L, "TestPlayer");
Session session = new Session(uuid, TestConstants.SERVER_UUID, 1000L, "world", "SURVIVAL"); Session session = new Session(uuid, TestConstants.SERVER_UUID, 1000L, "world", "SURVIVAL");
session.endSession(11000L); session.endSession(11000L);
save.session(uuid, session); database.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(DataStoreQueries.storeSession(session));
}
});
// TODO Refactor to use Event transactions when available.
} }
@After @After