From 5a5110d90581825b0f2936230ecee10a45b854a9 Mon Sep 17 00:00:00 2001 From: P0nk Date: Fri, 16 Apr 2021 20:37:51 +0200 Subject: [PATCH] Use existing connection for loading new year + family Move async tasks earlier for lower chance of having to wait --- src/main/java/client/MapleFamily.java | 164 +++++++++--------- .../client/newyear/NewYearCardRecord.java | 24 ++- src/main/java/net/server/Server.java | 102 +++++------ 3 files changed, 144 insertions(+), 146 deletions(-) diff --git a/src/main/java/client/MapleFamily.java b/src/main/java/client/MapleFamily.java index 8f1b008feb..60bf97b092 100644 --- a/src/main/java/client/MapleFamily.java +++ b/src/main/java/client/MapleFamily.java @@ -182,97 +182,95 @@ public class MapleFamily { } } - public static void loadAllFamilies() { - try(Connection con = DatabaseConnection.getConnection()) { - List, MapleFamilyEntry>> unmatchedJuniors = new ArrayList<>(200); // < familyEntry> - try(PreparedStatement psEntries = con.prepareStatement("SELECT * FROM family_character")) { - ResultSet rsEntries = psEntries.executeQuery(); - while(rsEntries.next()) { // can be optimized - int cid = rsEntries.getInt("cid"); - String name = null; - int level = -1; - int jobID = -1; - int world = -1; - try(PreparedStatement ps = con.prepareStatement("SELECT world, name, level, job FROM characters WHERE id = ?")) { - ps.setInt(1, cid); - ResultSet rs = ps.executeQuery(); - if(rs.next()) { - world = rs.getInt("world"); - name = rs.getString("name"); - level = rs.getInt("level"); - jobID = rs.getInt("job"); - } else { - FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not load character information of " + cid + " in loadAllFamilies(). (RECORD DOES NOT EXIST)"); - continue; - } - } catch(SQLException e) { - FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not load character information of " + cid + " in loadAllFamilies(). (SQL ERROR)"); - continue; - } - int familyid = rsEntries.getInt("familyid"); - int seniorid = rsEntries.getInt("seniorid"); - int reputation = rsEntries.getInt("reputation"); - int todaysRep = rsEntries.getInt("todaysrep"); - int totalRep = rsEntries.getInt("totalreputation"); - int repsToSenior = rsEntries.getInt("reptosenior"); - String precepts = rsEntries.getString("precepts"); - //Timestamp lastResetTime = rsEntries.getTimestamp("lastresettime"); //taken care of by FamilyDailyResetTask - World wserv = Server.getInstance().getWorld(world); - if (wserv == null) { - continue; - } - MapleFamily family = wserv.getFamily(familyid); - if(family == null) { - family = new MapleFamily(familyid, world); - Server.getInstance().getWorld(world).addFamily(familyid, family); - } - MapleFamilyEntry familyEntry = new MapleFamilyEntry(family, cid, name, level, MapleJob.getById(jobID)); - family.addEntry(familyEntry); - if(seniorid <= 0) { - family.setLeader(familyEntry); - family.setMessage(precepts, false); - } - MapleFamilyEntry senior = family.getEntryByID(seniorid); - if(senior != null) { - familyEntry.setSenior(family.getEntryByID(seniorid), false); + public static void loadAllFamilies(Connection con) { + List, MapleFamilyEntry>> unmatchedJuniors = new ArrayList<>(200); // < familyEntry> + try (PreparedStatement psEntries = con.prepareStatement("SELECT * FROM family_character")) { + ResultSet rsEntries = psEntries.executeQuery(); + while (rsEntries.next()) { // can be optimized + int cid = rsEntries.getInt("cid"); + String name = null; + int level = -1; + int jobID = -1; + int world = -1; + try (PreparedStatement ps = con.prepareStatement("SELECT world, name, level, job FROM characters WHERE id = ?")) { + ps.setInt(1, cid); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + world = rs.getInt("world"); + name = rs.getString("name"); + level = rs.getInt("level"); + jobID = rs.getInt("job"); } else { - if(seniorid > 0) unmatchedJuniors.add(new Pair<>(new Pair<>(world, seniorid), familyEntry)); - } - familyEntry.setReputation(reputation); - familyEntry.setTodaysRep(todaysRep); - familyEntry.setTotalReputation(totalRep); - familyEntry.setRepsToSenior(repsToSenior); - //load used entitlements - try (PreparedStatement ps = con.prepareStatement("SELECT entitlementid FROM family_entitlement WHERE charid = ?")) { - ps.setInt(1, familyEntry.getChrId()); - ResultSet rs = ps.executeQuery(); - while(rs.next()) { - familyEntry.setEntitlementUsed(rs.getInt("entitlementid")); - } + FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not load character information of " + cid + " in loadAllFamilies(). (RECORD DOES NOT EXIST)"); + continue; } + } catch (SQLException e) { + FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not load character information of " + cid + " in loadAllFamilies(). (SQL ERROR)"); + continue; } - } catch(SQLException e) { - FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get family_character entries."); - e.printStackTrace(); - } - // link missing ones (out of order) - for(Pair, MapleFamilyEntry> unmatchedJunior : unmatchedJuniors) { - int world = unmatchedJunior.getLeft().getLeft(); - int seniorid = unmatchedJunior.getLeft().getRight(); - MapleFamilyEntry junior = unmatchedJunior.getRight(); - MapleFamilyEntry senior = Server.getInstance().getWorld(world).getFamily(junior.getFamily().getID()).getEntryByID(seniorid); - if(senior != null) { - junior.setSenior(senior, false); + int familyid = rsEntries.getInt("familyid"); + int seniorid = rsEntries.getInt("seniorid"); + int reputation = rsEntries.getInt("reputation"); + int todaysRep = rsEntries.getInt("todaysrep"); + int totalRep = rsEntries.getInt("totalreputation"); + int repsToSenior = rsEntries.getInt("reptosenior"); + String precepts = rsEntries.getString("precepts"); + //Timestamp lastResetTime = rsEntries.getTimestamp("lastresettime"); //taken care of by FamilyDailyResetTask + World wserv = Server.getInstance().getWorld(world); + if (wserv == null) { + continue; + } + MapleFamily family = wserv.getFamily(familyid); + if (family == null) { + family = new MapleFamily(familyid, world); + Server.getInstance().getWorld(world).addFamily(familyid, family); + } + MapleFamilyEntry familyEntry = new MapleFamilyEntry(family, cid, name, level, MapleJob.getById(jobID)); + family.addEntry(familyEntry); + if (seniorid <= 0) { + family.setLeader(familyEntry); + family.setMessage(precepts, false); + } + MapleFamilyEntry senior = family.getEntryByID(seniorid); + if (senior != null) { + familyEntry.setSenior(family.getEntryByID(seniorid), false); } else { - FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Missing senior for character " + junior.getName() + " in world " + world); + if (seniorid > 0) { + unmatchedJuniors.add(new Pair<>(new Pair<>(world, seniorid), familyEntry)); + } + } + familyEntry.setReputation(reputation); + familyEntry.setTodaysRep(todaysRep); + familyEntry.setTotalReputation(totalRep); + familyEntry.setRepsToSenior(repsToSenior); + //load used entitlements + try (PreparedStatement ps = con.prepareStatement("SELECT entitlementid FROM family_entitlement WHERE charid = ?")) { + ps.setInt(1, familyEntry.getChrId()); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + familyEntry.setEntitlementUsed(rs.getInt("entitlementid")); + } } } - } catch(SQLException e) { - FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get DB connection."); + } catch (SQLException e) { + FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get family_character entries."); e.printStackTrace(); } - for(World world : Server.getInstance().getWorlds()) { - for(MapleFamily family : world.getFamilies()) { + // link missing ones (out of order) + for (Pair, MapleFamilyEntry> unmatchedJunior : unmatchedJuniors) { + int world = unmatchedJunior.getLeft().getLeft(); + int seniorid = unmatchedJunior.getLeft().getRight(); + MapleFamilyEntry junior = unmatchedJunior.getRight(); + MapleFamilyEntry senior = Server.getInstance().getWorld(world).getFamily(junior.getFamily().getID()).getEntryByID(seniorid); + if (senior != null) { + junior.setSenior(senior, false); + } else { + FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Missing senior for character " + junior.getName() + " in world " + world); + } + } + + for (World world : Server.getInstance().getWorlds()) { + for (MapleFamily family : world.getFamilies()) { family.getLeader().doFullCount(); } } diff --git a/src/main/java/client/newyear/NewYearCardRecord.java b/src/main/java/client/newyear/NewYearCardRecord.java index f86de1b7da..88a7c0212d 100644 --- a/src/main/java/client/newyear/NewYearCardRecord.java +++ b/src/main/java/client/newyear/NewYearCardRecord.java @@ -339,22 +339,18 @@ public class NewYearCardRecord { } } } - - public static void startPendingNewYearCardRequests() { - try (Connection con = DatabaseConnection.getConnection()) { - try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE timereceived = 0 AND senderdiscard = 0")) { - try (ResultSet rs = ps.executeQuery()) { - while (rs.next()) { - NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message")); - newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived")); - - Server.getInstance().setNewYearCard(newyear); - newyear.startNewYearCardTask(); - } + + public static void startPendingNewYearCardRequests(Connection con) throws SQLException { + try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE timereceived = 0 AND senderdiscard = 0")) { + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message")); + newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived")); + + Server.getInstance().setNewYearCard(newyear); + newyear.startNewYearCardTask(); } } - } catch(SQLException sqle) { - sqle.printStackTrace(); } } } diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index e03a42caf1..c053bbb369 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -704,7 +704,7 @@ public class Server { } private void installWorldPlayerRanking(int worldid) { - List>>> ranking = updatePlayerRankingFromDB(worldid); + List>>> ranking = loadPlayerRankingFromDB(worldid); if (!ranking.isEmpty()) { wldWLock.lock(); try { @@ -736,7 +736,7 @@ public class Server { wldWLock.unlock(); } } else { - List>>> ranking = updatePlayerRankingFromDB(-1 * (this.getWorldsSize() - 2)); // update ranking list + List>>> ranking = loadPlayerRankingFromDB(-1 * (this.getWorldsSize() - 2)); // update ranking list wldWLock.lock(); try { @@ -748,40 +748,47 @@ public class Server { } public void updateWorldPlayerRanking() { - List>>> rankUpdates = updatePlayerRankingFromDB(-1 * (this.getWorldsSize() - 1)); - if (!rankUpdates.isEmpty()) { - wldWLock.lock(); - try { - if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { - for (int i = playerRanking.size(); i <= rankUpdates.get(rankUpdates.size() - 1).getLeft(); i++) { - playerRanking.add(new ArrayList<>(0)); - } - - for (Pair>> wranks : rankUpdates) { - playerRanking.set(wranks.getLeft(), wranks.getRight()); - } - } else { - playerRanking.set(0, rankUpdates.get(0).getRight()); - } - } finally { - wldWLock.unlock(); - } + List>>> rankUpdates = loadPlayerRankingFromDB(-1 * (this.getWorldsSize() - 1)); + if (rankUpdates.isEmpty()) { + return; } + + wldWLock.lock(); + try { + if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { + for (int i = playerRanking.size(); i <= rankUpdates.get(rankUpdates.size() - 1).getLeft(); i++) { + playerRanking.add(new ArrayList<>(0)); + } + + for (Pair>> wranks : rankUpdates) { + playerRanking.set(wranks.getLeft(), wranks.getRight()); + } + } else { + playerRanking.set(0, rankUpdates.get(0).getRight()); + } + } finally { + wldWLock.unlock(); + } + } private void initWorldPlayerRanking() { if (YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { - playerRanking.add(new ArrayList<>(0)); + wldWLock.lock(); + try { + playerRanking.add(new ArrayList<>(0)); + } finally { + wldWLock.unlock(); + } } + updateWorldPlayerRanking(); } - private static List>>> updatePlayerRankingFromDB(int worldid) { + private static List>>> loadPlayerRankingFromDB(int worldid) { List>>> rankSystem = new ArrayList<>(); - List> rankUpdate = new ArrayList<>(0); try (Connection con = DatabaseConnection.getConnection()) { - String worldQuery; if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { if (worldid >= 0) { @@ -793,6 +800,7 @@ public class Server { worldQuery = (" AND `characters`.`world` >= 0 AND `characters`.`world` <= " + Math.abs(worldid)); } + List> rankUpdate = new ArrayList<>(0); try (PreparedStatement ps = con.prepareStatement("SELECT `characters`.`name`, `characters`.`level`, `characters`.`world` FROM `characters` LEFT JOIN accounts ON accounts.id = characters.accountid WHERE `characters`.`gm` < 2 AND `accounts`.`banned` = '0'" + worldQuery + " ORDER BY " + (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING ? "world, " : "") + "level DESC, exp DESC, lastExpGainTime ASC LIMIT 50"); ResultSet rs = ps.executeQuery()) { @@ -836,22 +844,6 @@ public class Server { throw new IllegalStateException("Failed to initiate a connection to the database"); } - TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE)); - - try (Connection con = DatabaseConnection.getConnection()) { - setAllLoggedOut(con); - setAllMerchantsInactive(con); - cleanNxcodeCoupons(con); - loadCouponRates(con); - updateActiveCoupons(con); - MapleCashidGenerator.loadExistentCashIdsFromDb(con); - applyAllNameChanges(con); // -- name changes can be missed by INSTANT_NAME_CHANGE -- - applyAllWorldTransfers(con); - } catch (SQLException sqle) { - log.error("Failed to run all startup-bound database tasks", sqle); - throw new IllegalStateException(sqle); - } - final ExecutorService initExecutor = Executors.newFixedThreadPool(10); // Run slow operations asynchronously to make startup faster final List> futures = new ArrayList<>(); @@ -861,11 +853,30 @@ public class Server { futures.add(initExecutor.submit(() -> MapleSkillbookInformationProvider.loadAllSkillbookInformation())); futures.add(initExecutor.submit(() -> MaplePlayerNPCFactory.loadFactoryMetadata())); + TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE)); + + try (Connection con = DatabaseConnection.getConnection()) { + setAllLoggedOut(con); + setAllMerchantsInactive(con); + cleanNxcodeCoupons(con); + loadCouponRates(con); + updateActiveCoupons(con); + NewYearCardRecord.startPendingNewYearCardRequests(con); + MapleCashidGenerator.loadExistentCashIdsFromDb(con); + applyAllNameChanges(con); // -- name changes can be missed by INSTANT_NAME_CHANGE -- + applyAllWorldTransfers(con); + + if (YamlConfig.config.server.USE_FAMILY_SYSTEM) { + MapleFamily.loadAllFamilies(con); + } + } catch (SQLException sqle) { + log.error("Failed to run all startup-bound database tasks", sqle); + throw new IllegalStateException(sqle); + } + ThreadManager.getInstance().start(); initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan - NewYearCardRecord.startPendingNewYearCardRequests(); - if (YamlConfig.config.server.USE_THREAD_TRACKER) { ThreadTracker.getInstance().registerThreadTrackerTask(); } @@ -885,13 +896,6 @@ public class Server { System.exit(0); } - if (YamlConfig.config.server.USE_FAMILY_SYSTEM) { - long timeToTake = System.currentTimeMillis(); - MapleFamily.loadAllFamilies(); - final double familyLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0; - log.info("Families loaded in {} seconds", familyLoadTime); - } - // Wait on all async tasks to complete for (Future future : futures) { try {