Improved log message in Backup engine
This commit is contained in:
parent
148099a4d2
commit
dcfbb3e06a
@ -1,5 +1,9 @@
|
|||||||
package fr.pandacube.lib.paper.modules.backup;
|
package fr.pandacube.lib.paper.modules.backup;
|
||||||
|
|
||||||
|
import fr.pandacube.lib.chat.Chat;
|
||||||
|
import fr.pandacube.lib.util.Log;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
@ -10,10 +14,12 @@ import java.util.TreeSet;
|
|||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import fr.pandacube.lib.util.Log;
|
import static fr.pandacube.lib.chat.ChatStatic.text;
|
||||||
|
|
||||||
public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTime>> {
|
public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTime>> {
|
||||||
|
|
||||||
|
private static final boolean testOnly = true; // if true, no files are deleted
|
||||||
|
|
||||||
public static BackupCleaner KEEPING_N_LAST(int n) {
|
public static BackupCleaner KEEPING_N_LAST(int n) {
|
||||||
return new BackupCleaner() {
|
return new BackupCleaner() {
|
||||||
@Override
|
@Override
|
||||||
@ -66,17 +72,17 @@ public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void cleanupArchives(File archiveDir) {
|
public void cleanupArchives(File archiveDir, String compressDisplayName) {
|
||||||
String[] files = archiveDir.list();
|
String[] files = archiveDir.list();
|
||||||
|
|
||||||
Log.info("[Backup] Cleaning up backup directory " + archiveDir + "...");
|
Log.info("[Backup] Cleaning up backup directory " + ChatColor.GRAY + compressDisplayName + ChatColor.RESET + "...");
|
||||||
|
|
||||||
TreeMap<LocalDateTime, File> datedFiles = new TreeMap<>();
|
TreeMap<LocalDateTime, File> datedFiles = new TreeMap<>();
|
||||||
|
|
||||||
for (String filename : files) {
|
for (String filename : files) {
|
||||||
File file = new File(archiveDir, filename);
|
File file = new File(archiveDir, filename);
|
||||||
if (!filename.matches("\\d{8}-\\d{6}\\.zip")) {
|
if (!filename.matches("\\d{8}-\\d{6}\\.zip")) {
|
||||||
Log.warning("[Backup] Invalid file in backup directory: " + file);
|
Log.warning("[Backup] " + ChatColor.GRAY + compressDisplayName + ChatColor.RESET + " Invalid file in backup directory: " + filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +91,7 @@ public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTi
|
|||||||
try {
|
try {
|
||||||
ldt = LocalDateTime.parse(dateTimeStr, CompressProcess.dateFileNameFormatter);
|
ldt = LocalDateTime.parse(dateTimeStr, CompressProcess.dateFileNameFormatter);
|
||||||
} catch (DateTimeParseException e) {
|
} catch (DateTimeParseException e) {
|
||||||
Log.warning("Unable to parse file name to a date-time: " + file, e);
|
Log.warning("[Backup] " + ChatColor.GRAY + compressDisplayName + ChatColor.RESET + " Unable to parse file name to a date-time: " + filename, e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,14 +100,31 @@ public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTi
|
|||||||
|
|
||||||
TreeSet<LocalDateTime> keptFiles = apply(new TreeSet<>(datedFiles.keySet()));
|
TreeSet<LocalDateTime> keptFiles = apply(new TreeSet<>(datedFiles.keySet()));
|
||||||
|
|
||||||
|
Chat c = text("[Backup] ")
|
||||||
|
.then(text(compressDisplayName).gray())
|
||||||
|
.thenText(testOnly ? " Archive cleanup debug (no files are actually deleted):" : "Deleted archive files:\n");
|
||||||
|
boolean oneDeleted = false;
|
||||||
for (Entry<LocalDateTime, File> datedFile : datedFiles.entrySet()) {
|
for (Entry<LocalDateTime, File> datedFile : datedFiles.entrySet()) {
|
||||||
if (keptFiles.contains(datedFile.getKey()))
|
if (keptFiles.contains(datedFile.getKey())) {
|
||||||
|
if (testOnly)
|
||||||
|
c.thenText("- " + datedFile.getValue().getName() + " ")
|
||||||
|
.thenSuccess("kept")
|
||||||
|
.thenText(".\n");
|
||||||
continue;
|
continue;
|
||||||
// datedFile.getValue().delete(); // TODO check if the filtering is ok before actually removing files
|
}
|
||||||
Log.info("[Backup] Removed expired backup file " + datedFile.getValue());
|
oneDeleted = true;
|
||||||
|
c.thenText("- " + datedFile.getValue().getName() + " ");
|
||||||
|
if (testOnly)
|
||||||
|
c.thenFailure("deleted")
|
||||||
|
.thenText(".\n");
|
||||||
|
else
|
||||||
|
datedFile.getValue().delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.info("[Backup] Backup directory " + archiveDir + " cleaned.");
|
if (testOnly || oneDeleted)
|
||||||
|
Log.warning(c.getLegacyText());
|
||||||
|
|
||||||
|
Log.info("[Backup] Backup directory " + ChatColor.GRAY + compressDisplayName + ChatColor.RESET + " cleaned.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,101 +52,106 @@ public abstract class CompressProcess implements Comparable<CompressProcess>, Ru
|
|||||||
|
|
||||||
protected abstract File getTargetDir();
|
protected abstract File getTargetDir();
|
||||||
|
|
||||||
|
protected abstract String getDisplayName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
backupManager.compressRunning.set(this);
|
backupManager.compressRunning.set(this);
|
||||||
|
|
||||||
BiPredicate<File, String> filter = getFilenameFilter();
|
try {
|
||||||
File sourceDir = getSourceDir();
|
BiPredicate<File, String> filter = getFilenameFilter();
|
||||||
|
File sourceDir = getSourceDir();
|
||||||
|
|
||||||
if (!sourceDir.exists()) {
|
if (!sourceDir.exists()) {
|
||||||
Log.warning(String.format("%% unable to compress %s (check path: %s)", name, sourceDir.getPath()));
|
Log.warning("[Backup] Unable to compress " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + ": source directory " + sourceDir + " doesn’t exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File targetDir = getTargetDir();
|
||||||
|
File target = new File(targetDir, getDateFileName() + ".zip");
|
||||||
|
|
||||||
|
|
||||||
|
BossBar bossBar = BossBar.bossBar(Chat.text("Archivage"), 0, Color.YELLOW, Overlay.NOTCHED_20);
|
||||||
|
AutoUpdatedBossBar auBossBar = new AutoUpdatedBossBar(bossBar, (bar) -> {
|
||||||
|
bar.setTitle(Chat.infoText("Archivage ")
|
||||||
|
.thenData(getDisplayName())
|
||||||
|
.thenText(" : ")
|
||||||
|
.then(compressor == null
|
||||||
|
? Chat.text("Démarrage...")
|
||||||
|
: compressor.getState()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
bar.setProgress(compressor == null ? 0 : compressor.getProgress());
|
||||||
|
});
|
||||||
|
auBossBar.scheduleUpdateTimeSyncThreadAsync(100, 100);
|
||||||
|
|
||||||
|
onCompressStart();
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(PandaLibPaper.getPlugin(), () -> {
|
||||||
|
Log.info("[Backup] Starting for " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + " ...");
|
||||||
|
|
||||||
|
compressor = new ZipCompressor(sourceDir, target, 9, filter);
|
||||||
|
|
||||||
|
PerformanceAnalysisManager.getInstance().addBossBar(bossBar);
|
||||||
|
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
compressor.compress();
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
|
||||||
|
Log.info("[Backup] Finished for " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET);
|
||||||
|
|
||||||
|
backupManager.persist.updateDirtyStatusAfterCompress(type, name);
|
||||||
|
|
||||||
|
displayDirtynessStatus();
|
||||||
|
|
||||||
|
try {
|
||||||
|
type.backupCleaner(backupManager.config).cleanupArchives(targetDir, getDisplayName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.severe(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
Log.severe("[Backup] Failed: " + sourceDir + " -> " + target, e);
|
||||||
|
|
||||||
|
FileUtils.delete(target);
|
||||||
|
if (target.exists())
|
||||||
|
Log.warning("unable to delete: " + target);
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
backupManager.compressRunning.set(null);
|
||||||
|
boolean successF = success;
|
||||||
|
Bukkit.getScheduler().runTask(PandaLibPaper.getPlugin(), () -> onCompressEnd(successF));
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(2000);
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
PerformanceAnalysisManager.getInstance().removeBossBar(bossBar);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
backupManager.compressRunning.set(null);
|
backupManager.compressRunning.set(null);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File targetDir = getTargetDir();
|
|
||||||
File target = new File(targetDir, getDateFileName() + ".zip");
|
|
||||||
|
|
||||||
|
|
||||||
BossBar bossBar = BossBar.bossBar(Chat.text("Archivage"), 0, Color.YELLOW, Overlay.NOTCHED_20);
|
|
||||||
AutoUpdatedBossBar auBossBar = new AutoUpdatedBossBar(bossBar, (bar) -> {
|
|
||||||
bar.setTitle(Chat.infoText("Archivage ")
|
|
||||||
.thenData(type + "\\" + name)
|
|
||||||
.thenText(" : ")
|
|
||||||
.then(compressor == null
|
|
||||||
? Chat.text("Démarrage...")
|
|
||||||
: compressor.getState()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
bar.setProgress(compressor == null ? 0 : compressor.getProgress());
|
|
||||||
});
|
|
||||||
auBossBar.scheduleUpdateTimeSyncThreadAsync(100, 100);
|
|
||||||
|
|
||||||
onCompressStart();
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(PandaLibPaper.getPlugin(), () -> {
|
|
||||||
Log.info("[Backup] starting for " + ChatColor.GRAY + type + "\\" + name + ChatColor.RESET + " ...");
|
|
||||||
|
|
||||||
compressor = new ZipCompressor(sourceDir, target, 9, filter);
|
|
||||||
|
|
||||||
PerformanceAnalysisManager.getInstance().addBossBar(bossBar);
|
|
||||||
|
|
||||||
boolean success = false;
|
|
||||||
try {
|
|
||||||
compressor.compress();
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
|
|
||||||
Log.info("[Backup] finished for " + ChatColor.GRAY + type + "\\" + name + ChatColor.RESET);
|
|
||||||
|
|
||||||
backupManager.persist.updateDirtyStatusAfterCompress(type, name);
|
|
||||||
|
|
||||||
displayDirtynessStatus();
|
|
||||||
|
|
||||||
try {
|
|
||||||
type.backupCleaner(backupManager.config).cleanupArchives(targetDir);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.severe(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (final Exception e) {
|
|
||||||
Log.severe("[Backup] Failed: " + sourceDir + " -> " + target, e);
|
|
||||||
|
|
||||||
FileUtils.delete(target);
|
|
||||||
if (target.exists())
|
|
||||||
Log.warning("unable to delete: " + target);
|
|
||||||
} finally {
|
|
||||||
|
|
||||||
backupManager.compressRunning.set(null);
|
|
||||||
boolean successF = success;
|
|
||||||
Bukkit.getScheduler().runTask(PandaLibPaper.getPlugin(), () -> onCompressEnd(successF));
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(2000);
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
PerformanceAnalysisManager.getInstance().removeBossBar(bossBar);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void displayDirtynessStatus() {
|
public void displayDirtynessStatus() {
|
||||||
if (hasNextScheduled() && type == Type.WORLDS) {
|
if (hasNextScheduled() && type == Type.WORLDS) {
|
||||||
Log.info("[Backup] " + ChatColor.GRAY + type + "\\" + name + ChatColor.RESET + " is dirty. Next backup on "
|
Log.info("[Backup] " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + " is dirty. Next backup on "
|
||||||
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date(getNext())));
|
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date(getNext())));
|
||||||
}
|
}
|
||||||
else if (hasNextScheduled()) {
|
else if (hasNextScheduled()) {
|
||||||
Log.info("[Backup] " + ChatColor.GRAY + type + "\\" + name + ChatColor.RESET + " next backup on "
|
Log.info("[Backup] " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + " next backup on "
|
||||||
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date(getNext())));
|
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date(getNext())));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.info("[Backup] " + ChatColor.GRAY + type + "\\" + name + ChatColor.RESET + " is clean. Next backup not scheduled.");
|
Log.info("[Backup] " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + " is clean. Next backup not scheduled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +175,7 @@ public abstract class CompressProcess implements Comparable<CompressProcess>, Ru
|
|||||||
public void logProgress() {
|
public void logProgress() {
|
||||||
if (compressor == null)
|
if (compressor == null)
|
||||||
return;
|
return;
|
||||||
Log.info("[Backup] " + ChatColor.GRAY + type + "\\" + name + ChatColor.RESET + ": " + compressor.getState().getLegacyText());
|
Log.info("[Backup] " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + ": " + compressor.getState().getLegacyText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,11 @@ public class CompressWorkdirProcess extends CompressProcess {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File getTargetDir() {
|
protected File getTargetDir() {
|
||||||
return new File(backupManager.config.backupDirectory, "workdir");
|
return new File(backupManager.config.backupDirectory, type.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDisplayName() {
|
||||||
|
return type.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,11 @@ public class CompressWorldProcess extends CompressProcess {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File getTargetDir() {
|
protected File getTargetDir() {
|
||||||
return new File(backupManager.config.backupDirectory, type.toString() + "/" + name);
|
return new File(backupManager.config.backupDirectory, type + "/" + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDisplayName() {
|
||||||
|
return type + "/" + name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import java.io.IOException;
|
|||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
@ -74,7 +75,7 @@ public class Persist extends YamlConfiguration {
|
|||||||
return;
|
return;
|
||||||
if (!isDirty(Type.WORLDS, world.getName())) { // don't set dirty if it is already
|
if (!isDirty(Type.WORLDS, world.getName())) { // don't set dirty if it is already
|
||||||
setDirtySinceNow(Type.WORLDS, world.getName());
|
setDirtySinceNow(Type.WORLDS, world.getName());
|
||||||
Log.info("[Backup] " + Type.WORLDS + "\\" + world.getName() + " was saved and is now dirty. Next backup on "
|
Log.info("[Backup] " + ChatColor.GRAY + Type.WORLDS + "/" + world.getName() + ChatColor.RESET + " was saved and is now dirty. Next backup on "
|
||||||
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG)
|
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG)
|
||||||
.format(new Date(backupManager.getNextCompress(System.currentTimeMillis())))
|
.format(new Date(backupManager.getNextCompress(System.currentTimeMillis())))
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user