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. --- .../keuin/kbackupfabric/worker/BackupWorker.java | 92 ++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/main/java/com/keuin/kbackupfabric/worker/BackupWorker.java (limited to 'src/main/java/com/keuin/kbackupfabric/worker/BackupWorker.java') diff --git a/src/main/java/com/keuin/kbackupfabric/worker/BackupWorker.java b/src/main/java/com/keuin/kbackupfabric/worker/BackupWorker.java new file mode 100644 index 0000000..30fd8b5 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/worker/BackupWorker.java @@ -0,0 +1,92 @@ +package com.keuin.kbackupfabric.worker; + +import com.keuin.kbackupfabric.util.ZipUtil; +import com.keuin.kbackupfabric.util.ZipUtilException; +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.world.World; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.*; +import static com.keuin.kbackupfabric.util.PrintUtil.debug; +import static com.keuin.kbackupfabric.util.PrintUtil.message; + +/** + * The backup worker + * To invoke this worker, simply call invoke() method. + */ +public final class BackupWorker implements Runnable { + private final CommandContext context; + private final String backupName; + private final Map oldWorldsSavingDisabled; + + + private BackupWorker(CommandContext context, String backupName, Map oldWorldsSavingDisabled) { + this.context = context; + this.backupName = backupName; + this.oldWorldsSavingDisabled = oldWorldsSavingDisabled; + } + + public static void invoke(CommandContext context, String backupName) { + //// Save world, save old autosave configs + + message(context, String.format("Making backup %s, please wait ...", backupName), true); + Map oldWorldsSavingDisabled = new HashMap<>(); // old switch stat + + // Get server + MinecraftServer server = context.getSource().getMinecraftServer(); + + // Save old autosave switch stat temporally + server.getWorlds().forEach(world -> { + oldWorldsSavingDisabled.put(world, world.savingDisabled); + world.savingDisabled = true; + }); + + // Force to save all player data and worlds + debug("Saving players ..."); + server.getPlayerManager().saveAllPlayerData(); + debug("Saving worlds ..."); + server.save(true, true, true); + + // Start threaded worker + BackupWorker worker = new BackupWorker(context, backupName, oldWorldsSavingDisabled); + Thread workerThread = new Thread(worker, "BackupWorker"); + workerThread.start(); + } + + @Override + public void run() { + String destPathFolderName = ""; + MinecraftServer server = context.getSource().getMinecraftServer(); + try { + //// Do our main backup logic + + // Create backup saving directory + File destPathFile = getBackupSaveDirectory(server); + destPathFolderName = destPathFile.getName(); + if (!destPathFile.isDirectory() && !destPathFile.mkdir()) { + message(context, String.format("Failed to create backup saving directory: %s. Failed to backup.", destPathFolderName)); + return; + } + + // Make zip + String levelPath = getLevelPath(server); + debug(String.format("zip(srcPath=%s, destPath=%s)", levelPath, destPathFile.toString())); + ZipUtil.zip(levelPath, destPathFile.toString(), getBackupFileName(backupName)); + + // Restore old autosave switch stat + server.getWorlds().forEach(world -> world.savingDisabled = oldWorldsSavingDisabled.getOrDefault(world, true)); + + message(context, "Done.", true); + } catch (SecurityException e) { + message(context, String.format("Failed to create backup saving directory: %s. Failed to backup.", destPathFolderName)); + } catch (IOException | ZipUtilException e) { + message(context, "Failed to make zip: " + e.getMessage()); + } + } +} -- cgit v1.2.3