Added safe restore
This commit is contained in:
parent
b4597f6f1f
commit
3f1f1704b1
@ -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);
|
||||||
|
@ -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"));
|
||||||
|
@ -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.getFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP)
|
if (ctx.restoreableFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP)
|
||||||
ZipDecompressor.decompress(ctx.getFile().getFile().toPath(), worldFile);
|
ZipDecompressor.decompress(ctx.restoreableFile().getFile(), tmp);
|
||||||
else
|
else
|
||||||
GenericTarDecompressor.decompress(ctx.getFile().getFile().toPath(), worldFile);
|
GenericTarDecompressor.decompress(ctx.restoreableFile().getFile(), tmp);
|
||||||
|
|
||||||
if(config.get().deleteOldBackupAfterRestore) {
|
log.info("Deleting old world...");
|
||||||
|
|
||||||
|
Utilities.deleteDirectory(worldFile);
|
||||||
|
|
||||||
|
Files.move(tmp, worldFile);
|
||||||
|
|
||||||
|
if (config.get().deleteOldBackupAfterRestore) {
|
||||||
log.info("Deleting old backup");
|
log.info("Deleting old backup");
|
||||||
|
|
||||||
if(!ctx.getFile().getFile().delete()) log.info("Something went wrong while 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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();
|
||||||
|
|
||||||
|
@ -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())));
|
||||||
|
@ -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())));
|
||||||
|
Loading…
Reference in New Issue
Block a user