Merged BackuContext, MakeBackupRunnable, MakeBackupRunnableFactory into ExecutableBackup

2.x
Szum123321 2023-05-10 08:55:54 +02:00
parent 27d6d68e97
commit 6782c4fe5f
16 changed files with 289 additions and 388 deletions

View File

@ -23,7 +23,6 @@ import net.szum123321.textile_backup.core.digest.BalticHash;
import net.szum123321.textile_backup.core.digest.Hash;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.MakeBackupRunnable;
import net.szum123321.textile_backup.core.restore.AwaitThread;
import org.apache.commons.io.FileUtils;
@ -70,8 +69,8 @@ public class Globals {
if(!executorService.awaitTermination(timeout, TimeUnit.MICROSECONDS)) {
log.error("Timeout occurred while waiting for currently running backups to finish!");
executorService.shutdownNow().stream()
.filter(r -> r instanceof MakeBackupRunnable)
.map(r -> (MakeBackupRunnable)r)
// .filter(r -> r instanceof ExecutableBackup)
// .map(r -> (ExecutableBackup)r)
.forEach(r -> log.error("Dropping: {}", r.toString()));
if(!executorService.awaitTermination(1000, TimeUnit.MICROSECONDS))
log.error("Couldn't shut down the executor!");

View File

@ -39,9 +39,8 @@ import net.szum123321.textile_backup.commands.restore.RestoreBackupCommand;
import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.BackupScheduler;
import net.szum123321.textile_backup.core.create.MakeBackupRunnableFactory;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import net.szum123321.textile_backup.test.BalticHashTest;
public class TextileBackup implements ModInitializer {
@ -82,14 +81,14 @@ public class TextileBackup implements ModInitializer {
if (config.get().shutdownBackup && Globals.INSTANCE.globalShutdownBackupFlag.get()) {
try {
MakeBackupRunnableFactory.create(
BackupContext.Builder
ExecutableBackup.Builder
.newBackupContextBuilder()
.setServer(server)
.setInitiator(ActionInitiator.Shutdown)
.setComment("shutdown")
.announce()
.build()
).call();
.call();
} catch (Exception ignored) {}
}
});

View File

@ -23,7 +23,7 @@ import net.minecraft.text.Text;
import net.minecraft.text.MutableText;
import net.minecraft.util.Formatting;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -112,7 +112,7 @@ public class TextileLogger {
sendFeedback(Level.INFO, source, msg, args);
}
public void sendInfo(BackupContext context, String msg, Object... args) {
public void sendInfo(ExecutableBackup context, String msg, Object... args) {
sendInfo(context.commandSource(), msg, args);
}
@ -120,7 +120,8 @@ public class TextileLogger {
sendFeedback(Level.ERROR, source, msg, args);
}
public void sendError(BackupContext context, String msg, Object... args) {
public void sendError(ExecutableBackup context, String msg, Object... args) {
sendError(context.commandSource(), msg, args);
}
@ -134,7 +135,7 @@ public class TextileLogger {
sendToPlayerAndLog(Level.INFO, source, msg, args);
}
public void sendInfoAL(BackupContext context, String msg, Object... args) {
public void sendInfoAL(ExecutableBackup context, String msg, Object... args) {
sendInfoAL(context.commandSource(), msg, args);
}
@ -142,7 +143,7 @@ public class TextileLogger {
sendToPlayerAndLog(Level.ERROR, source, msg, args);
}
public void sendErrorAL(BackupContext context, String msg, Object... args) {
public void sendErrorAL(ExecutableBackup context, String msg, Object... args) {
sendErrorAL(context.commandSource(), msg, args);
}
}

View File

@ -25,8 +25,7 @@ import net.minecraft.server.command.ServerCommandSource;
import net.szum123321.textile_backup.Globals;
import net.szum123321.textile_backup.TextileBackup;
import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.MakeBackupRunnableFactory;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import javax.annotation.Nullable;
@ -42,15 +41,13 @@ public class StartBackupCommand {
private static int execute(ServerCommandSource source, @Nullable String comment) {
Globals.INSTANCE.getQueueExecutor().submit(
MakeBackupRunnableFactory.create(
BackupContext.Builder
ExecutableBackup.Builder
.newBackupContextBuilder()
.setCommandSource(source)
.setComment(comment)
.guessInitiator()
.saveServer()
.build()
)
);
return 1;

View File

@ -1,119 +0,0 @@
/*
* A simple backup mod for Fabric
* Copyright (C) 2022 Szum123321
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.szum123321.textile_backup.core.create;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.Utilities;
import org.jetbrains.annotations.NotNull;
import java.time.LocalDateTime;
import java.util.NoSuchElementException;
public record BackupContext(@NotNull MinecraftServer server,
ServerCommandSource commandSource,
ActionInitiator initiator,
boolean save,
boolean cleanup,
String comment,
LocalDateTime startDate) {
public boolean startedByPlayer() {
return initiator == ActionInitiator.Player;
}
public boolean shouldSave() {
return save;
}
public static class Builder {
private MinecraftServer server;
private ServerCommandSource commandSource;
private ActionInitiator initiator;
private boolean save;
private boolean cleanup;
private String comment;
private boolean guessInitiator;
public Builder() {
this.server = null;
this.commandSource = null;
this.initiator = null;
this.save = false;
cleanup = true; //defaults
this.comment = null;
guessInitiator = false;
}
public static Builder newBackupContextBuilder() {
return new Builder();
}
public Builder setCommandSource(ServerCommandSource commandSource) {
this.commandSource = commandSource;
return this;
}
public Builder setServer(MinecraftServer server) {
this.server = server;
return this;
}
public Builder setInitiator(ActionInitiator initiator) {
this.initiator = initiator;
return this;
}
public Builder setComment(String comment) {
this.comment = comment;
return this;
}
public Builder guessInitiator() {
this.guessInitiator = true;
return this;
}
public Builder saveServer() {
this.save = true;
return this;
}
public Builder dontCleanup() {
this.cleanup = false;
return this;
}
public BackupContext build() {
if (guessInitiator) {
initiator = Utilities.wasSentByPlayer(commandSource) ? ActionInitiator.Player : ActionInitiator.ServerConsole;
} else if (initiator == null) throw new NoSuchElementException("No initiator provided!");
if (server == null) {
if (commandSource != null) setServer(commandSource.getServer());
else throw new RuntimeException("Neither MinecraftServer or ServerCommandSource were provided!");
}
return new BackupContext(server, commandSource, initiator, save, cleanup, comment, LocalDateTime.now());
}
}
}

View File

@ -53,14 +53,13 @@ public class BackupScheduler {
if(nextBackup <= now) {
//It's time to run
Globals.INSTANCE.getQueueExecutor().submit(
MakeBackupRunnableFactory.create(
BackupContext.Builder
ExecutableBackup.Builder
.newBackupContextBuilder()
.setServer(server)
.setInitiator(ActionInitiator.Timer)
.saveServer()
.announce()
.build()
)
);
nextBackup = now + config.get().backupInterval;
@ -76,14 +75,13 @@ public class BackupScheduler {
if(scheduled && nextBackup <= now) {
//Verify we hadn't done the final one, and it's time to do so
Globals.INSTANCE.getQueueExecutor().submit(
MakeBackupRunnableFactory.create(
BackupContext.Builder
ExecutableBackup.Builder
.newBackupContextBuilder()
.setServer(server)
.setInitiator(ActionInitiator.Timer)
.saveServer()
.announce()
.build()
)
);
scheduled = false;

View File

@ -0,0 +1,232 @@
package net.szum123321.textile_backup.core.create;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.szum123321.textile_backup.Globals;
import net.szum123321.textile_backup.TextileBackup;
import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.Cleanup;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.compressors.ParallelZipCompressor;
import net.szum123321.textile_backup.core.create.compressors.ZipCompressor;
import net.szum123321.textile_backup.core.create.compressors.tar.AbstractTarArchiver;
import net.szum123321.textile_backup.core.create.compressors.tar.ParallelGzipCompressor;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
public record ExecutableBackup(@NotNull MinecraftServer server,
ServerCommandSource commandSource,
ActionInitiator initiator,
boolean save,
boolean cleanup,
String comment,
LocalDateTime startDate) implements Callable<Void> {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static ConfigHelper config = ConfigHelper.INSTANCE;
public boolean startedByPlayer() {
return initiator == ActionInitiator.Player;
}
public void announce() {
if(config.get().broadcastBackupStart) {
Utilities.notifyPlayers(server,
"Warning! Server backup will begin shortly. You may experience some lag."
);
} else {
log.sendInfoAL(this, "Warning! Server backup will begin shortly. You may experience some lag.");
}
StringBuilder builder = new StringBuilder();
builder.append("Backup started ");
builder.append(initiator.getPrefix());
if(startedByPlayer())
builder.append(commandSource.getDisplayName().getString());
else
builder.append(initiator.getName());
builder.append(" on: ");
builder.append(Utilities.getDateTimeFormatter().format(LocalDateTime.now()));
log.info(builder.toString());
}
@Override
public Void call() throws IOException, ExecutionException, InterruptedException {
if (save) { //save the world
log.sendInfoAL(this, "Saving server...");
server.saveAll(true, true, false);
}
Path outFile = Utilities.getBackupRootPath(Utilities.getLevelName(server)).resolve(getFileName());
log.trace("Outfile is: {}", outFile);
try {
//I think I should synchronise these two next calls...
Utilities.disableWorldSaving(server);
Globals.INSTANCE.disableWatchdog = true;
Globals.INSTANCE.updateTMPFSFlag(server);
log.sendInfoAL(this, "Starting backup");
Path world = Utilities.getWorldFolder(server);
log.trace("Minecraft world is: {}", world);
Files.createDirectories(outFile.getParent());
Files.createFile(outFile);
int coreCount;
if (config.get().compressionCoreCountLimit <= 0) coreCount = Runtime.getRuntime().availableProcessors();
else
coreCount = Math.min(config.get().compressionCoreCountLimit, Runtime.getRuntime().availableProcessors());
log.trace("Running compression on {} threads. Available cores: {}", coreCount, Runtime.getRuntime().availableProcessors());
switch (config.get().format) {
case ZIP -> {
if (coreCount > 1 && !Globals.INSTANCE.disableTMPFS()) {
log.trace("Using PARALLEL Zip Compressor. Threads: {}", coreCount);
ParallelZipCompressor.getInstance().createArchive(world, outFile, this, coreCount);
} else {
log.trace("Using REGULAR Zip Compressor.");
ZipCompressor.getInstance().createArchive(world, outFile, this, coreCount);
}
}
case GZIP -> ParallelGzipCompressor.getInstance().createArchive(world, outFile, this, coreCount);
case TAR -> new AbstractTarArchiver().createArchive(world, outFile, this, coreCount);
}
if(cleanup) new Cleanup(commandSource, Utilities.getLevelName(server)).call();
if (config.get().broadcastBackupDone) Utilities.notifyPlayers(server, "Done!");
else log.sendInfoAL(this, "Done!");
} catch (Throwable e) {
//ExecutorService swallows exception, so I need to catch everything
log.error("An exception occurred when trying to create new backup file!", e);
if (ConfigHelper.INSTANCE.get().integrityVerificationMode.isStrict()) {
try {
Files.delete(outFile);
} catch (IOException ex) {
log.error("An exception occurred while trying go delete: {}", outFile, ex);
}
}
if (initiator == ActionInitiator.Player)
log.sendError(this, "An exception occurred when trying to create new backup file!");
throw e;
} finally {
Utilities.enableWorldSaving(server);
Globals.INSTANCE.disableWatchdog = false;
}
return null;
}
private String getFileName() {
return Utilities.getDateTimeFormatter().format(startDate) +
(comment != null ? "#" + comment.replaceAll("[\\\\/:*?\"<>|#]", "") : "") +
config.get().format.getCompleteString();
}
public static class Builder {
private MinecraftServer server;
private ServerCommandSource commandSource;
private ActionInitiator initiator;
private boolean save;
private boolean cleanup;
private String comment;
private boolean announce;
private boolean guessInitiator;
public Builder() {
this.server = null;
this.commandSource = null;
this.initiator = null;
this.save = false;
cleanup = true; //defaults
this.comment = null;
this.announce = false;
guessInitiator = false;
}
public static ExecutableBackup.Builder newBackupContextBuilder() {
return new ExecutableBackup.Builder();
}
public ExecutableBackup.Builder setCommandSource(ServerCommandSource commandSource) {
this.commandSource = commandSource;
return this;
}
public ExecutableBackup.Builder setServer(MinecraftServer server) {
this.server = server;
return this;
}
public ExecutableBackup.Builder setInitiator(ActionInitiator initiator) {
this.initiator = initiator;
return this;
}
public ExecutableBackup.Builder setComment(String comment) {
this.comment = comment;
return this;
}
public ExecutableBackup.Builder guessInitiator() {
this.guessInitiator = true;
return this;
}
public ExecutableBackup.Builder saveServer() {
this.save = true;
return this;
}
public ExecutableBackup.Builder noCleanup() {
this.cleanup = false;
return this;
}
public ExecutableBackup.Builder announce() {
this.announce = true;
return this;
}
public ExecutableBackup build() {
if (guessInitiator) {
initiator = Utilities.wasSentByPlayer(commandSource) ? ActionInitiator.Player : ActionInitiator.ServerConsole;
} else if (initiator == null) throw new NoSuchElementException("No initiator provided!");
if (server == null) {
if (commandSource != null) setServer(commandSource.getServer());
else throw new RuntimeException("Neither MinecraftServer or ServerCommandSource were provided!");
}
ExecutableBackup v = new ExecutableBackup(server, commandSource, initiator, save, cleanup, comment, LocalDateTime.now());
if(announce) v.announce();
return v;
}
}
}

View File

@ -1,138 +0,0 @@
/*
* A simple backup mod for Fabric
* Copyright (C) 2022 Szum123321
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.szum123321.textile_backup.core.create;
import net.szum123321.textile_backup.Globals;
import net.szum123321.textile_backup.TextileBackup;
import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.Cleanup;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.compressors.ParallelZipCompressor;
import net.szum123321.textile_backup.core.create.compressors.ZipCompressor;
import net.szum123321.textile_backup.core.create.compressors.tar.AbstractTarArchiver;
import net.szum123321.textile_backup.core.create.compressors.tar.ParallelBZip2Compressor;
import net.szum123321.textile_backup.core.create.compressors.tar.ParallelGzipCompressor;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
/**
* The actual object responsible for creating the backup
*/
public class MakeBackupRunnable implements Callable<Void> {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static ConfigHelper config = ConfigHelper.INSTANCE;
private final BackupContext context;
public MakeBackupRunnable(BackupContext context) {
this.context = context;
}
@Override
public Void call() throws IOException, ExecutionException, InterruptedException {
Path outFile = Utilities.getBackupRootPath(Utilities.getLevelName(context.server())).resolve(getFileName());
log.trace("Outfile is: {}", outFile);
try {
//I think I should synchronise these two next calls...
Utilities.disableWorldSaving(context.server());
Globals.INSTANCE.disableWatchdog = true;
Globals.INSTANCE.updateTMPFSFlag(context.server());
log.sendInfoAL(context, "Starting backup");
Path world = Utilities.getWorldFolder(context.server());
log.trace("Minecraft world is: {}", world);
Files.createDirectories(outFile.getParent());
Files.createFile(outFile);
int coreCount;
if (config.get().compressionCoreCountLimit <= 0) coreCount = Runtime.getRuntime().availableProcessors();
else
coreCount = Math.min(config.get().compressionCoreCountLimit, Runtime.getRuntime().availableProcessors());
log.trace("Running compression on {} threads. Available cores: {}", coreCount, Runtime.getRuntime().availableProcessors());
switch (config.get().format) {
case ZIP -> {
if (coreCount > 1 && !Globals.INSTANCE.disableTMPFS()) {
log.trace("Using PARALLEL Zip Compressor. Threads: {}", coreCount);
ParallelZipCompressor.getInstance().createArchive(world, outFile, context, coreCount);
} else {
log.trace("Using REGULAR Zip Compressor.");
ZipCompressor.getInstance().createArchive(world, outFile, context, coreCount);
}
}
case BZIP2 -> ParallelBZip2Compressor.getInstance().createArchive(world, outFile, context, coreCount);
case GZIP -> ParallelGzipCompressor.getInstance().createArchive(world, outFile, context, coreCount);
/* case LZMA -> new AbstractTarArchiver() {
protected OutputStream getCompressorOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException {
return new LZMACompressorOutputStream(stream);
}
}.createArchive(world, outFile, context, coreCount);*/
case TAR -> new AbstractTarArchiver().createArchive(world, outFile, context, coreCount);
}
if(context.cleanup())
new Cleanup(context.commandSource(), Utilities.getLevelName(context.server())).call();
if (config.get().broadcastBackupDone) Utilities.notifyPlayers(context.server(), "Done!");
else log.sendInfoAL(context, "Done!");
} catch (Throwable e) {
//ExecutorService swallows exception, so I need to catch everything
log.error("An exception occurred when trying to create new backup file!", e);
if (ConfigHelper.INSTANCE.get().integrityVerificationMode.isStrict()) {
try {
Files.delete(outFile);
} catch (IOException ex) {
log.error("An exception occurred while trying go delete: {}", outFile, ex);
}
}
if (context.initiator() == ActionInitiator.Player)
log.sendError(context, "An exception occurred when trying to create new backup file!");
throw e;
} finally {
Utilities.enableWorldSaving(context.server());
Globals.INSTANCE.disableWatchdog = false;
}
return null;
}
private String getFileName() {
return Utilities.getDateTimeFormatter().format(context.startDate()) +
(context.comment() != null ? "#" + context.comment().replaceAll("[\\\\/:*?\"<>|#]", "") : "") +
config.get().format.getCompleteString();
}
}

View File

@ -1,66 +0,0 @@
/*
* A simple backup mod for Fabric
* Copyright (C) 2022 Szum123321
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.szum123321.textile_backup.core.create;
import net.szum123321.textile_backup.TextileBackup;
import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.Utilities;
import java.time.LocalDateTime;
import java.util.concurrent.Callable;
public class MakeBackupRunnableFactory {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static ConfigHelper config = ConfigHelper.INSTANCE;
public static Callable<Void> create(BackupContext ctx) {
if(config.get().broadcastBackupStart) {
Utilities.notifyPlayers(ctx.server(),
"Warning! Server backup will begin shortly. You may experience some lag."
);
} else {
log.sendInfoAL(ctx, "Warning! Server backup will begin shortly. You may experience some lag.");
}
StringBuilder builder = new StringBuilder();
builder.append("Backup started ");
builder.append(ctx.initiator().getPrefix());
if(ctx.startedByPlayer())
builder.append(ctx.commandSource().getDisplayName().getString());
else
builder.append(ctx.initiator().getName());
builder.append(" on: ");
builder.append(Utilities.getDateTimeFormatter().format(LocalDateTime.now()));
log.info(builder.toString());
if (ctx.shouldSave()) {
log.sendInfoAL(ctx, "Saving server...");
ctx.server().saveAll(true, true, false);
}
return new MakeBackupRunnable(ctx);
}
}

View File

@ -23,8 +23,8 @@ import net.szum123321.textile_backup.TextileBackup;
import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.*;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.BrokenFileHandler;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import net.szum123321.textile_backup.core.create.FileInputStreamSupplier;
import net.szum123321.textile_backup.core.create.InputSupplier;
import net.szum123321.textile_backup.core.digest.FileTreeHashBuilder;
@ -44,7 +44,7 @@ import java.util.stream.Stream;
public abstract class AbstractCompressor {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
public void createArchive(Path inputFile, Path outputFile, BackupContext ctx, int coreLimit) throws IOException, ExecutionException, InterruptedException {
public void createArchive(Path inputFile, Path outputFile, ExecutableBackup ctx, int coreLimit) throws IOException, ExecutionException, InterruptedException {
Instant start = Instant.now();
BrokenFileHandler brokenFileHandler = new BrokenFileHandler(); //Basically a hashmap storing files and their respective exceptions
@ -106,7 +106,7 @@ public abstract class AbstractCompressor {
log.sendInfoAL(ctx, "Compression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
}
protected abstract OutputStream createArchiveOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException;
protected abstract OutputStream createArchiveOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) throws IOException;
protected abstract void addEntry(InputSupplier inputSupplier, OutputStream arc) throws IOException;
protected void finish(OutputStream arc) throws InterruptedException, ExecutionException, IOException {

View File

@ -21,7 +21,7 @@ package net.szum123321.textile_backup.core.create.compressors;
import net.szum123321.textile_backup.TextileBackup;
import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.NoSpaceLeftOnDeviceException;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import net.szum123321.textile_backup.core.create.InputSupplier;
import org.apache.commons.compress.archivers.zip.*;
@ -61,7 +61,7 @@ public class ParallelZipCompressor extends ZipCompressor {
}
@Override
protected OutputStream createArchiveOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) {
protected OutputStream createArchiveOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) {
scatterZipCreator = new ParallelScatterZipCreator(Executors.newFixedThreadPool(coreLimit));
return super.createArchiveOutputStream(stream, ctx, coreLimit);
}

View File

@ -20,7 +20,7 @@ package net.szum123321.textile_backup.core.create.compressors;
import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import net.szum123321.textile_backup.core.create.InputSupplier;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
@ -43,7 +43,7 @@ public class ZipCompressor extends AbstractCompressor {
}
@Override
protected OutputStream createArchiveOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) {
protected OutputStream createArchiveOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) {
ZipArchiveOutputStream arc = new ZipArchiveOutputStream(stream);
arc.setMethod(ZipArchiveOutputStream.DEFLATED);

View File

@ -18,7 +18,7 @@
package net.szum123321.textile_backup.core.create.compressors.tar;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import net.szum123321.textile_backup.core.create.compressors.AbstractCompressor;
import net.szum123321.textile_backup.core.create.InputSupplier;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
@ -28,12 +28,12 @@ import org.apache.commons.compress.utils.IOUtils;
import java.io.*;
public class AbstractTarArchiver extends AbstractCompressor {
protected OutputStream getCompressorOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException {
protected OutputStream getCompressorOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) throws IOException {
return stream;
}
@Override
protected OutputStream createArchiveOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException {
protected OutputStream createArchiveOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) throws IOException {
TarArchiveOutputStream tar = new TarArchiveOutputStream(getCompressorOutputStream(stream, ctx, coreLimit));
tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
tar.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);

View File

@ -18,7 +18,7 @@
package net.szum123321.textile_backup.core.create.compressors.tar;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import org.at4j.comp.bzip2.BZip2OutputStream;
import org.at4j.comp.bzip2.BZip2OutputStreamSettings;
@ -30,7 +30,7 @@ public class ParallelBZip2Compressor extends AbstractTarArchiver {
}
@Override
protected OutputStream getCompressorOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException {
protected OutputStream getCompressorOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) throws IOException {
return new BZip2OutputStream(stream, new BZip2OutputStreamSettings().setNumberOfEncoderThreads(coreLimit));
}
}

View File

@ -18,7 +18,7 @@
package net.szum123321.textile_backup.core.create.compressors.tar;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import org.anarres.parallelgzip.ParallelGZIPOutputStream;
import java.io.*;
@ -33,7 +33,7 @@ public class ParallelGzipCompressor extends AbstractTarArchiver {
}
@Override
protected OutputStream getCompressorOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException {
protected OutputStream getCompressorOutputStream(OutputStream stream, ExecutableBackup ctx, int coreLimit) throws IOException {
executorService = Executors.newFixedThreadPool(coreLimit);
return new ParallelGZIPOutputStream(stream, executorService);

View File

@ -26,8 +26,7 @@ import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.CompressionStatus;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.MakeBackupRunnableFactory;
import net.szum123321.textile_backup.core.create.ExecutableBackup;
import net.szum123321.textile_backup.core.restore.decompressors.GenericTarDecompressor;
import net.szum123321.textile_backup.core.restore.decompressors.ZipDecompressor;
import net.szum123321.textile_backup.mixin.MinecraftServerSessionAccessor;
@ -78,20 +77,19 @@ public class RestoreBackupRunnable implements Runnable {
ctx.server().getThread().join(); //wait for server thread to die and save all its state
if(config.get().backupOldWorlds) {
return MakeBackupRunnableFactory.create (
BackupContext.Builder
return ExecutableBackup.Builder
.newBackupContextBuilder()
.setServer(ctx.server())
.setInitiator(ActionInitiator.Restore)
.dontCleanup()
.noCleanup()
.setComment("Old_World" + (ctx.comment() != null ? "_" + ctx.comment() : ""))
.build()
).call();
.announce()
.build().call();
}
return null;
});
//run the thread.
new Thread(waitForShutdown, "Server shutdown wait thread").start();
try {
@ -106,7 +104,7 @@ public class RestoreBackupRunnable implements Runnable {
log.info("Waiting for server to fully terminate...");
//locks until the backup is finished
//locks until the backup is finished and the server is dead
waitForShutdown.get();
Optional<String> errorMsg;
@ -127,8 +125,8 @@ public class RestoreBackupRunnable implements Runnable {
if (errorMsg.isEmpty()) log.info("Backup valid. Restoring");
else log.info("Backup is damaged, but verification is disabled [{}]. Restoring", errorMsg.get());
((MinecraftServerSessionAccessor) ctx.server())
.getSession().close();
//Disables write lock to override world file
((MinecraftServerSessionAccessor) ctx.server()).getSession().close();
Utilities.deleteDirectory(worldFile);
Files.move(tmp, worldFile);