Skip to content

Commit

Permalink
Add option to only backup claimed chunks (#101)
Browse files Browse the repository at this point in the history
* switch backups to common compress lib & add max folder size config

* Change uncompressed backup to a STORED zip instead of folder

* disabled by default

* stringbuilder be gone

* custom-named backups should be deleted by default

* iterator isn't necessary anymore

* add option to only backup claimed chunks

* no need to remap the ChunkDimPos' to long

* much more optimized solution for mapping claims to their region file

* update configs

* update configs

* make backups fall back to using native java zip if commons compress is somehow missing

---------

Co-authored-by: Martin Robertz <dream-master@gmx.net>
  • Loading branch information
Lyfts and Dream-Master authored Sep 13, 2024
1 parent 9b013ce commit b82a106
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 60 deletions.
6 changes: 6 additions & 0 deletions src/main/java/serverutils/ServerUtilitiesConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,12 @@ public static class Backups {
@Config.Comment("Delete backups that have a custom name set through /backup start <name>")
@Config.DefaultBoolean(true)
public boolean delete_custom_name_backups;

@Config.Comment("""
Only include claimed chunks in backup.
Backups will be much faster and smaller, but any unclaimed chunk will be unrecoverable.""")
@Config.DefaultBoolean(false)
public boolean only_backup_claimed_chunks;
}

public static class Login {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/serverutils/data/ClaimedChunks.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ public Collection<ClaimedChunk> getAllChunks() {
return map.isEmpty() ? Collections.emptyList() : map.values();
}

public Set<ChunkDimPos> getAllClaimedPositions() {
return map.isEmpty() ? Collections.emptySet() : map.keySet();
}

public Set<ClaimedChunk> getTeamChunks(@Nullable ForgeTeam team, OptionalInt dimension, boolean includePending) {
if (team == null) {
return Collections.emptySet();
Expand Down
7 changes: 2 additions & 5 deletions src/main/java/serverutils/lib/math/ChunkDimPos.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ public ChunkDimPos set(int x, int z, int dim) {
return this;
}

public ChunkDimPos set(long packedPos, int dim) {
this.posX = CoordinatePacker.unpackX(packedPos);
this.posZ = CoordinatePacker.unpackZ(packedPos);
this.dim = dim;
return this;
public ChunkDimPos set(long packed, int dim) {
return set(CoordinatePacker.unpackX(packed), CoordinatePacker.unpackZ(packed), dim);
}

public boolean equals(Object o) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/serverutils/lib/util/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,8 @@ public static String getBaseName(File file) {
return index == -1 ? name : name.substring(0, index);
}
}

public static String getRelativePath(File dir, File file) {
return dir.getName() + File.separator + file.getAbsolutePath().substring(dir.getAbsolutePath().length() + 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package serverutils.lib.util.compression;

import static serverutils.ServerUtilitiesConfig.backups;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.IOUtils;

public class CommonsCompressor implements ICompress {

private ArchiveOutputStream output;

@Override
public void createOutputStream(File file) throws IOException {
ZipArchiveOutputStream zaos = new ZipArchiveOutputStream(file);
if (backups.compression_level == 0) {
zaos.setMethod(ZipEntry.STORED);
} else {
zaos.setLevel(backups.compression_level);
}
output = zaos;
}

@Override
public void addFileToArchive(File file, String name) throws IOException {
ArchiveEntry entry = output.createArchiveEntry(file, name);
output.putArchiveEntry(entry);
try (FileInputStream fis = new FileInputStream(file)) {
IOUtils.copy(fis, output);
}
output.closeArchiveEntry();
}

@Override
public void close() throws Exception {
if (output != null) {
output.close();
}
}
}
11 changes: 11 additions & 0 deletions src/main/java/serverutils/lib/util/compression/ICompress.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package serverutils.lib.util.compression;

import java.io.File;
import java.io.IOException;

public interface ICompress extends AutoCloseable {

void createOutputStream(File file) throws IOException;

void addFileToArchive(File file, String name) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package serverutils.lib.util.compression;

import static serverutils.ServerUtilitiesConfig.backups;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;

public class LegacyCompressor implements ICompress {

private ZipOutputStream output;

@Override
public void createOutputStream(File file) throws IOException {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file));
if (backups.compression_level == 0) {
zos.setMethod(ZipOutputStream.STORED);
} else {
zos.setLevel(backups.compression_level);
}

output = zos;
}

@Override
public void addFileToArchive(File file, String name) throws IOException {
ZipEntry entry = new ZipEntry(name);
output.putNextEntry(entry);
try (FileInputStream fis = new FileInputStream(file)) {
IOUtils.copy(fis, output);
}
output.closeEntry();
}

@Override
public void close() throws Exception {
if (output != null) {
output.close();
}
}
}
30 changes: 28 additions & 2 deletions src/main/java/serverutils/task/backup/BackupTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

Expand All @@ -21,15 +23,23 @@
import serverutils.ServerUtilities;
import serverutils.ServerUtilitiesConfig;
import serverutils.ServerUtilitiesNotifications;
import serverutils.data.ClaimedChunks;
import serverutils.lib.data.Universe;
import serverutils.lib.math.ChunkDimPos;
import serverutils.lib.math.Ticks;
import serverutils.lib.util.CommonUtils;
import serverutils.lib.util.FileUtils;
import serverutils.lib.util.ServerUtils;
import serverutils.lib.util.compression.CommonsCompressor;
import serverutils.lib.util.compression.ICompress;
import serverutils.lib.util.compression.LegacyCompressor;
import serverutils.task.Task;

public class BackupTask extends Task {

public static final Pattern BACKUP_NAME_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{2}(.*)");
public static final File BACKUP_TEMP_FOLDER = new File("serverutilities/temp/");
private static final boolean useLegacy;
public static File backupsFolder;
public static ThreadBackup thread;
public static boolean hadPlayer = false;
Expand All @@ -43,6 +53,7 @@ public class BackupTask extends Task {
if (!backupsFolder.exists()) backupsFolder.mkdirs();
clearOldBackups();
ServerUtilities.LOGGER.info("Backups folder - {}", backupsFolder.getAbsolutePath());
useLegacy = !CommonUtils.getClassExists("org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream");
}

public BackupTask() {
Expand Down Expand Up @@ -96,11 +107,24 @@ public void execute(Universe universe) {

File worldDir = DimensionManager.getCurrentSaveRootDirectory();

Set<ChunkDimPos> backupChunks = new HashSet<>();
if (backups.only_backup_claimed_chunks && ClaimedChunks.isActive()) {
backupChunks.addAll(ClaimedChunks.instance.getAllClaimedPositions());
BACKUP_TEMP_FOLDER.mkdirs();
}

ICompress compressor;
if (useLegacy) {
compressor = new LegacyCompressor();
} else {
compressor = new CommonsCompressor();
}

if (backups.use_separate_thread) {
thread = new ThreadBackup(worldDir, customName);
thread = new ThreadBackup(compressor, worldDir, customName, backupChunks);
thread.start();
} else {
ThreadBackup.doBackup(worldDir, customName);
ThreadBackup.doBackup(compressor, worldDir, customName, backupChunks);
}
universe.scheduleTask(new BackupTask(true));
}
Expand Down Expand Up @@ -158,6 +182,8 @@ private void postBackup(Universe universe) {
}

clearOldBackups();
FileUtils.delete(BACKUP_TEMP_FOLDER);

thread = null;
try {
MinecraftServer server = ServerUtils.getServer();
Expand Down
Loading

0 comments on commit b82a106

Please sign in to comment.