Moved around error handling. LocalDateTime is now passed with BackupContext. Replaced equals method with matches in ParallelZipCompressor.SimpleStackTraceElement to avert warning.
This commit is contained in:
parent
4007d8f86d
commit
dbb9a71749
@ -84,8 +84,8 @@ public class Globals {
|
||||
public Optional<Path> getLockedFile() { return Optional.ofNullable(lockedPath); }
|
||||
public void setLockedFile(Path p) { lockedPath = p; }
|
||||
|
||||
public boolean disableTMPFS() { return disableTMPFiles; }
|
||||
public void updateTMPFSFlag(MinecraftServer server) {
|
||||
public synchronized boolean disableTMPFS() { return disableTMPFiles; }
|
||||
public synchronized void updateTMPFSFlag(MinecraftServer server) {
|
||||
disableTMPFiles = false;
|
||||
Path tmp_dir = Path.of(System.getProperty("java.io.tmpdir"));
|
||||
if(
|
||||
|
@ -188,7 +188,9 @@ public class ConfigPOJO implements ConfigData {
|
||||
public enum ErrorHandlingMode {
|
||||
STRICT,
|
||||
PERMISSIBLE,
|
||||
VERY_PERMISSIBLE
|
||||
VERY_PERMISSIBLE;
|
||||
|
||||
public boolean isStrict() { return this == STRICT; }
|
||||
}
|
||||
|
||||
public enum ArchiveFormat {
|
||||
|
@ -18,7 +18,8 @@
|
||||
|
||||
package net.szum123321.textile_backup.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
@ -27,4 +28,19 @@ public record CompressionStatus(long treeHash, LocalDateTime date, long startTim
|
||||
public static final String DATA_FILENAME = "textile_status.data";
|
||||
public boolean isValid(long decompressedHash) { return true; }
|
||||
|
||||
public static CompressionStatus readFromFile(Path f) throws IOException, ClassNotFoundException {
|
||||
try(InputStream i = Files.newInputStream(f);
|
||||
ObjectInputStream obj = new ObjectInputStream(i)) {
|
||||
return (CompressionStatus) obj.readObject();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() throws IOException {
|
||||
try (ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
ObjectOutputStream o = new ObjectOutputStream(bo)) {
|
||||
o.writeObject(this);
|
||||
return bo.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,11 +24,14 @@ import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.szum123321.textile_backup.core.ActionInitiator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record BackupContext(@NotNull MinecraftServer server,
|
||||
ServerCommandSource commandSource,
|
||||
ActionInitiator initiator,
|
||||
boolean save,
|
||||
String comment) {
|
||||
String comment,
|
||||
LocalDateTime startDate) {
|
||||
|
||||
public boolean startedByPlayer() {
|
||||
return initiator == ActionInitiator.Player;
|
||||
@ -103,7 +106,7 @@ public record BackupContext(@NotNull MinecraftServer server,
|
||||
else throw new RuntimeException("Neither MinecraftServer or ServerCommandSource were provided!");
|
||||
}
|
||||
|
||||
return new BackupContext(server, commandSource, initiator, save, comment);
|
||||
return new BackupContext(server, commandSource, initiator, save, comment, LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* The actual object responsible for creating the backup
|
||||
@ -53,7 +52,14 @@ public class MakeBackupRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Path outFile = Utilities
|
||||
.getBackupRootPath(Utilities.getLevelName(context.server()))
|
||||
.resolve(getFileName());
|
||||
|
||||
log.trace("Outfile is: {}", outFile);
|
||||
|
||||
try {
|
||||
//I think I should synchronise those two next calls...
|
||||
Utilities.disableWorldSaving(context.server());
|
||||
Globals.INSTANCE.disableWatchdog = true;
|
||||
|
||||
@ -65,12 +71,6 @@ public class MakeBackupRunnable implements Runnable {
|
||||
|
||||
log.trace("Minecraft world is: {}", world);
|
||||
|
||||
Path outFile = Utilities
|
||||
.getBackupRootPath(Utilities.getLevelName(context.server()))
|
||||
.resolve(getFileName());
|
||||
|
||||
log.trace("Outfile is: {}", outFile);
|
||||
|
||||
Files.createDirectories(outFile.getParent());
|
||||
Files.createFile(outFile);
|
||||
|
||||
@ -118,6 +118,14 @@ public class MakeBackupRunnable implements Runnable {
|
||||
//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().errorErrorHandlingMode.isStrict()) {
|
||||
try {
|
||||
Files.delete(outFile);
|
||||
} catch (IOException ex) {
|
||||
log.error("An exception occurred while tryin go delete: {}", outFile, ex);
|
||||
}
|
||||
}
|
||||
|
||||
if(context.initiator() == ActionInitiator.Player)
|
||||
log.sendError(context, "An exception occurred when trying to create new backup file!");
|
||||
} finally {
|
||||
@ -127,9 +135,7 @@ public class MakeBackupRunnable implements Runnable {
|
||||
}
|
||||
|
||||
private String getFileName(){
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
return Utilities.getDateTimeFormatter().format(now) +
|
||||
return Utilities.getDateTimeFormatter().format(context.startDate()) +
|
||||
(context.comment() != null ? "#" + context.comment().replaceAll("[\\\\/:*?\"<>|#]", "") : "") +
|
||||
config.get().format.getCompleteString();
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ 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.config.ConfigHelper;
|
||||
import net.szum123321.textile_backup.config.ConfigPOJO;
|
||||
import net.szum123321.textile_backup.core.*;
|
||||
import net.szum123321.textile_backup.core.create.BackupContext;
|
||||
import net.szum123321.textile_backup.core.create.BrokenFileHandler;
|
||||
@ -42,14 +41,12 @@ 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) {
|
||||
public void createArchive(Path inputFile, Path outputFile, BackupContext ctx, int coreLimit) throws IOException, ExecutionException, InterruptedException {
|
||||
Instant start = Instant.now();
|
||||
|
||||
FileTreeHashBuilder fileHashBuilder = new FileTreeHashBuilder(() -> null); //TODO: select hashing algorithm
|
||||
BrokenFileHandler brokenFileHandler = new BrokenFileHandler();
|
||||
|
||||
boolean keep = true;
|
||||
|
||||
try (OutputStream outStream = Files.newOutputStream(outputFile);
|
||||
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outStream);
|
||||
OutputStream arc = createArchiveOutputStream(bufferedOutputStream, ctx, coreLimit);
|
||||
@ -62,39 +59,35 @@ public abstract class AbstractCompressor {
|
||||
Path file = it.next();
|
||||
|
||||
try {
|
||||
addEntry(new FileInputStreamSupplier(file, inputFile.relativize(file).toString(), fileHashBuilder, brokenFileHandler), arc);
|
||||
} catch (Exception e) {
|
||||
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode == ConfigPOJO.ErrorHandlingMode.STRICT) {
|
||||
keep = false;
|
||||
break;
|
||||
}
|
||||
addEntry(
|
||||
new FileInputStreamSupplier(
|
||||
file,
|
||||
inputFile.relativize(file).toString(),
|
||||
fileHashBuilder,
|
||||
brokenFileHandler),
|
||||
arc
|
||||
);
|
||||
} catch (IOException e) {
|
||||
brokenFileHandler.handle(file, e);
|
||||
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode.isStrict()) throw e;
|
||||
else log.sendErrorAL(ctx, "An exception occurred while trying to compress: {}",
|
||||
inputFile.relativize(file).toString(), e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//If there are still files left in the stream, we should handle them
|
||||
while(it.hasNext()) {
|
||||
Path file = it.next();
|
||||
brokenFileHandler.handle(file, new DataLeftException(Files.size(file)));
|
||||
}
|
||||
|
||||
Instant now = Instant.now();
|
||||
|
||||
CompressionStatus status = new CompressionStatus (
|
||||
fileHashBuilder.getValue(),
|
||||
null, start.toEpochMilli(), now.toEpochMilli(),
|
||||
ctx.startDate(), start.toEpochMilli(), now.toEpochMilli(),
|
||||
brokenFileHandler.get()
|
||||
);
|
||||
|
||||
//Serialize using gson?
|
||||
try (ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
ObjectOutputStream o = new ObjectOutputStream(bo)) {
|
||||
o.writeObject(status);
|
||||
addEntry(new StatusFileInputSupplier(bo.toByteArray()), arc);
|
||||
}
|
||||
addEntry(new StatusFileInputSupplier(status.serialize()), arc);
|
||||
|
||||
finish(arc);
|
||||
} catch(NoSpaceLeftOnDeviceException e) {
|
||||
} /*catch(NoSpaceLeftOnDeviceException e) {
|
||||
log.error("""
|
||||
CRITICAL ERROR OCCURRED!
|
||||
The backup is corrupt!
|
||||
@ -106,14 +99,14 @@ public abstract class AbstractCompressor {
|
||||
log.sendError(ctx, "Backup failed. The file is corrupt.");
|
||||
log.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
|
||||
}
|
||||
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode == ConfigPOJO.ErrorHandlingMode.STRICT) keep = false;
|
||||
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode.isStrict()) keep = false;
|
||||
} catch (IOException | InterruptedException | ExecutionException e) {
|
||||
log.error("An exception occurred!", e);
|
||||
if(ctx.initiator() == ActionInitiator.Player)
|
||||
log.sendError(ctx, "Something went wrong while compressing files!");
|
||||
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode == ConfigPOJO.ErrorHandlingMode.STRICT) keep = false;
|
||||
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode.isStrict()) keep = false;
|
||||
|
||||
} finally {
|
||||
} */finally {
|
||||
close();
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,7 @@ public class ParallelZipCompressor extends ZipCompressor {
|
||||
boolean match = (cause.getStackTrace().length >= STACKTRACE_NO_SPACE_ON_LEFT_ON_DEVICE.length);
|
||||
if(match) {
|
||||
for(int i = 0; i < STACKTRACE_NO_SPACE_ON_LEFT_ON_DEVICE.length && match; i++)
|
||||
if(!STACKTRACE_NO_SPACE_ON_LEFT_ON_DEVICE[i].equals(cause.getStackTrace()[i])) match = false;
|
||||
|
||||
if(!STACKTRACE_NO_SPACE_ON_LEFT_ON_DEVICE[i].matches(cause.getStackTrace()[i])) match = false;
|
||||
|
||||
//For clarity's sake let's not throw the ExecutionException itself rather only the cause, as the EE is just the wrapper
|
||||
if(match) throw new NoSpaceLeftOnDeviceException(cause);
|
||||
@ -113,17 +112,8 @@ public class ParallelZipCompressor extends ZipCompressor {
|
||||
String methodName,
|
||||
boolean isNative
|
||||
) {
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if(o.getClass() == StackTraceElement.class) {
|
||||
StackTraceElement that = (StackTraceElement) o;
|
||||
return (isNative == that.isNativeMethod()) && Objects.equals(className, that.getClassName()) && Objects.equals(methodName, that.getMethodName());
|
||||
}
|
||||
if(getClass() != o.getClass()) return false;
|
||||
SimpleStackTraceElement that = (SimpleStackTraceElement) o;
|
||||
return isNative == that.isNative && Objects.equals(className, that.className) && Objects.equals(methodName, that.methodName);
|
||||
public boolean matches(StackTraceElement o) {
|
||||
return (isNative == o.isNativeMethod()) && Objects.equals(className, o.getClassName()) && Objects.equals(methodName, o.getMethodName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user