Change the system to support group restarts (#651)

This commit is contained in:
Sam 2018-09-03 20:38:31 +01:00 committed by Alexander Meech
parent 3b89458bbd
commit 48e8a7e451
17 changed files with 197 additions and 280 deletions

View File

@ -10,20 +10,19 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import mineplex.core.MiniPlugin;
import mineplex.core.account.permissions.Permission;
import mineplex.core.account.permissions.PermissionGroup;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilServer;
import mineplex.core.portal.GenericServer;
import mineplex.core.portal.Intent;
@ -31,7 +30,6 @@ import mineplex.core.portal.Portal;
import mineplex.core.updater.command.BuildVersionCommand;
import mineplex.core.updater.command.RestartServerCommand;
import mineplex.core.updater.event.RestartServerEvent;
import mineplex.core.updater.event.RestartTriggerEvent;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.serverdata.Region;
import mineplex.serverdata.commands.RestartCommand;
@ -39,6 +37,7 @@ import mineplex.serverdata.commands.ServerCommandManager;
public class FileUpdater extends MiniPlugin
{
public enum Perm implements Permission
{
RESTART_COMMAND,
@ -47,43 +46,65 @@ public class FileUpdater extends MiniPlugin
private static final FilenameFilter JAR_FILTER = (file, name) -> name.endsWith(".jar");
private Portal _portal;
private Map<String, String> _jarMd5Map = new ConcurrentHashMap<>();
private String _serverName;
private Region _region;
private final Portal _portal;
private final Map<String, String> _jarMd5Map = new ConcurrentHashMap<>();
private final String _serverName;
private final Region _region;
private final GenericServer _transferHub;
private AtomicBoolean _needUpdate = new AtomicBoolean();
private boolean _enabled = true;
private boolean _restartTriggered = false;
private AtomicBoolean _restartTriggered = new AtomicBoolean();
private boolean _restartHappening, _enabled;
private Properties _buildProperties;
public FileUpdater(JavaPlugin plugin, Portal portal, String serverName, Region region, GenericServer transferHub)
{
super("File Updater", plugin);
_portal = portal;
_serverName = serverName;
_region = region;
public FileUpdater(GenericServer transferHub)
{
super("Restart");
_portal = Portal.getInstance();
_serverName = UtilServer.getServerName();
_region = UtilServer.getRegion();
_transferHub = transferHub;
getJarHashes();
if (new File("IgnoreUpdates.dat").exists())
{
_enabled = false;
}
_enabled = !new File("IgnoreUpdates.dat").exists();
// Register the server command type for future use
ServerCommandManager.getInstance().registerCommandType("RestartCommand", RestartCommand.class, new RestartHandler(plugin, _serverName, _region));
ServerCommandManager.getInstance().registerCommandType(RestartCommand.class, command ->
{
if (_region != command.getRegion())
{
return;
}
if (command.isGroupRestart() ? _serverName.startsWith(command.getServerName()) : _serverName.equals(command.getServerName()))
{
RestartReason reason;
int delay;
if (command.isGroupRestart())
{
reason = RestartReason.GROUP_COMMAND;
// If we are restarting the entire group then delay the shutdown to sometime within the next 5 minutes.
// Prevents players getting fully kicked from the network.
delay = UtilMath.r(300);
}
else
{
reason = RestartReason.SINGLE_COMMAND;
delay = 0;
}
attemptToRestart(reason, delay);
}
});
loadBuildProperties();
generatePermissions();
}
private void generatePermissions()
{
PermissionGroup.QA.setPermission(Perm.BVERSION_COMMAND, true, true);
@ -100,71 +121,63 @@ public class FileUpdater extends MiniPlugin
addCommand(new BuildVersionCommand(this));
}
// This scares me, I don't know if it is used but I'm not removing it.
@EventHandler
public void onServerCommand(ServerCommandEvent event)
{
if (event.getCommand().startsWith("updatekickall "))
{
String[] args = event.getCommand().split(" ");
String message = StringUtils.join(args, " ", 1, args.length);
attemptToRestart(RestartReason.GROUP_COMMAND, 0);
}
}
for (Player player : Bukkit.getOnlinePlayers())
{
player.sendMessage(F.main("Updater", message));
_portal.sendPlayerToGenericServer(player, _transferHub, Intent.KICK);
}
}
}
@EventHandler
public void tryToRestart(UpdateEvent event)
private void attemptToRestart(RestartReason reason, int delayInSeconds)
{
if (event.getType() != UpdateType.SLOWER)
// If we already have a scheduled restart, don't try again.
if (_restartTriggered.get())
{
return;
}
if (!_enabled || _restartTriggered || !_needUpdate.get())
log("Restart scheduled by " + reason + ", delaying " + delayInSeconds + " seconds.");
_restartTriggered.set(true);
runSyncTimer(new BukkitRunnable()
{
return;
}
if (UtilServer.CallEvent(new RestartTriggerEvent(RestartTriggerEvent.RestartReason.UPDATE)).isCancelled())
{
return;
}
_restartTriggered = true;
RestartServerEvent restartEvent = new RestartServerEvent(RestartServerEvent.RestartReason.UPDATE);
getPluginManager().callEvent(restartEvent);
if (!restartEvent.isCancelled())
{
for (Player player : Bukkit.getOnlinePlayers())
@Override
public void run()
{
player.sendMessage(F.main("Updater", C.cGold + _serverName + C.cGray + " is restarting for an update."));
// Keep calling this event until it doesn't get cancelled.
// For example, for unimportant updates game servers don't need to restart until their current game is over.
RestartServerEvent restartEvent = new RestartServerEvent(reason);
UtilServer.CallEvent(restartEvent);
if (restartEvent.isCancelled())
{
return;
}
_restartHappening = true;
// Cancel the task
cancel();
// Tell the players
Bukkit.broadcastMessage(F.main(getName(), F.color(_serverName, C.cGold) + " " + reason.getDescription()));
// Move all players out and shutdown the server
runSyncLater(() -> _portal.sendAllPlayersToGenericServer(_transferHub, Intent.KICK), 60L);
runSyncLater(() -> Bukkit.getServer().shutdown(), 100L);
}
getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(getPlugin(), () ->
{
_portal.sendAllPlayersToGenericServer(_transferHub, Intent.KICK);
}, 60L);
getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(getPlugin(), () ->
{
getPlugin().getServer().shutdown();
}, 100L);
}
}, delayInSeconds * 20, 16 * 20);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void reflectMotd(ServerListPingEvent event)
{
if (_needUpdate.get())
if (_restartHappening)
{
event.setMotd("Restarting soon");
event.setMotd("Restarting");
}
}
@ -190,9 +203,9 @@ public class FileUpdater extends MiniPlugin
String newHash = DigestUtils.md5Hex(stream);
if (!hash.equals(newHash))
{
System.out.println(file.getName() + " old hash : " + hash);
System.out.println(file.getName() + " new hash : " + newHash);
_needUpdate.set(true);
log(file.getName() + " old hash : " + hash);
log(file.getName() + " new hash : " + newHash);
attemptToRestart(RestartReason.JAR_UPDATE, 0);
}
}
catch (IOException ex)
@ -203,16 +216,11 @@ public class FileUpdater extends MiniPlugin
}
}
}
@EventHandler
public void checkForUpdates(UpdateEvent event)
{
if (event.getType() != UpdateType.MIN_01)
{
return;
}
if (!_enabled || _needUpdate.get())
if (event.getType() != UpdateType.MIN_01 || !_enabled || _restartTriggered.get())
{
return;
}
@ -241,7 +249,7 @@ public class FileUpdater extends MiniPlugin
}
}
}
private void getJarHashes()
{
File base = new File(".");

View File

@ -1,87 +0,0 @@
package mineplex.core.updater;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilServer;
import mineplex.core.portal.GenericServer;
import mineplex.core.portal.Intent;
import mineplex.core.portal.Portal;
import mineplex.core.updater.event.RestartServerEvent;
import mineplex.core.updater.event.RestartTriggerEvent;
import mineplex.serverdata.Region;
import mineplex.serverdata.commands.CommandCallback;
import mineplex.serverdata.commands.RestartCommand;
import mineplex.serverdata.commands.ServerCommand;
public class RestartHandler implements CommandCallback<RestartCommand>, Listener
{
private JavaPlugin _plugin;
private String _serverName;
private Region _region;
private boolean _restarting;
public RestartHandler(JavaPlugin plugin, String serverName, Region region)
{
_plugin = plugin;
_serverName = serverName;
_region = region;
_plugin.getServer().getPluginManager().registerEvents(this, _plugin);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void reflectMotd(ServerListPingEvent event)
{
if (_restarting)
{
event.setMotd("Restarting soon");
}
}
@Override
public void run(RestartCommand command)
{
String serverName = command.getServerName();
Region region = command.getRegion();
if (!serverName.equalsIgnoreCase(_serverName) || _region != region)
{
return;
}
if (UtilServer.CallEvent(new RestartTriggerEvent(RestartTriggerEvent.RestartReason.COMMAND)).isCancelled())
{
return;
}
if (UtilServer.CallEvent(new RestartServerEvent(RestartServerEvent.RestartReason.COMMAND)).isCancelled())
{
return;
}
_restarting = true;
for (Player player : Bukkit.getOnlinePlayers())
{
player.sendMessage(F.main("Restart", "Server is restarting, you're being sent to a lobby."));
}
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(UtilServer.getPlugin(), () ->
{
Portal.getInstance().sendAllPlayersToGenericServer(GenericServer.HUB, Intent.KICK);
}, 60L);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(UtilServer.getPlugin(), () ->
{
Bukkit.getServer().shutdown();
}, 100L);
}
}

View File

@ -0,0 +1,21 @@
package mineplex.core.updater;
public enum RestartReason
{
SINGLE_COMMAND("is restarting."),
GROUP_COMMAND("is restarting."),
JAR_UPDATE("is restarting for an update.");
private final String _description;
RestartReason(String description)
{
_description = description;
}
public String getDescription()
{
return _description;
}
}

View File

@ -4,7 +4,6 @@ import org.bukkit.entity.Player;
import mineplex.core.command.CommandBase;
import mineplex.core.common.util.C;
import mineplex.core.common.util.Callback;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.portal.Portal;
@ -13,6 +12,7 @@ import mineplex.serverdata.commands.RestartCommand;
public class RestartServerCommand extends CommandBase<FileUpdater>
{
public RestartServerCommand(FileUpdater plugin)
{
super(plugin, FileUpdater.Perm.RESTART_COMMAND, "restart");
@ -21,26 +21,35 @@ public class RestartServerCommand extends CommandBase<FileUpdater>
@Override
public void Execute(final Player caller, final String[] args)
{
if (args == null || args.length < 1)
if (args.length == 0)
{
UtilPlayer.message(caller, F.main("Restart", "You must specify a server to restart."));
UtilPlayer.message(caller, F.main(Plugin.getName(), "/" + _aliasUsed + " <server> - Restarts a single server."));
UtilPlayer.message(caller, F.main(Plugin.getName(), "/" + _aliasUsed + " <prefix> group - Restarts a group of servers that match the prefix."));
return;
}
Portal.getInstance().doesServerExist(args[0], new Callback<Boolean>()
String serverName = args[0];
boolean groupRestart = args.length > 1 && args[1].equalsIgnoreCase("group");
if (groupRestart)
{
public void run(Boolean serverExists)
new RestartCommand(serverName, Plugin.getRegion(), true).publish();
UtilPlayer.message(caller, F.main(Plugin.getName(), "Sent restart command to all " + F.color(serverName, C.cGold) + " servers."));
}
else
{
Portal.getInstance().doesServerExist(serverName, serverExists ->
{
if (serverExists)
{
new RestartCommand(args[0], Plugin.getRegion()).publish();
UtilPlayer.message(caller, F.main("Restart", "Sent restart command to " + C.cGold + args[0] + C.cGray + "."));
new RestartCommand(serverName, Plugin.getRegion(), false).publish();
UtilPlayer.message(caller, F.main(Plugin.getName(), "Sent restart command to " + F.color(serverName, C.cGold) + "."));
}
else
{
UtilPlayer.message(caller, F.main("Restart", C.cGold + args[0] + C.cGray + " doesn't exist."));
UtilPlayer.message(caller, F.main(Plugin.getName(), F.color(serverName, C.cGold) + " doesn't exist."));
}
}
});
});
}
}
}

View File

@ -4,27 +4,26 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import mineplex.core.updater.RestartReason;
public class RestartServerEvent extends Event implements Cancellable
{
private static final HandlerList handlers = new HandlerList();
private boolean _cancelled = false;
private final RestartReason _reason;
public RestartServerEvent(RestartReason reason)
private static final HandlerList HANDLER_LIST = new HandlerList();
public static HandlerList getHandlerList()
{
return HANDLER_LIST;
}
private final RestartReason _reason;
private boolean _cancelled;
public RestartServerEvent(RestartReason reason)
{
_reason = reason;
}
public HandlerList getHandlers()
{
return handlers;
}
public static HandlerList getHandlerList()
{
return handlers;
}
public RestartReason getReason()
{
return _reason;
@ -41,10 +40,10 @@ public class RestartServerEvent extends Event implements Cancellable
{
_cancelled = cancel;
}
public enum RestartReason
{
COMMAND,
UPDATE
}
@Override
public HandlerList getHandlers()
{
return HANDLER_LIST;
}
}

View File

@ -1,50 +0,0 @@
package mineplex.core.updater.event;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class RestartTriggerEvent extends Event implements Cancellable
{
private static final HandlerList handlers = new HandlerList();
private boolean _cancelled = false;
private final RestartReason _reason;
public RestartTriggerEvent(RestartReason reason)
{
_reason = reason;
}
public HandlerList getHandlers()
{
return handlers;
}
public static HandlerList getHandlerList()
{
return handlers;
}
public RestartReason getReason()
{
return _reason;
}
@Override
public boolean isCancelled()
{
return _cancelled;
}
@Override
public void setCancelled(boolean cancel)
{
_cancelled = cancel;
}
public enum RestartReason
{
COMMAND,
UPDATE
}
}

View File

@ -9,7 +9,7 @@ import net.minecraft.server.v1_8_R3.MinecraftServer;
public class UpdateEvent extends Event
{
private static final HandlerList handlers = new HandlerList();
private UpdateType _type;
private final UpdateType _type;
public UpdateEvent(UpdateType example)
{

View File

@ -138,7 +138,7 @@ public class Clans extends JavaPlugin
Teleport teleport = new Teleport(this, _clientManager);
Portal portal = new Portal();
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.CLANS_HUB);
new FileUpdater(GenericServer.CLANS_HUB);
ClansFreezeManager clansFreeze = new ClansFreezeManager(this, _clientManager);

View File

@ -159,7 +159,7 @@ public class ClansHub extends JavaPlugin
new MessageManager(this, incognito, clientManager, preferenceManager, ignoreManager, punish, friendManager, require(Chat.class));
new MemoryFix(this);
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.CLANS_HUB);
new FileUpdater(GenericServer.CLANS_HUB);
new CustomTagFix(this, packetHandler);
new PacketsInteractionFix(this, packetHandler);
new ResourcePackManager(this, portal);

View File

@ -159,7 +159,7 @@ public class Hub extends JavaPlugin implements IRelation
new MessageManager(this, incognito, clientManager, preferenceManager, ignoreManager, punish, friendManager, require(Chat.class));
new MemoryFix(this);
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.HUB);
new FileUpdater(GenericServer.HUB);
new CustomTagFix(this, packetHandler);
new PacketsInteractionFix(this, packetHandler);
new ResourcePackManager(this, portal);

View File

@ -4,21 +4,35 @@ import mineplex.serverdata.Region;
public class RestartCommand extends ServerCommand
{
private String _server;
public String getServerName() { return _server; }
private Region _region;
public Region getRegion() { return _region; }
public RestartCommand(String server, Region region)
private final String _server;
private final Region _region;
private final boolean _groupRestart;
public RestartCommand(String server, Region region, boolean groupRestart)
{
_server = server;
_region = region;
_groupRestart = groupRestart;
}
@Override
public void run()
public void run()
{
// Utilitizes a callback functionality to seperate dependencies
}
public String getServerName()
{
return _server;
}
public Region getRegion()
{
return _region;
}
public boolean isGroupRestart()
{
return _groupRestart;
}
}

View File

@ -322,7 +322,7 @@ public class ServerMonitor
{
if (laggyServers.contains(minecraftServer.getName()))
{
new RestartCommand(minecraftServer.getName(), _region).publish();
new RestartCommand(minecraftServer.getName(), _region, false).publish();
log("[RESTART LAGGY] : " + minecraftServer.getName() + ":" + minecraftServer.getPublicAddress());
}
else

View File

@ -69,8 +69,8 @@ public class StaffServer extends JavaPlugin
InventoryManager inventoryManager = new InventoryManager(this, clientManager);
BonusRepository bonusRepository = new BonusRepository(this, null, donationManager);
new AchievementManager(statsManager, clientManager, donationManager, null, eloManager);
new MemoryFix(this);
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.HUB);
new MemoryFix(this);
new FileUpdater(GenericServer.HUB);
require(PacketHandler.class);
require(DisguiseManager.class);

View File

@ -149,7 +149,7 @@ public class Arcade extends JavaPlugin
Creature creature = new Creature(this);
Teleport teleport = new Teleport(this, clientManager);
Portal portal = new Portal();
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.HUB);
new FileUpdater(GenericServer.HUB);
DisguiseManager disguiseManager = require(DisguiseManager.class);

