Added safe restore

This commit is contained in:
Szum123321 2022-06-17 23:14:14 +02:00
parent b4597f6f1f
commit 3f1f1704b1
6 changed files with 58 additions and 48 deletions

View File

@ -85,12 +85,16 @@ public class TextileLogger {
log(Level.ERROR, msg, data); log(Level.ERROR, msg, data);
} }
void error(String message, Throwable throwable) {
logger.error(prefix + message, throwable);
}
public void fatal(String msg, Object... data) { public void fatal(String msg, Object... data) {
log(Level.FATAL, msg, data); log(Level.FATAL, msg, data);
} }
boolean sendFeedback(Level level, ServerCommandSource source, String msg, Object... args) { boolean sendFeedback(Level level, ServerCommandSource source, String msg, Object... args) {
if(source != null && source.getEntity() instanceof PlayerEntity) { if(source != null && source.isExecutedByPlayer()) {
MutableText text = Text.literal(messageFactory.newMessage(msg, args).getFormattedMessage()); MutableText text = Text.literal(messageFactory.newMessage(msg, args).getFormattedMessage());
if(level.intLevel() == Level.TRACE.intLevel()) text.formatted(Formatting.GREEN); if(level.intLevel() == Level.TRACE.intLevel()) text.formatted(Formatting.GREEN);

View File

@ -32,18 +32,20 @@ import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.Statics; import net.szum123321.textile_backup.Statics;
import net.szum123321.textile_backup.mixin.MinecraftServerSessionAccessor; import net.szum123321.textile_backup.mixin.MinecraftServerSessionAccessor;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.file.SimplePathVisitor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.time.*; import java.time.*;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
public class Utilities { public class Utilities {
private final static ConfigHelper config = ConfigHelper.INSTANCE; private final static ConfigHelper config = ConfigHelper.INSTANCE;
@ -80,6 +82,22 @@ public class Utilities {
return path; return path;
} }
public static void deleteDirectory(Path path) throws IOException {
Files.walkFileTree(path, new SimplePathVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
public static void updateTMPFSFlag(MinecraftServer server) { public static void updateTMPFSFlag(MinecraftServer server) {
boolean flag = false; boolean flag = false;
Path tmp_dir = Path.of(System.getProperty("java.io.tmpdir")); Path tmp_dir = Path.of(System.getProperty("java.io.tmpdir"));

View File

@ -31,7 +31,7 @@ import net.szum123321.textile_backup.core.create.BackupHelper;
import net.szum123321.textile_backup.core.restore.decompressors.GenericTarDecompressor; import net.szum123321.textile_backup.core.restore.decompressors.GenericTarDecompressor;
import net.szum123321.textile_backup.core.restore.decompressors.ZipDecompressor; import net.szum123321.textile_backup.core.restore.decompressors.ZipDecompressor;
import java.io.File; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -51,54 +51,60 @@ public class RestoreBackupRunnable implements Runnable {
log.info("Shutting down server..."); log.info("Shutting down server...");
ctx.getServer().stop(false); ctx.server().stop(false);
awaitServerShutdown(); awaitServerShutdown();
if(config.get().backupOldWorlds) { if(config.get().backupOldWorlds) {
BackupHelper.create( BackupHelper.create(
BackupContext.Builder BackupContext.Builder
.newBackupContextBuilder() .newBackupContextBuilder()
.setServer(ctx.getServer()) .setServer(ctx.server())
.setInitiator(ActionInitiator.Restore) .setInitiator(ActionInitiator.Restore)
.setComment("Old_World" + (ctx.getComment() != null ? "_" + ctx.getComment() : "")) .setComment("Old_World" + (ctx.comment() != null ? "_" + ctx.comment() : ""))
.build() .build()
).run(); ).run();
} }
Path worldFile = Utilities.getWorldFolder(ctx.getServer()).toPath(); Path worldFile = Utilities.getWorldFolder(ctx.server());
log.info("Deleting old world..."); try {
Path tmp = Files.createTempDirectory (
worldFile.getParent(),
ctx.restoreableFile().getFile().getFileName().toString()
);
if(!deleteDirectory(worldFile)) tmp.toFile().deleteOnExit();
log.error("Something went wrong while deleting old world!");
Files.createDirectories(worldFile); log.info("Starting decompression...");
log.info("Starting decompression..."); if (ctx.restoreableFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP)
ZipDecompressor.decompress(ctx.restoreableFile().getFile(), tmp);
else
GenericTarDecompressor.decompress(ctx.restoreableFile().getFile(), tmp);
if(ctx.getFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP) log.info("Deleting old world...");
ZipDecompressor.decompress(ctx.getFile().getFile().toPath(), worldFile);
else
GenericTarDecompressor.decompress(ctx.getFile().getFile().toPath(), worldFile);
if(config.get().deleteOldBackupAfterRestore) { Utilities.deleteDirectory(worldFile);
log.info("Deleting old backup");
if(!ctx.getFile().getFile().delete()) log.info("Something went wrong while deleting old backup"); Files.move(tmp, worldFile);
if (config.get().deleteOldBackupAfterRestore) {
log.info("Deleting old backup");
Files.delete(ctx.restoreableFile().getFile());
}
} catch (IOException e) {
log.error("An exception occurred while trying to restore a backup!", e);
} }
//in case we're playing on client //in case we're playing on client
Statics.globalShutdownBackupFlag.set(true); Statics.globalShutdownBackupFlag.set(true);
log.info("Done!"); log.info("Done!");
//Might solve #37
//Idk if it's a good idea...
//Runtime.getRuntime().exit(0);
} }
private void awaitServerShutdown() { private void awaitServerShutdown() {
while(((LivingServer)ctx.getServer()).isAlive()) { while(((LivingServer)ctx.server()).isAlive()) {
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -106,15 +112,4 @@ public class RestoreBackupRunnable implements Runnable {
} }
} }
} }
private static boolean deleteDirectory(File f) {
boolean state = true;
if(f.isDirectory()) {
for(File f2 : f.listFiles())
state &= deleteDirectory(f2);
}
return f.delete() && state;
}
} }

View File

@ -98,9 +98,9 @@ public class RestoreHelper {
private RestoreableFile(Path file) throws NoSuchElementException { private RestoreableFile(Path file) throws NoSuchElementException {
this.file = file; this.file = file;
archiveFormat = Utilities.getArchiveExtension(file).orElseThrow(() -> new NoSuchElementException("Couldn't get restoreableFile extension!")); archiveFormat = Utilities.getArchiveExtension(file).orElseThrow(() -> new NoSuchElementException("Couldn't get file extension!"));
String extension = archiveFormat.getCompleteString(); String extension = archiveFormat.getCompleteString();
creationTime = Utilities.getFileCreationTime(file).orElseThrow(() -> new NoSuchElementException("Couldn't get restoreableFile creation time!")); creationTime = Utilities.getFileCreationTime(file).orElseThrow(() -> new NoSuchElementException("Couldn't get file creation time!"));
final String filename = file.getFileName().toString(); final String filename = file.getFileName().toString();

View File

@ -36,7 +36,7 @@ import java.time.Instant;
public class GenericTarDecompressor { public class GenericTarDecompressor {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME); private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
public static void decompress(Path input, Path target) { public static void decompress(Path input, Path target) throws IOException {
Instant start = Instant.now(); Instant start = Instant.now();
try (InputStream fileInputStream = Files.newInputStream(input); try (InputStream fileInputStream = Files.newInputStream(input);
@ -60,13 +60,11 @@ public class GenericTarDecompressor {
try (OutputStream outputStream = Files.newOutputStream(file); try (OutputStream outputStream = Files.newOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) { BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
IOUtils.copy(archiveInputStream, bufferedOutputStream); IOUtils.copy(archiveInputStream, bufferedOutputStream);
} catch (IOException e) {
log.error("An exception occurred while trying to decompress file: {}", file.getFileName().toString(), e);
} }
} }
} }
} catch (IOException | CompressorException e) { } catch (CompressorException e) {
log.error("An exception occurred! ", e); throw new IOException(e);
} }
log.info("Decompression took {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now()))); log.info("Decompression took {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));

View File

@ -35,7 +35,7 @@ import java.util.Iterator;
public class ZipDecompressor { public class ZipDecompressor {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME); private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
public static void decompress(Path inputFile, Path target) { public static void decompress(Path inputFile, Path target) throws IOException {
Instant start = Instant.now(); Instant start = Instant.now();
try(ZipFile zipFile = new ZipFile(inputFile.toFile())) { try(ZipFile zipFile = new ZipFile(inputFile.toFile())) {
@ -50,14 +50,9 @@ public class ZipDecompressor {
try (OutputStream outputStream = Files.newOutputStream(file); try (OutputStream outputStream = Files.newOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) { BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
IOUtils.copy(zipFile.getInputStream(entry), bufferedOutputStream); IOUtils.copy(zipFile.getInputStream(entry), bufferedOutputStream);
} catch (IOException e) {
log.error("An exception occurred while trying to decompress file: {}", entry.getName(), e);
} }
} }
} }
} catch (IOException e) {
log.error("An exception occurred! ", e);
} }
log.info("Decompression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now()))); log.info("Decompression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));