mirror of
https://github.com/TotalFreedomMC/TF-EssentialsX.git
synced 2024-06-30 17:59:43 +00:00
Improve backup functionality (#3258)
Waits for an ongoing backup task to complete in onDisable (and yells at users for `/reload`ing), and adds a `backup.always-run` option to enable always running backups even when no users have logged in since the last backup. Fixes #3257 and closes #2646.
This commit is contained in:
parent
61d0ed3f01
commit
8b71437264
|
@ -7,6 +7,8 @@ import org.bukkit.command.CommandSender;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -20,11 +22,13 @@ public class Backup implements Runnable {
|
||||||
private transient boolean running = false;
|
private transient boolean running = false;
|
||||||
private transient int taskId = -1;
|
private transient int taskId = -1;
|
||||||
private transient boolean active = false;
|
private transient boolean active = false;
|
||||||
|
private final AtomicBoolean pendingShutdown = new AtomicBoolean(false);
|
||||||
|
private transient CompletableFuture<Object> taskLock = null;
|
||||||
|
|
||||||
public Backup(final IEssentials ess) {
|
public Backup(final IEssentials ess) {
|
||||||
this.ess = ess;
|
this.ess = ess;
|
||||||
server = ess.getServer();
|
server = ess.getServer();
|
||||||
if (!ess.getOnlinePlayers().isEmpty()) {
|
if (!ess.getOnlinePlayers().isEmpty() || ess.getSettings().isAlwaysRunBackup()) {
|
||||||
ess.runTaskAsynchronously(this::startTask);
|
ess.runTaskAsynchronously(this::startTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,12 +56,21 @@ public class Backup implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Object> getTaskLock() {
|
||||||
|
return taskLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPendingShutdown(boolean shutdown) {
|
||||||
|
pendingShutdown.set(shutdown);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (active) {
|
if (active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
active = true;
|
active = true;
|
||||||
|
taskLock = new CompletableFuture<>();
|
||||||
final String command = ess.getSettings().getBackupCommand();
|
final String command = ess.getSettings().getBackupCommand();
|
||||||
if (command == null || "".equals(command)) {
|
if (command == null || "".equals(command)) {
|
||||||
return;
|
return;
|
||||||
|
@ -66,6 +79,7 @@ public class Backup implements Runnable {
|
||||||
final CommandSender cs = server.getConsoleSender();
|
final CommandSender cs = server.getConsoleSender();
|
||||||
server.dispatchCommand(cs, "save-all");
|
server.dispatchCommand(cs, "save-all");
|
||||||
active = false;
|
active = false;
|
||||||
|
taskLock.complete(new Object());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOGGER.log(Level.INFO, tl("backupStarted"));
|
LOGGER.log(Level.INFO, tl("backupStarted"));
|
||||||
|
@ -102,14 +116,17 @@ public class Backup implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
server.dispatchCommand(cs, "save-on");
|
server.dispatchCommand(cs, "save-on");
|
||||||
if (ess.getOnlinePlayers().isEmpty()) {
|
if (!ess.getSettings().isAlwaysRunBackup() && ess.getOnlinePlayers().isEmpty()) {
|
||||||
stopTask();
|
stopTask();
|
||||||
}
|
}
|
||||||
active = false;
|
active = false;
|
||||||
|
taskLock.complete(new Object());
|
||||||
LOGGER.log(Level.INFO, tl("backupFinished"));
|
LOGGER.log(Level.INFO, tl("backupFinished"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ess.scheduleSyncDelayedTask(new BackupEnableSaveTask());
|
if (!pendingShutdown.get()) {
|
||||||
|
ess.scheduleSyncDelayedTask(new BackupEnableSaveTask());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,6 +314,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||||
handleCrash(ex);
|
handleCrash(ex);
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
getBackup().setPendingShutdown(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -363,12 +364,17 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
boolean stopping = ServerState.isStopping();
|
||||||
|
if (!stopping) {
|
||||||
|
LOGGER.log(Level.SEVERE, tl("serverReloading"));
|
||||||
|
}
|
||||||
|
getBackup().setPendingShutdown(true);
|
||||||
for (User user : getOnlineUsers()) {
|
for (User user : getOnlineUsers()) {
|
||||||
if (user.isVanished()) {
|
if (user.isVanished()) {
|
||||||
user.setVanished(false);
|
user.setVanished(false);
|
||||||
user.sendMessage(tl("unvanishedReload"));
|
user.sendMessage(tl("unvanishedReload"));
|
||||||
}
|
}
|
||||||
if (ServerState.isStopping()) {
|
if (stopping) {
|
||||||
user.setLastLocation();
|
user.setLastLocation();
|
||||||
if (!user.isHidden()) {
|
if (!user.isHidden()) {
|
||||||
user.setLastLogout(System.currentTimeMillis());
|
user.setLastLogout(System.currentTimeMillis());
|
||||||
|
@ -379,6 +385,10 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleanupOpenInventories();
|
cleanupOpenInventories();
|
||||||
|
if (getBackup().getTaskLock() != null && !getBackup().getTaskLock().isDone()) {
|
||||||
|
LOGGER.log(Level.SEVERE, tl("backupInProgress"));
|
||||||
|
getBackup().getTaskLock().join();
|
||||||
|
}
|
||||||
if (i18n != null) {
|
if (i18n != null) {
|
||||||
i18n.onDisable();
|
i18n.onDisable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ public interface ISettings extends IConf {
|
||||||
|
|
||||||
long getBackupInterval();
|
long getBackupInterval();
|
||||||
|
|
||||||
|
boolean isAlwaysRunBackup();
|
||||||
|
|
||||||
String getChatFormat(String group);
|
String getChatFormat(String group);
|
||||||
|
|
||||||
int getChatRadius();
|
int getChatRadius();
|
||||||
|
|
|
@ -425,6 +425,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||||
return config.getString("backup.command", null);
|
return config.getString("backup.command", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAlwaysRunBackup() {
|
||||||
|
return config.getBoolean("backup.always-run", false);
|
||||||
|
}
|
||||||
|
|
||||||
private final Map<String, String> chatFormats = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, String> chatFormats = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -371,6 +371,8 @@ unprotected-sign-names:
|
||||||
backup:
|
backup:
|
||||||
# Interval in minutes.
|
# Interval in minutes.
|
||||||
interval: 30
|
interval: 30
|
||||||
|
# If true, the backup task will run even if there are no players online.
|
||||||
|
always-run: false
|
||||||
# Unless you add a valid backup command or script here, this feature will be useless.
|
# Unless you add a valid backup command or script here, this feature will be useless.
|
||||||
# Use 'save-all' to simply force regular world saving without backup.
|
# Use 'save-all' to simply force regular world saving without backup.
|
||||||
#command: 'rdiff-backup World1 backups/World1'
|
#command: 'rdiff-backup World1 backups/World1'
|
||||||
|
|
|
@ -27,6 +27,7 @@ backOther=\u00a76Returned\u00a7c {0}\u00a76 to previous location.
|
||||||
backupDisabled=\u00a74An external backup script has not been configured.
|
backupDisabled=\u00a74An external backup script has not been configured.
|
||||||
backupFinished=\u00a76Backup finished.
|
backupFinished=\u00a76Backup finished.
|
||||||
backupStarted=\u00a76Backup started.
|
backupStarted=\u00a76Backup started.
|
||||||
|
backupInProgress=\u00a76An external backup script is currently in progress! Halting plugin disable until finished.
|
||||||
backUsageMsg=\u00a76Returning to previous location.
|
backUsageMsg=\u00a76Returning to previous location.
|
||||||
balance=\u00a7aBalance\:\u00a7c {0}
|
balance=\u00a7aBalance\:\u00a7c {0}
|
||||||
balanceOther=\u00a7aBalance of {0}\u00a7a\:\u00a7c {1}
|
balanceOther=\u00a7aBalance of {0}\u00a7a\:\u00a7c {1}
|
||||||
|
@ -484,6 +485,7 @@ seenOnline=\u00a76Player\u00a7c {0} \u00a76has been \u00a7aonline\u00a76 since \
|
||||||
sellBulkPermission=\u00a76You do not have permission to bulk sell.
|
sellBulkPermission=\u00a76You do not have permission to bulk sell.
|
||||||
sellHandPermission=\u00a76You do not have permission to hand sell.
|
sellHandPermission=\u00a76You do not have permission to hand sell.
|
||||||
serverFull=Server is full\!
|
serverFull=Server is full\!
|
||||||
|
serverReloading=There's a good chance you're reloading your server right now. If that's the case, why do you hate yourself? Expect no support from the EssentialsX team when using /reload.
|
||||||
serverTotal=\u00a76Server Total\:\u00a7c {0}
|
serverTotal=\u00a76Server Total\:\u00a7c {0}
|
||||||
serverUnsupported=You are running an unsupported server version!
|
serverUnsupported=You are running an unsupported server version!
|
||||||
setBal=\u00a7aYour balance was set to {0}.
|
setBal=\u00a7aYour balance was set to {0}.
|
||||||
|
|
Loading…
Reference in a new issue