From 720e8ec8eeb69d24afbb6b14068563cde2d470f0 Mon Sep 17 00:00:00 2001 From: Keuin Date: Thu, 23 Apr 2020 14:51:29 +0800 Subject: Version 1.1.0-dev: - Optimized backup lag (using async I/O). - Added twice confirmation /kb confirm and cancellation /kb cancel, to avoid mistake. - Added countdown before restoring. - Adjusted some text. - Code optimization. --- .../kbackupfabric/util/BackupFilesystemUtil.java | 53 ++++++++++++++++ src/main/java/com/keuin/kbackupfabric/util/IO.java | 54 ---------------- .../kbackupfabric/util/PermissionValidator.java | 9 +++ .../util/PostProgressRestoreThread.java | 71 ---------------------- .../com/keuin/kbackupfabric/util/PrintUtil.java | 57 +++++++++++++++++ .../keuin/kbackupfabric/util/ReflectionUtils.java | 4 +- .../com/keuin/kbackupfabric/util/WorldUtil.java | 15 ----- .../java/com/keuin/kbackupfabric/util/ZipUtil.java | 2 +- 8 files changed, 122 insertions(+), 143 deletions(-) create mode 100644 src/main/java/com/keuin/kbackupfabric/util/BackupFilesystemUtil.java delete mode 100644 src/main/java/com/keuin/kbackupfabric/util/IO.java create mode 100644 src/main/java/com/keuin/kbackupfabric/util/PermissionValidator.java delete mode 100644 src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java create mode 100644 src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java delete mode 100644 src/main/java/com/keuin/kbackupfabric/util/WorldUtil.java (limited to 'src/main/java/com/keuin/kbackupfabric/util') diff --git a/src/main/java/com/keuin/kbackupfabric/util/BackupFilesystemUtil.java b/src/main/java/com/keuin/kbackupfabric/util/BackupFilesystemUtil.java new file mode 100644 index 0000000..5b8ba5a --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/BackupFilesystemUtil.java @@ -0,0 +1,53 @@ +package com.keuin.kbackupfabric.util; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ThreadedAnvilChunkStorage; +import net.minecraft.world.World; + +import java.io.File; + +/** + * Functions deal with file name, directory name about Minecraft saves. + */ +public final class BackupFilesystemUtil { + + private static final String backupSaveDirectoryName = "backups"; + private static final String backupFileNamePrefix = "kbackup-"; + + public static String getBackupFileName(String backupName) { + return backupFileNamePrefix + backupName + ".zip"; + } + + public static String getBackupName(String backupFileName) { + try { + if (backupFileName.matches(backupFileNamePrefix + ".+\\.zip")) + return backupFileName.substring(backupFileNamePrefix.length(), backupFileName.length() - 4); + } catch (IndexOutOfBoundsException ignored) { + } + return backupFileName; + } + + public static boolean isBackupNameValid(String backupName, MinecraftServer server) { + File backupFile = new File(getBackupSaveDirectory(server), getBackupFileName(backupName)); + return backupFile.isFile(); + } + + public static File getBackupSaveDirectory(MinecraftServer server) { + return new File(server.getRunDirectory(), backupSaveDirectoryName); + } + + public static String getLevelPath(MinecraftServer server) { + return (new File(server.getRunDirectory(), server.getLevelName())).getAbsolutePath(); + } + + public static String getWorldDirectoryName(World world) throws NoSuchFieldException, IllegalAccessException { + File saveDir; + ThreadedAnvilChunkStorage threadedAnvilChunkStorage = (ThreadedAnvilChunkStorage) ReflectionUtils.getPrivateField(world.getChunkManager(), "threadedAnvilChunkStorage"); + saveDir = (File) ReflectionUtils.getPrivateField(threadedAnvilChunkStorage, "saveDir"); + return saveDir.getName(); + } + + public static String getBackupFileNamePrefix() { + return backupFileNamePrefix; + } +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/IO.java b/src/main/java/com/keuin/kbackupfabric/util/IO.java deleted file mode 100644 index 6d969ba..0000000 --- a/src/main/java/com/keuin/kbackupfabric/util/IO.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.keuin.kbackupfabric.util; - -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class IO { - - private static final Logger LOGGER = LogManager.getLogger(); - private static final boolean printDebugMessages = true; - private static final boolean printErrorMessages = true; - private static final boolean printInfoMessages = true; - private static final Object syncDebug = new Object(); - private static final Object syncError = new Object(); - private static final Object syncInfo = new Object(); - - public static CommandContext message(CommandContext context, String messageText) { - return message(context, messageText, false); - } - - public static CommandContext message(CommandContext context, String messageText, boolean broadcastToOps) { - context.getSource().sendFeedback(new LiteralText("[KBackup] " + messageText), broadcastToOps); - return context; - } - - public static void debug(String message) { - synchronized (syncDebug) { - if (printDebugMessages) { - System.out.println(String.format("[DEBUG] [KBackup] %s", message)); - LOGGER.debug(message); - } - } - } - - public static void error(String message) { - synchronized (syncError) { - if (printErrorMessages) { - System.out.println(String.format("[ERROR] [KBackup] %s", message)); - LOGGER.error(message); - } - } - } - - public static void info(String message) { - synchronized (syncInfo) { - if (printInfoMessages) { - System.out.println(String.format("[INFO] [KBackup] %s", message)); - LOGGER.info(message); - } - } - } -} diff --git a/src/main/java/com/keuin/kbackupfabric/util/PermissionValidator.java b/src/main/java/com/keuin/kbackupfabric/util/PermissionValidator.java new file mode 100644 index 0000000..9d37901 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/PermissionValidator.java @@ -0,0 +1,9 @@ +package com.keuin.kbackupfabric.util; + +import net.minecraft.server.command.ServerCommandSource; + +public class PermissionValidator { + public static boolean op(ServerCommandSource commandSource) { + return commandSource.hasPermissionLevel(4); + } +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java b/src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java deleted file mode 100644 index 8427a2c..0000000 --- a/src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.keuin.kbackupfabric.util; - -import java.io.File; -import java.io.IOException; - -import static com.keuin.kbackupfabric.util.IO.*; -import static org.apache.commons.io.FileUtils.forceDelete; - -/** - * This thread wait the server to be stopped (must invoke stop out of this thread), - * then delete current level, and restore our backup. - */ -public class PostProgressRestoreThread implements Runnable { - private final Thread serverThread; - private final String backupFilePath; - private final String levelDirectory; - - public PostProgressRestoreThread(Thread serverThread, String backupFilePath, String levelDirectory) { - this.serverThread = serverThread; - this.backupFilePath = backupFilePath; - this.levelDirectory = levelDirectory; - } - - @Override - public void run() { - try { - // Wait server thread die - debug("Waiting server thread stopping ..."); - while (serverThread.isAlive()) { - try { - serverThread.join(); - } catch (InterruptedException ignored) { - } - } - - debug("Waiting ..."); - try { - Thread.sleep(5000); - } catch (InterruptedException ignored) { - } - // Delete old level - debug("Server stopped. Deleting old level ..."); - File levelDirFile = new File(levelDirectory); - - int failedCounter = 0; - final int MAX_RETRY_TIMES = 20; - while (failedCounter < MAX_RETRY_TIMES) { - System.gc(); - if (!levelDirFile.delete() && levelDirFile.exists()) { - System.gc(); - forceDelete(levelDirFile); // Try to force delete. - } - if (levelDirFile.exists()) - ++failedCounter; - else - break; - } - if (levelDirFile.exists()) { - error(String.format("Cannot restore: failed to delete old level %s .", levelDirFile.getName())); - return; - } - - // Decompress archive - debug("Decompressing archived level"); - ZipUtil.unzip(backupFilePath, levelDirectory, false); - info("Restore complete! Please restart the server manually."); - } catch (SecurityException | IOException | ZipUtilException e) { - error("An exception occurred while restoring: " + e.getMessage()); - } - } -} diff --git a/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java b/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java new file mode 100644 index 0000000..e76155f --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java @@ -0,0 +1,57 @@ +package com.keuin.kbackupfabric.util; + +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public final class PrintUtil { + + private static final Logger LOGGER = LogManager.getLogger(); + private static final boolean printDebugMessages = true; + private static final boolean printErrorMessages = true; + private static final boolean printInfoMessages = true; + private static final Object syncDebug = new Object(); + private static final Object syncError = new Object(); + private static final Object syncInfo = new Object(); + private static final Object syncMessage = new Object(); + + public static CommandContext message(CommandContext context, String messageText) { + return message(context, messageText, false); + } + + public static CommandContext message(CommandContext context, String messageText, boolean broadcastToOps) { + synchronized (syncMessage) { + context.getSource().sendFeedback(new LiteralText("[KBackup] " + messageText), broadcastToOps); + } + return context; + } + + public static void debug(String message) { + synchronized (syncDebug) { + if (printDebugMessages) { + System.out.println(String.format("[DEBUG] [KBackup] %s", message)); + LOGGER.debug(message); + } + } + } + + public static void error(String message) { + synchronized (syncError) { + if (printErrorMessages) { + System.out.println(String.format("[ERROR] [KBackup] %s", message)); + LOGGER.error(message); + } + } + } + + public static void info(String message) { + synchronized (syncInfo) { + if (printInfoMessages) { + System.out.println(String.format("[INFO] [KBackup] %s", message)); + LOGGER.info(message); + } + } + } +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/ReflectionUtils.java b/src/main/java/com/keuin/kbackupfabric/util/ReflectionUtils.java index f7bc351..2acc562 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/ReflectionUtils.java +++ b/src/main/java/com/keuin/kbackupfabric/util/ReflectionUtils.java @@ -7,9 +7,9 @@ import java.lang.reflect.Method; /** * @Author 落叶飞翔的蜗牛 * @Date 2018/3/10 - * @Description + * @Description 常用反射函数 */ -public class ReflectionUtils { +public final class ReflectionUtils { /** * 获取私有成员变量的值 diff --git a/src/main/java/com/keuin/kbackupfabric/util/WorldUtil.java b/src/main/java/com/keuin/kbackupfabric/util/WorldUtil.java deleted file mode 100644 index badc068..0000000 --- a/src/main/java/com/keuin/kbackupfabric/util/WorldUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.keuin.kbackupfabric.util; - -import net.minecraft.server.world.ThreadedAnvilChunkStorage; -import net.minecraft.world.World; - -import java.io.File; - -public class WorldUtil { - public static String getWorldDirectoryName(World world) throws NoSuchFieldException, IllegalAccessException { - File saveDir; - ThreadedAnvilChunkStorage threadedAnvilChunkStorage = (ThreadedAnvilChunkStorage) ReflectionUtils.getPrivateField(world.getChunkManager(), "threadedAnvilChunkStorage"); - saveDir = (File) ReflectionUtils.getPrivateField(threadedAnvilChunkStorage, "saveDir"); - return saveDir.getName(); - } -} diff --git a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java index 0ab93ca..1ceeb60 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java +++ b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java @@ -4,7 +4,7 @@ import java.io.*; import java.util.Enumeration; import java.util.zip.*; -public class ZipUtil { +public final class ZipUtil { /** * 递归压缩文件夹 -- cgit v1.2.3