SteamWar/SpigotCore
Archiviert
13
0

First tested checkpoint implementation
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Dieser Commit ist enthalten in:
Lixfel 2024-01-16 12:36:49 +01:00
Ursprung 4bde0996ce
Commit c0b111eabc

Datei anzeigen

@ -21,6 +21,7 @@ package de.steamwar.core;
import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol; import com.comphenix.tinyprotocol.TinyProtocol;
import com.viaversion.viaversion.api.Via;
import de.steamwar.sql.internal.Statement; import de.steamwar.sql.internal.Statement;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -28,22 +29,46 @@ import org.eclipse.openj9.criu.CRIUSupport;
import org.eclipse.openj9.criu.JVMCRIUException; import org.eclipse.openj9.criu.JVMCRIUException;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import java.util.stream.Stream;
public class CheckpointUtils { public class CheckpointUtils {
private CheckpointUtils() {}
private static final Reflection.FieldAccessor<List> channelFutures = Reflection.getField(TinyProtocol.serverConnection, List.class, 0, ChannelFuture.class); private static final Reflection.FieldAccessor<List> 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 final Reflection.MethodInvoker bind = Reflection.getMethod(TinyProtocol.serverConnection, null, InetAddress.class, int.class);
public static void freeze() { public static void freeze() {
Bukkit.getOnlinePlayers().forEach(player -> player.kickPlayer(null)); Path path = FileSystems.getDefault().getPath(System.getProperty("checkpoint"));
try {
freezeInternal(path);
} catch (Exception e) {
Bukkit.shutdown();
throw new SecurityException(e);
} finally {
// Delete checkpoint
try (Stream<Path> stream = Files.walk(path)) {
stream.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
} catch (IOException e) {
//ignore
}
}
}
private static void freezeInternal(Path path) throws Exception {
Statement.closeAll(); Statement.closeAll();
// Close socket // Close socket
Via.getManager().getInjector().uninject();
Object serverConnection = TinyProtocol.getServerConnection(Core.getInstance()); Object serverConnection = TinyProtocol.getServerConnection(Core.getInstance());
List<?> channels = channelFutures.get(serverConnection); List<?> channels = channelFutures.get(serverConnection);
for(Object future : channels) { for(Object future : channels) {
@ -51,13 +76,13 @@ public class CheckpointUtils {
} }
channels.clear(); channels.clear();
// Do the snapshot // Do the checkpoint
Path path = FileSystems.getDefault().getPath("/tmp/checkpoints/" + Core.getVersion() + "/" + Bukkit.getWorlds().get(0).getName());
path.toFile().mkdirs(); path.toFile().mkdirs();
CRIUSupport criu = new CRIUSupport(path); CRIUSupport criu = new CRIUSupport(path);
criu.setAutoDedup(true); criu.setAutoDedup(true);
//criu.setShellJob(true); criu.setFileLocks(true);
//criu.setWorkDir(path); criu.setLogFile("criu.log"); criu.setShellJob(true);
criu.setLogFile("criu.log");
try { try {
criu.checkpointJVM(); criu.checkpointJVM();
} catch (JVMCRIUException e) { } catch (JVMCRIUException e) {
@ -69,9 +94,6 @@ public class CheckpointUtils {
int port; int port;
try (DataInputStream stream = new DataInputStream(Files.newInputStream(path.resolve("port").toFile().toPath()))) { try (DataInputStream stream = new DataInputStream(Files.newInputStream(path.resolve("port").toFile().toPath()))) {
port = stream.readInt(); port = stream.readInt();
} catch (IOException e) {
Bukkit.shutdown();
throw new SecurityException(e);
} }
// Reopen socket // Reopen socket
@ -81,5 +103,8 @@ public class CheckpointUtils {
((ChannelFuture) future).channel().config().setAutoRead(true); ((ChannelFuture) future).channel().config().setAutoRead(true);
} }
} }
Via.getManager().getInjector().inject();
Core.getInstance().getLogger().log(Level.INFO, "Checkpoint restored");
} }
} }