Make database operations during startup consistent

Use the same Connection. and log things in a similar fashion
This commit is contained in:
P0nk
2021-04-11 13:33:22 +02:00
parent 858fcd2a3a
commit 68239bc0b5
3 changed files with 65 additions and 55 deletions

View File

@@ -19,6 +19,8 @@
*/ */
package client.inventory.manipulator; package client.inventory.manipulator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import java.sql.Connection; import java.sql.Connection;
@@ -32,7 +34,7 @@ import java.util.Set;
* @author RonanLana * @author RonanLana
*/ */
public class MapleCashidGenerator { public class MapleCashidGenerator {
private static final Logger log = LoggerFactory.getLogger(MapleCashidGenerator.class);
private final static Set<Integer> existentCashids = new HashSet<>(10000); private final static Set<Integer> existentCashids = new HashSet<>(10000);
private static Integer runningCashid = 0; private static Integer runningCashid = 0;
@@ -49,13 +51,9 @@ public class MapleCashidGenerator {
} }
} }
public static synchronized void loadExistentCashIdsFromDb() { public static synchronized void loadExistentCashIdsFromDb(Connection con) throws SQLException {
try (Connection con = DatabaseConnection.getConnection()) { loadExistentCashIdsFromQuery(con, "SELECT id FROM rings");
loadExistentCashIdsFromQuery(con, "SELECT id FROM rings"); loadExistentCashIdsFromQuery(con, "SELECT petid FROM pets");
loadExistentCashIdsFromQuery(con, "SELECT petid FROM pets");
} catch (SQLException ex) {
ex.printStackTrace();
}
runningCashid = 0; runningCashid = 0;
do { do {
@@ -67,7 +65,11 @@ public class MapleCashidGenerator {
runningCashid++; runningCashid++;
if (runningCashid >= 777000000) { if (runningCashid >= 777000000) {
existentCashids.clear(); existentCashids.clear();
loadExistentCashIdsFromDb(); try (Connection con = DatabaseConnection.getConnection()) {
loadExistentCashIdsFromDb(con);
} catch (SQLException e) {
log.warn("Failed to reset overflowing cash ids", e);
}
} }
} }

View File

@@ -80,6 +80,7 @@ import java.sql.Connection;
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.time.Instant;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@@ -625,7 +626,7 @@ public class Server {
} }
} }
public void updateActiveCoupons() throws SQLException { public void updateActiveCoupons(Connection con) throws SQLException {
synchronized (activeCoupons) { synchronized (activeCoupons) {
activeCoupons.clear(); activeCoupons.clear();
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance();
@@ -633,23 +634,19 @@ public class Server {
int weekDay = c.get(Calendar.DAY_OF_WEEK); int weekDay = c.get(Calendar.DAY_OF_WEEK);
int hourDay = c.get(Calendar.HOUR_OF_DAY); int hourDay = c.get(Calendar.HOUR_OF_DAY);
try (Connection con = DatabaseConnection.getConnection()) { int weekdayMask = (1 << weekDay);
PreparedStatement ps = con.prepareStatement("SELECT couponid FROM nxcoupons WHERE (activeday & ?) = ? AND starthour <= ? AND endhour > ?");
ps.setInt(1, weekdayMask);
ps.setInt(2, weekdayMask);
ps.setInt(3, hourDay);
ps.setInt(4, hourDay);
int weekdayMask = (1 << weekDay); try (ResultSet rs = ps.executeQuery()) {
PreparedStatement ps = con.prepareStatement("SELECT couponid FROM nxcoupons WHERE (activeday & ?) = ? AND starthour <= ? AND endhour > ?"); while (rs.next()) {
ps.setInt(1, weekdayMask); activeCoupons.add(rs.getInt("couponid"));
ps.setInt(2, weekdayMask);
ps.setInt(3, hourDay);
ps.setInt(4, hourDay);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
activeCoupons.add(rs.getInt("couponid"));
}
} }
} catch (SQLException ex) {
ex.printStackTrace();
} }
} }
} }
@@ -837,26 +834,19 @@ public class Server {
TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE)); TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE));
try (Connection con = DatabaseConnection.getConnection()) { try (Connection con = DatabaseConnection.getConnection()) {
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0")) { setAllLoggedOut(con);
ps.executeUpdate(); setAllMerchantsInactive(con);
}
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0")) {
ps.executeUpdate();
}
cleanNxcodeCoupons(con); cleanNxcodeCoupons(con);
loadCouponRates(con); loadCouponRates(con);
updateActiveCoupons(); updateActiveCoupons(con);
MapleCashidGenerator.loadExistentCashIdsFromDb(con);
applyAllNameChanges(con); // -- name changes can be missed by INSTANT_NAME_CHANGE --
applyAllWorldTransfers(con);
} catch (SQLException sqle) { } catch (SQLException sqle) {
sqle.printStackTrace(); log.error("Failed to run all startup-bound database tasks", sqle);
throw new IllegalStateException(sqle);
} }
applyAllNameChanges(); // -- name changes can be missed by INSTANT_NAME_CHANGE --
applyAllWorldTransfers();
//MaplePet.clearMissingPetsFromDb(); // thanks Optimist for noticing this taking too long to run
MapleCashidGenerator.loadExistentCashIdsFromDb();
ThreadManager.getInstance().start(); ThreadManager.getInstance().start();
initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan
@@ -931,6 +921,18 @@ public class Server {
} }
} }
private static void setAllLoggedOut(Connection con) throws SQLException {
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0")) {
ps.executeUpdate();
}
}
private static void setAllMerchantsInactive(Connection con) throws SQLException {
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0")) {
ps.executeUpdate();
}
}
private void initializeTimelyTasks() { private void initializeTimelyTasks() {
TimerManager tMan = TimerManager.getInstance(); TimerManager tMan = TimerManager.getInstance();
tMan.start(); tMan.start();
@@ -1570,9 +1572,8 @@ public class Server {
} }
} }
private static void applyAllNameChanges() { private static void applyAllNameChanges(Connection con) throws SQLException {
try (Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL");
PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL");
ResultSet rs = ps.executeQuery()) { ResultSet rs = ps.executeQuery()) {
List<Pair<String, String>> changedNames = new LinkedList<>(); //logging only List<Pair<String, String>> changedNames = new LinkedList<>(); //logging only
@@ -1596,18 +1597,17 @@ public class Server {
} }
//log //log
for (Pair<String, String> namePair : changedNames) { for (Pair<String, String> namePair : changedNames) {
FilePrinter.print(FilePrinter.CHANGE_CHARACTER_NAME, "Name change applied : from \"" + namePair.getLeft() + "\" to \"" + namePair.getRight() + "\" at " + Calendar.getInstance().getTime().toString()); log.info("Name change applied - from: \"{}\" to \"{}\" at {}", namePair.getLeft(), namePair.getRight(), Instant.now());
} }
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); log.warn("Failed to retrieve list of pending name changes", e);
FilePrinter.printError(FilePrinter.CHANGE_CHARACTER_NAME, e, "Failed to retrieve list of pending name changes."); throw e;
} }
} }
private static void applyAllWorldTransfers() { private static void applyAllWorldTransfers(Connection con) throws SQLException {
try (Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL",
PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = ps.executeQuery()) { ResultSet rs = ps.executeQuery()) {
List<Integer> removedTransfers = new LinkedList<>(); List<Integer> removedTransfers = new LinkedList<>();
while (rs.next()) { while (rs.next()) {
@@ -1658,11 +1658,11 @@ public class Server {
int charId = worldTransferPair.getLeft(); int charId = worldTransferPair.getLeft();
int oldWorld = worldTransferPair.getRight().getLeft(); int oldWorld = worldTransferPair.getRight().getLeft();
int newWorld = worldTransferPair.getRight().getRight(); int newWorld = worldTransferPair.getRight().getRight();
FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer applied : Character ID " + charId + " from World " + oldWorld + " to World " + newWorld + " at " + Calendar.getInstance().getTime().toString()); log.info("World transfer applied - character id {} from world {} to world {} at {}", charId, oldWorld, newWorld, Instant.now());
} }
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); log.warn("Failed to retrieve list of pending world transfers", e);
FilePrinter.printError(FilePrinter.WORLD_TRANSFER, e, "Failed to retrieve list of pending world transfers."); throw e;
} }
} }

View File

@@ -19,8 +19,12 @@
*/ */
package net.server.task; package net.server.task;
import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import net.server.Server; import net.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tools.DatabaseConnection;
import tools.FilePrinter; import tools.FilePrinter;
/** /**
@@ -28,13 +32,17 @@ import tools.FilePrinter;
* @info Thread responsible for maintaining coupons EXP & DROP effects active * @info Thread responsible for maintaining coupons EXP & DROP effects active
*/ */
public class CouponTask implements Runnable { public class CouponTask implements Runnable {
private static final Logger log = LoggerFactory.getLogger(CouponTask.class);
@Override @Override
public void run() { public void run() {
try { try {
Server.getInstance().updateActiveCoupons(); try (Connection con = DatabaseConnection.getConnection()) {
Server.getInstance().updateActiveCoupons(con);
}
Server.getInstance().commitActiveCoupons(); Server.getInstance().commitActiveCoupons();
} catch(SQLException sqle) { } catch (SQLException sqle) {
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Unexpected SQL error: " + sqle.getMessage()); log.error("Error updating coupon effects", sqle);
} }
} }
} }