From daa17c3e8b8487227b64226a96f05acde70cbedd Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 24 Nov 2024 22:12:43 +0100 Subject: [PATCH] Wrap CheckpointUtils for OpenJDK support, remove Border debug messages --- .../steamwar/fightsystem/listener/Border.java | 2 - .../src/de/steamwar/core/CheckpointUtils.java | 181 ++++++++++-------- 2 files changed, 100 insertions(+), 83 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Border.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Border.java index 6ab6605e..602a8e11 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Border.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Border.java @@ -64,7 +64,6 @@ public class Border { ghostBarriers.put(player.getUniqueId(), new HashSet<>()); lastLocation.put(player.getUniqueId(), player.getLocation()); - FightSystem.getPlugin().getLogger().log(Level.INFO, () -> player.getName() + " was added to border " + name); } public boolean contains(Player player) { @@ -72,7 +71,6 @@ public class Border { } public void removePlayer(Player player) { - FightSystem.getPlugin().getLogger().log(Level.INFO, () -> player.getName() + " was removed from border " + name); lastLocation.remove(player.getUniqueId()); Set blocks = ghostBarriers.remove(player.getUniqueId()); if(blocks == null || !player.isOnline()) diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtils.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtils.java index d65d7311..f274acfc 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtils.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtils.java @@ -45,103 +45,122 @@ public class CheckpointUtils { private CheckpointUtils() {} public static void signalHandler() { - Signal.handle(new Signal("USR1"), signal -> Bukkit.getScheduler().runTask(Core.getInstance(), CheckpointUtils::freeze)); + try { + J9Wrapper.signalHandler(); + } catch (NoClassDefFoundError e) { + //ignore + } } public static void freeze() { - String checkpointFile = System.getProperty("checkpoint"); - if(!CRIUSupport.isCheckpointAllowed() || checkpointFile == null) { - Bukkit.shutdown(); - return; - } - - Bukkit.getOnlinePlayers().forEach(player -> player.kickPlayer(null)); - - List networkManagers = TinyProtocol.networkManagers.get(TinyProtocol.getServerConnection(Core.getInstance())); - if(!Bukkit.getOnlinePlayers().isEmpty() || !networkManagers.isEmpty()) { - Core.getInstance().getLogger().log(Level.INFO, "Waiting for players to disconnect for checkpointing"); - Bukkit.getScheduler().runTaskLater(Core.getInstance(), CheckpointUtils::freeze, 1); - return; - } - - Path path = FileSystems.getDefault().getPath(checkpointFile); - try { - freezeInternal(path); - } catch (Exception e) { - String message = e.getMessage() != null ? e.getMessage() : ""; - if(message.contains("Connected TCP socket")) { - Core.getInstance().getLogger().log(Level.INFO, "Connected TCP socket, waiting for checkpointing"); + J9Wrapper.freeze(); + } catch (NoClassDefFoundError e) { + //ignore + } + } + + private static class J9Wrapper { + private static void signalHandler() { + Signal.handle(new Signal("USR1"), signal -> Bukkit.getScheduler().runTask(Core.getInstance(), CheckpointUtils::freeze)); + } + + private static void freeze() { + String checkpointFile = System.getProperty("checkpoint"); + if(!CRIUSupport.isCheckpointAllowed() || checkpointFile == null) { + Bukkit.shutdown(); + return; + } + + Bukkit.getOnlinePlayers().forEach(player -> player.kickPlayer(null)); + + List networkManagers = TinyProtocol.networkManagers.get(TinyProtocol.getServerConnection(Core.getInstance())); + if(!Bukkit.getOnlinePlayers().isEmpty() || !networkManagers.isEmpty()) { + Core.getInstance().getLogger().log(Level.INFO, "Waiting for players to disconnect for checkpointing"); Bukkit.getScheduler().runTaskLater(Core.getInstance(), CheckpointUtils::freeze, 1); return; } - Bukkit.shutdown(); + Path path = FileSystems.getDefault().getPath(checkpointFile); - if(!message.contains("Can't dump ghost file") && !message.contains("Can't create link remap")) // File/Jar has been updated - throw new SecurityException(e); - } finally { - // Delete checkpoint - try (Stream stream = Files.walk(path)) { - stream.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); - } catch (IOException e) { - //ignore + try { + freezeInternal(path); + } catch (Exception e) { + String message = e.getMessage() != null ? e.getMessage() : ""; + if(message.contains("Connected TCP socket")) { + Core.getInstance().getLogger().log(Level.INFO, "Connected TCP socket, waiting for checkpointing"); + Bukkit.getScheduler().runTaskLater(Core.getInstance(), CheckpointUtils::freeze, 1); + return; + } + + Bukkit.shutdown(); + + if(!message.contains("Can't dump ghost file") && !message.contains("Can't create link remap")) // File/Jar has been updated + throw new SecurityException(e); + } finally { + // Delete checkpoint + try (Stream stream = Files.walk(path)) { + stream.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } catch (IOException e) { + //ignore + } } } - } - private static final Reflection.FieldAccessor channelFutures = Reflection.getField(TinyProtocol.serverConnection, List.class, 0, ChannelFuture.class); - private static final Reflection.MethodInvoker bind = Reflection.getMethod(TinyProtocol.serverConnection, null, InetAddress.class, int.class); - private static void freezeInternal(Path path) throws Exception { - Bukkit.getPluginManager().callEvent(new CRIUSleepEvent()); - Bukkit.getWorlds().forEach(FlatteningWrapper.impl::syncSave); - Statement.closeAll(); - // Close socket - Via.getManager().getInjector().uninject(); - Object serverConnection = TinyProtocol.getServerConnection(Core.getInstance()); - List channels = channelFutures.get(serverConnection); - for(Object future : channels) { - ((ChannelFuture) future).channel().close().syncUninterruptibly(); - } - channels.clear(); + private static final Reflection.FieldAccessor channelFutures = Reflection.getField(TinyProtocol.serverConnection, List.class, 0, ChannelFuture.class); + private static final Reflection.MethodInvoker bind = Reflection.getMethod(TinyProtocol.serverConnection, null, InetAddress.class, int.class); + private static void freezeInternal(Path path) throws Exception { + Bukkit.getPluginManager().callEvent(new CRIUSleepEvent()); + Bukkit.getWorlds().forEach(FlatteningWrapper.impl::syncSave); + Statement.closeAll(); - System.runFinalization(); - System.gc(); - - // Do the checkpoint - path.toFile().mkdirs(); - CRIUSupport criu = new CRIUSupport(path); - criu.setAutoDedup(true); - criu.setFileLocks(true); - criu.setShellJob(true); - criu.setLogFile("criu.log"); - try { - criu.checkpointJVM(); - } catch (JVMCRIUException e) { - Path logfile = path.resolve("criu.log"); - if(logfile.toFile().exists()) - throw new IllegalStateException("Could not create checkpoint, criu log:\n" + new String(Files.readAllBytes(logfile)), e); - - throw e; - } - - // Get new port - int port; - try (DataInputStream stream = new DataInputStream(Files.newInputStream(path.resolve("port").toFile().toPath()))) { - port = stream.readInt(); - } - - // Reopen socket - bind.invoke(serverConnection, InetAddress.getLoopbackAddress(), port); - if(Core.getVersion() > 12) { + // Close socket + Via.getManager().getInjector().uninject(); + Object serverConnection = TinyProtocol.getServerConnection(Core.getInstance()); + List channels = channelFutures.get(serverConnection); for(Object future : channels) { - ((ChannelFuture) future).channel().config().setAutoRead(true); + ((ChannelFuture) future).channel().close().syncUninterruptibly(); } - } - Via.getManager().getInjector().inject(); + channels.clear(); - Bukkit.getPluginManager().callEvent(new CRIUWakeupEvent()); - Core.getInstance().getLogger().log(Level.INFO, "Checkpoint restored"); + System.runFinalization(); + System.gc(); + + // Do the checkpoint + path.toFile().mkdirs(); + CRIUSupport criu = new CRIUSupport(path); + criu.setAutoDedup(true); + criu.setFileLocks(true); + criu.setShellJob(true); + criu.setLogFile("criu.log"); + try { + criu.checkpointJVM(); + } catch (JVMCRIUException e) { + Path logfile = path.resolve("criu.log"); + if(logfile.toFile().exists()) + throw new IllegalStateException("Could not create checkpoint, criu log:\n" + new String(Files.readAllBytes(logfile)), e); + + throw e; + } + + // Get new port + int port; + try (DataInputStream stream = new DataInputStream(Files.newInputStream(path.resolve("port").toFile().toPath()))) { + port = stream.readInt(); + } + + // Reopen socket + bind.invoke(serverConnection, InetAddress.getLoopbackAddress(), port); + if(Core.getVersion() > 12) { + for(Object future : channels) { + ((ChannelFuture) future).channel().config().setAutoRead(true); + } + } + Via.getManager().getInjector().inject(); + + Bukkit.getPluginManager().callEvent(new CRIUWakeupEvent()); + Core.getInstance().getLogger().log(Level.INFO, "Checkpoint restored"); + } } }