Addition of precautionary restart manager.
This commit is contained in:
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -774,6 +774,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1438,6 +1444,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -427,6 +428,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -784,6 +784,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1449,6 +1455,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -435,6 +436,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -785,6 +785,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1462,6 +1468,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -435,6 +436,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -772,6 +772,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1449,6 +1455,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -435,6 +436,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -767,6 +767,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1444,6 +1450,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -437,6 +438,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -767,6 +767,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1451,6 +1457,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -437,6 +438,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -768,6 +768,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1473,6 +1479,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -439,6 +440,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -773,6 +773,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1484,6 +1490,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -443,6 +444,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -770,6 +770,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Hardin (Agent of Chaos)
|
// Hardin (Agent of Chaos)
|
||||||
@@ -1481,6 +1487,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -441,6 +442,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -309,6 +310,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -324,6 +330,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -158,6 +158,37 @@ ClanNameTemplate = .*
|
|||||||
AllyNameTemplate = .*
|
AllyNameTemplate = .*
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1127,6 +1127,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
public static int IP_UPDATE_TIME;
|
public static int IP_UPDATE_TIME;
|
||||||
public static boolean SHOW_LICENCE;
|
public static boolean SHOW_LICENCE;
|
||||||
@@ -1228,6 +1234,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverConfig.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverConfig.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverConfig.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverConfig.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverConfig.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverConfig.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadTelnetConfig()
|
public static void loadTelnetConfig()
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ import org.l2jmobius.gameserver.instancemanager.IdManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossPointsManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossPointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
||||||
@@ -471,6 +472,11 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
System.gc();
|
System.gc();
|
||||||
|
|
||||||
Util.printSection("Info");
|
Util.printSection("Info");
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.l2jmobius.gameserver.instancemanager.CastleManorManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
@@ -193,6 +194,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -219,6 +225,11 @@ public class Shutdown extends Thread
|
|||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+198
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.enums.ChatType;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers(new CreatureSay(-1, ChatType.ANNOUNCEMENT, "", "Server will restart in 10 minutes."));
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers(new CreatureSay(-1, ChatType.ANNOUNCEMENT, "", "Server will restart in 10 minutes."));
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getAllPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player._inEvent || player.atEvent)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getInstanceId() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -158,6 +158,37 @@ ClanNameTemplate = .*
|
|||||||
AllyNameTemplate = .*
|
AllyNameTemplate = .*
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1162,6 +1162,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
public static int IP_UPDATE_TIME;
|
public static int IP_UPDATE_TIME;
|
||||||
public static boolean SHOW_LICENCE;
|
public static boolean SHOW_LICENCE;
|
||||||
@@ -1263,6 +1269,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverConfig.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverConfig.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverConfig.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverConfig.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverConfig.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverConfig.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadTelnetConfig()
|
public static void loadTelnetConfig()
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ import org.l2jmobius.gameserver.instancemanager.IdManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossPointsManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossPointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
||||||
@@ -483,6 +484,11 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
System.gc();
|
System.gc();
|
||||||
|
|
||||||
Util.printSection("Info");
|
Util.printSection("Info");
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.l2jmobius.gameserver.instancemanager.FishingChampionshipManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
@@ -195,6 +196,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -221,6 +227,11 @@ public class Shutdown extends Thread
|
|||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+198
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.enums.ChatType;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers(new CreatureSay(-1, ChatType.ANNOUNCEMENT, "", "Server will restart in 10 minutes."));
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers(new CreatureSay(-1, ChatType.ANNOUNCEMENT, "", "Server will restart in 10 minutes."));
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getAllPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player._inEvent || player.atEvent)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getInstanceId() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -184,6 +184,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -897,6 +897,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// MMO Settings
|
// MMO Settings
|
||||||
@@ -1482,6 +1488,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ import org.l2jmobius.gameserver.instancemanager.MailManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
|
import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -439,6 +440,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
@@ -313,6 +314,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -328,6 +334,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getInstanceId() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -184,6 +184,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -901,6 +901,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// MMO Settings
|
// MMO Settings
|
||||||
@@ -1481,6 +1487,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ import org.l2jmobius.gameserver.instancemanager.MailManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
|
import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
import org.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -441,6 +442,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
import org.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
@@ -313,6 +314,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -328,6 +334,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getInstanceId() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -774,6 +774,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1380,6 +1386,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -432,6 +433,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -774,6 +774,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1384,6 +1390,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -432,6 +433,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -774,6 +774,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1384,6 +1390,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -432,6 +433,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -774,6 +774,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1384,6 +1390,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -434,6 +435,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -774,6 +774,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1389,6 +1395,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -436,6 +437,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -778,6 +778,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1397,6 +1403,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -440,6 +441,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,6 +203,37 @@ ClanNameTemplate = .*
|
|||||||
CharMaxNumber = 7
|
CharMaxNumber = 7
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Precautionary Server Restart
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable server restart when CPU or memory usage is too high.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartEnabled = False
|
||||||
|
|
||||||
|
# Enable monitoring system CPU usage.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartCpu = True
|
||||||
|
|
||||||
|
# Enable monitoring process memory usage.
|
||||||
|
# Default: False
|
||||||
|
PrecautionaryRestartMemory = False
|
||||||
|
|
||||||
|
# Check if sieges are in progress
|
||||||
|
# or players are in olympiad, events, instances
|
||||||
|
# or have targeted raidbosses.
|
||||||
|
# Default: True
|
||||||
|
PrecautionaryRestartChecks = True
|
||||||
|
|
||||||
|
# Percentage of used resources.
|
||||||
|
# Default: 95
|
||||||
|
PrecautionaryRestartPercentage = 95
|
||||||
|
|
||||||
|
# Delay in seconds between each check.
|
||||||
|
# Default: 60
|
||||||
|
PrecautionaryRestartDelay = 60
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Scheduled Server Restart
|
# Scheduled Server Restart
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -783,6 +783,12 @@ public class Config
|
|||||||
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
public static int SERVER_RESTART_SCHEDULE_COUNTDOWN;
|
||||||
public static String[] SERVER_RESTART_SCHEDULE;
|
public static String[] SERVER_RESTART_SCHEDULE;
|
||||||
public static List<Integer> SERVER_RESTART_DAYS;
|
public static List<Integer> SERVER_RESTART_DAYS;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_ENABLED;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CPU;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_MEMORY;
|
||||||
|
public static boolean PRECAUTIONARY_RESTART_CHECKS;
|
||||||
|
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
|
||||||
|
public static int PRECAUTIONARY_RESTART_DELAY;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Vitality Settings
|
// Vitality Settings
|
||||||
@@ -1398,6 +1404,12 @@ public class Config
|
|||||||
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
SERVER_RESTART_DAYS.add(Integer.parseInt(day));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PRECAUTIONARY_RESTART_ENABLED = serverSettings.getBoolean("PrecautionaryRestartEnabled", false);
|
||||||
|
PRECAUTIONARY_RESTART_CPU = serverSettings.getBoolean("PrecautionaryRestartCpu", true);
|
||||||
|
PRECAUTIONARY_RESTART_MEMORY = serverSettings.getBoolean("PrecautionaryRestartMemory", false);
|
||||||
|
PRECAUTIONARY_RESTART_CHECKS = serverSettings.getBoolean("PrecautionaryRestartChecks", true);
|
||||||
|
PRECAUTIONARY_RESTART_PERCENTAGE = serverSettings.getInt("PrecautionaryRestartPercentage", 95);
|
||||||
|
PRECAUTIONARY_RESTART_DELAY = serverSettings.getInt("PrecautionaryRestartDelay", 60) * 1000;
|
||||||
|
|
||||||
// Hosts and Subnets
|
// Hosts and Subnets
|
||||||
final IPConfigData ipcd = new IPConfigData();
|
final IPConfigData ipcd = new IPConfigData();
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ import org.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
import org.l2jmobius.gameserver.instancemanager.MentorManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
import org.l2jmobius.gameserver.instancemanager.PetitionManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
import org.l2jmobius.gameserver.instancemanager.PremiumManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
import org.l2jmobius.gameserver.instancemanager.PunishmentManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
@@ -432,6 +433,10 @@ public class GameServer
|
|||||||
ServerRestartManager.getInstance();
|
ServerRestartManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance();
|
||||||
|
}
|
||||||
if (Config.DEADLOCK_DETECTOR)
|
if (Config.DEADLOCK_DETECTOR)
|
||||||
{
|
{
|
||||||
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
_deadDetectThread = new DeadLockDetector(Duration.ofSeconds(Config.DEADLOCK_CHECK_INTERVAL), () ->
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
|||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
import org.l2jmobius.gameserver.instancemanager.QuestManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
@@ -310,6 +311,11 @@ public class Shutdown extends Thread
|
|||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
// the main instance should only run for shutdown hook, so we start a new instance
|
// the main instance should only run for shutdown hook, so we start a new instance
|
||||||
_counterInstance = new Shutdown(seconds, restart);
|
_counterInstance = new Shutdown(seconds, restart);
|
||||||
_counterInstance.start();
|
_counterInstance.start();
|
||||||
@@ -325,6 +331,12 @@ public class Shutdown extends Thread
|
|||||||
if (_counterInstance != null)
|
if (_counterInstance != null)
|
||||||
{
|
{
|
||||||
_counterInstance._abort();
|
_counterInstance._abort();
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_ENABLED)
|
||||||
|
{
|
||||||
|
PrecautionaryRestartManager.getInstance().restartAborted();
|
||||||
|
}
|
||||||
|
|
||||||
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
Broadcast.toAllOnlinePlayers("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the L2J Mobius project.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.l2jmobius.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.Shutdown;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.RaidBossInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Castle;
|
||||||
|
import org.l2jmobius.gameserver.model.siege.Fort;
|
||||||
|
import org.l2jmobius.gameserver.util.Broadcast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class PrecautionaryRestartManager
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PrecautionaryRestartManager.class.getName());
|
||||||
|
|
||||||
|
private static final String SYSTEM_CPU_LOAD_VAR = "SystemCpuLoad";
|
||||||
|
private static final String PROCESS_CPU_LOAD_VAR = "ProcessCpuLoad";
|
||||||
|
|
||||||
|
private static boolean _restarting = false;
|
||||||
|
|
||||||
|
protected PrecautionaryRestartManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_restarting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_CPU && (getCpuLoad(SYSTEM_CPU_LOAD_VAR) > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: CPU usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Server is using " + getCpuLoad(PROCESS_CPU_LOAD_VAR) + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.PRECAUTIONARY_RESTART_MEMORY && (getProcessRamLoad() > Config.PRECAUTIONARY_RESTART_PERCENTAGE))
|
||||||
|
{
|
||||||
|
if (serverBizzy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("PrecautionaryRestartManager: Memory usage over " + Config.PRECAUTIONARY_RESTART_PERCENTAGE + "%.");
|
||||||
|
Broadcast.toAllOnlinePlayers("Server will restart in 10 minutes.", false);
|
||||||
|
Shutdown.getInstance().startShutdown(null, 600, true);
|
||||||
|
}
|
||||||
|
}, Config.PRECAUTIONARY_RESTART_DELAY, Config.PRECAUTIONARY_RESTART_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getCpuLoad(String var)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
final ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
final AttributeList list = mbs.getAttributes(name, new String[]
|
||||||
|
{
|
||||||
|
var
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Attribute att = (Attribute) list.get(0);
|
||||||
|
final Double value = (Double) att.getValue();
|
||||||
|
if (value == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 1000) / 10d;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getProcessRamLoad()
|
||||||
|
{
|
||||||
|
final Runtime runTime = Runtime.getRuntime();
|
||||||
|
final long totalMemory = runTime.maxMemory();
|
||||||
|
final long usedMemory = totalMemory - ((totalMemory - runTime.totalMemory()) + runTime.freeMemory());
|
||||||
|
return (usedMemory * 100) / totalMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean serverBizzy()
|
||||||
|
{
|
||||||
|
for (Castle castle : CastleManager.getInstance().getCastles())
|
||||||
|
{
|
||||||
|
if ((castle != null) && castle.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fort fort : FortManager.getInstance().getForts())
|
||||||
|
{
|
||||||
|
if ((fort != null) && fort.getSiege().isInProgress())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerInstance player : World.getInstance().getPlayers())
|
||||||
|
{
|
||||||
|
if ((player == null) || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInOlympiadMode())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isOnEvent())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isInInstance())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target instanceof RaidBossInstance) || (target instanceof GrandBossInstance))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartEnabled()
|
||||||
|
{
|
||||||
|
_restarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartAborted()
|
||||||
|
{
|
||||||
|
_restarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrecautionaryRestartManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final PrecautionaryRestartManager INSTANCE = new PrecautionaryRestartManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user