summaryrefslogtreecommitdiff
path: root/src/main/java/com/keuin/kbackupfabric/util
diff options
context:
space:
mode:
authorKeuin <[email protected]>2020-04-23 10:45:28 +0800
committerkeuin <[email protected]>2020-04-23 10:45:28 +0800
commitb2d161cee43b9b1af04416486d6df82621b03ae3 (patch)
treee102ea567d7e7f0f7a90acd16b34ac147ed9338e /src/main/java/com/keuin/kbackupfabric/util
parentb582ad31ed8d44aa60b2eab22b2d927519297eeb (diff)
Version 1.0.0-dev1.0.0-dev
TODO: Optimize ZipUtil
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/util')
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/IO.java54
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/PostProgressRestoreThread.java71
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java34
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();
}