Commented some more code.

BackupScheduler is now static
This commit is contained in:
Szum123321 2022-08-31 22:53:30 +02:00
parent 6707e813b2
commit 81c5cd04cb
12 changed files with 50 additions and 24 deletions

View File

@ -36,16 +36,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class Globals {
public static final Globals INSTANCE = new Globals();
public final static DateTimeFormatter defaultDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
public final static DateTimeFormatter defaultDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
private ExecutorService executorService = Executors.newSingleThreadExecutor();
public final AtomicBoolean globalShutdownBackupFlag = new AtomicBoolean(true);
public boolean disableWatchdog = false;
private boolean disableTMPFiles = false;
private AwaitThread restoreAwaitThread = null;
private Path lockedPath = null;

View File

@ -55,7 +55,7 @@ public class TextileBackup implements ModInitializer {
ConfigHelper.updateInstance(AutoConfig.register(ConfigPOJO.class, JanksonConfigSerializer::new));
ServerTickEvents.END_SERVER_TICK.register(new BackupScheduler()::tick);
ServerTickEvents.END_SERVER_TICK.register(BackupScheduler::tick);
//Restart Executor Service in single-player
ServerLifecycleEvents.SERVER_STARTING.register(server -> {
@ -63,6 +63,7 @@ public class TextileBackup implements ModInitializer {
Globals.INSTANCE.updateTMPFSFlag(server);
});
//Wait 60s for already submited backups to finish. After that kill the bastards and run the one last if required
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
Globals.INSTANCE.shutdownQueueExecutor(60000);

View File

@ -18,10 +18,13 @@
package net.szum123321.textile_backup.core;
/**
* Enum representing possible sources of action
*/
public enum ActionInitiator {
Player("Player", "by"),
ServerConsole("Server Console", "from"),
Timer("Timer", "by"),
ServerConsole("Server Console", "from"), //some/ting typed a command and it was not a player (command blocks and server console count)
Timer("Timer", "by"), //a.k.a scheduler
Shutdown("Server Shutdown", "by"),
Restore("Backup Restoration", "because of"),
Null("Null (That shouldn't have happened)", "form");

View File

@ -33,6 +33,9 @@ import java.time.ZoneOffset;
import java.util.Objects;
import java.util.stream.Stream;
/**
* Set of utility used for removing old backups
*/
public class Cleanup {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static ConfigHelper config = ConfigHelper.INSTANCE;
@ -55,7 +58,7 @@ public class Cleanup {
}
final int noToKeep = config.get().backupsToKeep > 0 ? config.get().backupsToKeep : Integer.MAX_VALUE;
final long maxSize = config.get().maxSize > 0 ? config.get().maxSize * 1024: Long.MAX_VALUE;
final long maxSize = config.get().maxSize > 0 ? config.get().maxSize * 1024: Long.MAX_VALUE; //max number of bytes to keep
long[] counts = count(root);
long n = counts[0], size = counts[1];

View File

@ -40,6 +40,9 @@ import java.util.stream.Stream;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
/**
* This class parses backup files, extracting its creation time, format and possibly comment
*/
public class RestoreableFile implements Comparable<RestoreableFile> {
private final Path file;
private final ConfigPOJO.ArchiveFormat archiveFormat;
@ -53,6 +56,7 @@ public class RestoreableFile implements Comparable<RestoreableFile> {
this.comment = comment;
}
//removes repetition of the files stream thingy with awfully large lambdas
public static <T> T applyOnFiles(Path root, T def, Consumer<IOException> errorConsumer, Function<Stream<RestoreableFile>, T> streamConsumer) {
try (Stream<Path> stream = Files.list(root)) {
return streamConsumer.apply(stream.flatMap(f -> RestoreableFile.build(f).stream()));

View File

@ -65,7 +65,6 @@ public class Utilities {
.getWorldDirectory(World.OVERWORLD);
}
public static void deleteDirectory(Path path) throws IOException {
Files.walkFileTree(path, new SimplePathVisitor() {
@Override

View File

@ -21,12 +21,9 @@ package net.szum123321.textile_backup.core.create;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.Util;
import net.szum123321.textile_backup.core.ActionInitiator;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public record BackupContext(@NotNull MinecraftServer server,
ServerCommandSource commandSource,
ActionInitiator initiator,
@ -103,8 +100,7 @@ public record BackupContext(@NotNull MinecraftServer server,
if (server == null) {
if (commandSource != null) setServer(commandSource.getServer());
else
throw new RuntimeException("Neither MinecraftServer or ServerCommandSource were provided!");
else throw new RuntimeException("Neither MinecraftServer or ServerCommandSource were provided!");
}
return new BackupContext(server, commandSource, initiator, save, comment);

View File

@ -25,24 +25,32 @@ import net.szum123321.textile_backup.core.ActionInitiator;
import java.time.Instant;
/**
* Runs backup on a preset interval
* <br>
* The important thing to note: <br>
* In the case that <code>doBackupsOnEmptyServer == false</code> and there have been made backups with players online,
* then everyone left the backup that was scheduled with player is still going to run. So it might appear as though there
* has been made backup with no players online despite the config. This is the expected behaviour
* <br>
* Furthermore, it uses system time
*/
public class BackupScheduler {
private final static ConfigHelper config = ConfigHelper.INSTANCE;
private boolean scheduled;
private long nextBackup;
//Scheduled flag tells whether we have decided to run another backup
private static boolean scheduled = false;
private static long nextBackup = - 1;
public BackupScheduler() {
scheduled = false;
nextBackup = -1;
}
public void tick(MinecraftServer server) {
public static void tick(MinecraftServer server) {
if(config.get().backupInterval < 1) return;
long now = Instant.now().getEpochSecond();
if(config.get().doBackupsOnEmptyServer || server.getPlayerManager().getCurrentPlayerCount() > 0) {
//Either just run backup with no one playing or there's at least one player
if(scheduled) {
if(nextBackup <= now) {
//It's time to run
Globals.INSTANCE.getQueueExecutor().submit(
MakeBackupRunnableFactory.create(
BackupContext.Builder
@ -57,11 +65,15 @@ public class BackupScheduler {
nextBackup = now + config.get().backupInterval;
}
} else {
//Either server just started or a new player joined after the last backup has finished
//So let's schedule one some time from now
nextBackup = now + config.get().backupInterval;
scheduled = true;
}
} else if(!config.get().doBackupsOnEmptyServer && server.getPlayerManager().getCurrentPlayerCount() == 0) {
//Do the final backup. No one's on-line and doBackupsOnEmptyServer == false
if(scheduled && nextBackup <= now) {
//Verify we hadn't done the final one and its time to do so
Globals.INSTANCE.getQueueExecutor().submit(
MakeBackupRunnableFactory.create(
BackupContext.Builder

View File

@ -37,6 +37,9 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
/**
* The actual object responsible for creating the backup
*/
public class MakeBackupRunnable implements Runnable {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static ConfigHelper config = ConfigHelper.INSTANCE;
@ -87,7 +90,7 @@ public class MakeBackupRunnable implements Runnable {
log.trace("Using PARALLEL Zip Compressor. Threads: {}", coreCount);
} else {
ZipCompressor.getInstance().createArchive(world, outFile, context, coreCount);
log.trace("Using REGULAR Zip Compressor. Threads: {}");
log.trace("Using REGULAR Zip Compressor.");
}
}
case BZIP2 -> ParallelBZip2Compressor.getInstance().createArchive(world, outFile, context, coreCount);

View File

@ -33,6 +33,9 @@ import java.time.Instant;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;
/**
* Basic abstract class representing directory compressor
*/
public abstract class AbstractCompressor {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
@ -88,7 +91,7 @@ public abstract class AbstractCompressor {
protected abstract void addEntry(Path file, String entryName, OutputStream arc) throws IOException;
protected void finish(OutputStream arc) throws InterruptedException, ExecutionException, IOException {
//Basically this function is only needed for the ParallelZipCompressor to write out ParallelScatterZipCreator
//This function is only needed for the ParallelZipCompressor to write out ParallelScatterZipCreator
}
protected void close() {

View File

@ -35,6 +35,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
//TODO: Verify backup's validity?
public class RestoreBackupRunnable implements Runnable {
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static ConfigHelper config = ConfigHelper.INSTANCE;

View File

@ -25,6 +25,10 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
/**
* This mixin should numb Watchdog while a backup runs.
* If works as intended solves issues with watchdog errors
*/
@Mixin(DedicatedServerWatchdog.class)
public class DedicatedServerWatchdogMixin {