View File

@ -29,8 +29,9 @@ import mineplex.core.gadget.gadgets.mount.types.MountDragon;
import mineplex.core.gadget.types.Gadget;
import mineplex.core.gadget.types.GadgetType;
import mineplex.core.gadget.types.WinEffectGadget;
import mineplex.core.updater.RestartReason;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.RestartTriggerEvent;
import mineplex.core.updater.event.RestartServerEvent;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.minecraft.game.core.condition.Condition.ConditionType;
@ -459,12 +460,14 @@ public class GameManager implements Listener
}
@EventHandler
public void restartServerCheck(RestartTriggerEvent event)
public void restartServerCheck(RestartServerEvent event)
{
if (Manager.GetGame() != null && !Manager.GetGame().inLobby() && event.getReason() == RestartTriggerEvent.RestartReason.UPDATE)
if (Manager.GetGame() == null || Manager.GetGame().inLobby() || event.getReason() == RestartReason.SINGLE_COMMAND)
{
event.setCancelled(true);
return;
}
event.setCancelled(true);
}
@EventHandler

View File

@ -102,7 +102,7 @@ public class Hub extends JavaPlugin
Creature creature = new Creature(this);
ServerStatusManager serverStatusManager = new ServerStatusManager(this, _clientManager, new LagMeter(this, _clientManager));
Portal portal = new Portal();
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.HUB);
new FileUpdater(GenericServer.HUB);
DisguiseManager disguiseManager = require(DisguiseManager.class);

View File

@ -170,7 +170,7 @@ public class GemHunters extends JavaPlugin
Portal portal = new Portal();
// File Updater
new FileUpdater(this, portal, serverStatusManager.getCurrentServerName(), serverStatusManager.getRegion(), GenericServer.HUB);
new FileUpdater(GenericServer.HUB);
// Punish
Punish punish = new Punish(this, clientManager);