diff options
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/util')
3 files changed, 146 insertions, 13 deletions
diff --git a/src/main/java/com/keuin/kbackupfabric/util/IO.java b/src/main/java/com/keuin/kbackupfabric/util/IO.java new file mode 100644 index 0000000..6d969ba --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/IO.java @@ -0,0 +1,54 @@ +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<ServerCommandSource> message(CommandContext<ServerCommandSource> context, String messageText) { + return message(context, messageText, false); + } + + public static CommandContext<ServerCommandSource> message(CommandContext<ServerCommandSource> 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/PostProgressRestoreThread.java b/src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java new file mode 100644 index 0000000..8427a2c --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java @@ -0,0 +1,71 @@ +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/ZipUtil.java b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java index d92ab12..29944c3 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java +++ b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java @@ -12,7 +12,7 @@ public class ZipUtil { * @param srcRootDir 压缩文件夹根目录的子路径 * @param file 当前递归压缩的文件或目录对象 * @param zos 压缩文件存储对象 - * @throws Exception + * @throws IOException IO Error */ private static void zip(String srcRootDir, File file, ZipOutputStream zos) throws IOException { if (file == null) { @@ -43,9 +43,9 @@ public class ZipUtil { else { // 压缩目录中的文件或子目录 File[] childFileList = file.listFiles(); - for (int n = 0; n < childFileList.length; n++) { - childFileList[n].getAbsolutePath().indexOf(file.getAbsolutePath()); - zip(srcRootDir, childFileList[n], zos); + for (File value : childFileList) { + value.getAbsolutePath().indexOf(file.getAbsolutePath()); + zip(srcRootDir, value, zos); } } } @@ -94,7 +94,7 @@ public class ZipUtil { //如果只是压缩一个文件,则需要截取该文件的父目录 String srcRootDir = srcPath; - if (srcFile.isFile() || true) { // Hack this stupid setting. We want to keep our least parent folder! + if (srcFile.isFile()) { // (Disabled) Hack this stupid setting. We want to keep our least parent folder! int index = srcPath.lastIndexOf(File.separator); if (index != -1) { srcRootDir = srcPath.substring(0, index); @@ -158,6 +158,7 @@ public class ZipUtil { entry = entries.nextElement(); // 构建压缩包中一个文件解压后保存的文件全路径 entryFilePath = unzipFilePath + File.separator + entry.getName(); + // 构建解压后保存的文件夹路径 index = entryFilePath.lastIndexOf(File.separator); if (index != -1) { @@ -180,15 +181,22 @@ public class ZipUtil { // 删除已存在的目标文件 entryFile.delete(); } - - // 写入文件 - bos = new BufferedOutputStream(new FileOutputStream(entryFile)); - bis = new BufferedInputStream(zip.getInputStream(entry)); - while ((count = bis.read(buffer, 0, bufferSize)) != -1) { - bos.write(buffer, 0, count); + if (entry.isDirectory()) { + // If the entry is a directory, we make its corresponding directory. + entryFile.mkdir(); + } else { + // Is a file, we write the data + // 写入文件 + bos = new BufferedOutputStream(new FileOutputStream(entryFile)); + bis = new BufferedInputStream(zip.getInputStream(entry)); + while ((count = bis.read(buffer, 0, bufferSize)) != -1) { + bos.write(buffer, 0, count); + } + bos.flush(); + bos.close(); } - bos.flush(); - bos.close(); + + } zip.close(); } |