WorldCrashRecoveryHandler class
Пакет: com.hypixel.hytale.server.core.universe
Файл: com/hypixel/hytale/server/core/universe/WorldCrashRecoveryHandler.java
Поля (20)
| Модификаторы | Тип | Имя |
|---|---|---|
final |
HytaleLogger |
LOGGER |
|
private int |
attempts |
|
private long |
lastCrashNanos |
|
private boolean |
loading |
|
WorldCrashRecovery |
var1 |
|
World |
var2 |
|
HytaleServerConfig |
var2 |
|
WorldCrashRecoveryHandler.RecoveryState |
var2 |
|
String |
var3 |
|
String |
var3 |
|
WorldCrashRecoveryHandler.ResolvedPolicy |
var4 |
|
boolean |
var4 |
|
WorldCrashRecoveryHandler.RecoveryState |
var4 |
|
WorldCrashRecoveryHandler.RecoveryState |
var5 |
|
CrashRecoveryConfig |
var5 |
|
long |
var5 |
|
WorldCrashRecoveryHandler.RecoveryState |
var5 |
|
WorldCrashRecovery |
var6 |
|
|
var6 |
|
long |
var7 |
Методы (25)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
|
private |
RecoveryStateprivate RecoveryState() |
private |
record |
ResolvedPolicyrecord ResolvedPolicy(@Nonnull WorldCrashRecovery mode, int maxAttempts, int retryDelaySeconds, @Nonnull WorldCrashRecovery fallback) |
private |
void |
applyFallbackvoid applyFallback(@Nonnull String var1, @Nonnull WorldCrashRecovery var2) |
private |
void |
clearStatevoid clearState(@Nonnull String var1) |
|
|
if if(!var5.loading) |
|
|
if if(var2 == null) |
|
|
if if(var5 != null) |
|
|
if if(var6 == null) |
|
|
if if(var1 != null) |
|
|
if if(var3.pending != null) |
|
|
if if(var4 != null) |
|
|
if if(var5 != null) |
|
|
if if(var4 != null) |
|
|
if if(var2 != null) |
|
|
if if(var2.pending != null) |
|
|
if if(var2 == WorldCrashRecovery.Shutdown) |
|
private static WorldCrashRecoveryHandler.ResolvedPolicy |
ofprivate static WorldCrashRecoveryHandler.ResolvedPolicy of(@Nonnull CrashRecoveryConfig var0, @Nonnull WorldCrashRecovery var1) |
private |
void |
onReloadCompletevoid onReloadComplete(@Nonnull String var1, @Nonnull String var2, @Nonnull WorldCrashRecoveryHandler.ResolvedPolicy var3, @Nullable Throwable var4) |
|
void |
onRemoveWorldvoid onRemoveWorld(@Nonnull RemoveWorldEvent var1) |
private |
void |
reloadNowvoid reloadNow(@Nonnull String var1, @Nonnull String var2, @Nonnull WorldCrashRecoveryHandler.ResolvedPolicy var3) |
private |
void |
scheduleReloadvoid scheduleReload(@Nonnull String var1, @Nonnull String var2, @Nonnull WorldCrashRecoveryHandler.RecoveryState var3, @Nonnull WorldCrashRecoveryHandler.ResolvedPolicy var4) |
|
|
synchronized synchronized(var5) |
|
|
synchronized synchronized(var4) |
|
|
synchronized synchronized(var5) |
|
|
synchronized synchronized(var2) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.universe;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.server.core.Constants;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.HytaleServerConfig;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.ShutdownReason;
class="kw">import com.hypixel.hytale.server.core.config.CrashRecoveryConfig;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.WorldCrashRecovery;
class="kw">import com.hypixel.hytale.server.core.universe.world.events.RemoveWorldEvent;
class="kw">import java.time.Duration;
class="kw">import java.util.Locale;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.ScheduledFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">final class WorldCrashRecoveryHandler {
class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
class="kw">static class="kw">final long CRASH_WINDOW_NANOS = Duration.ofMinutes(5L).toNanos();
class="kw">private class="kw">final Universe universe;
class="kw">private class="kw">final ConcurrentHashMap<String, WorldCrashRecoveryHandler.RecoveryState> states = new ConcurrentHashMap<>();
WorldCrashRecoveryHandler(@Nonnull Universe var1) {
this.universe = var1;
}
void onRemoveWorld(@Nonnull RemoveWorldEvent var1) {
World var2 = var1.getWorld();
String var3 = var2.getName().toLowerCase(Locale.ROOT);
if (var1.getRemovalReason() != RemoveWorldEvent.RemovalReason.EXCEPTIONAL) {
this.clearState(var3);
} else {
WorldCrashRecoveryHandler.ResolvedPolicy var4 = this.resolve(var2);
if (var4 != null && var4.mode() != WorldCrashRecovery.None) {
if (var4.mode() == WorldCrashRecovery.Shutdown) {
LOGGER.at(Level.WARNING).log("World '%s' crashed, shutting down the server", var2.getName());
HytaleServer.get()
.shutdownServer(
ShutdownReason.CRASH.withMessage(Message.translation("server.general.disconnect.worldCrashedShutdown").param("world", var2.getName()))
);
} else if (var2.getWorldConfig().isDeleteOnRemove()) {
LOGGER.at(Level.INFO).log("Skipping reload of crashed world '%s' because it is set to delete on remove", var2.getName());
this.clearState(var3);
} else {
WorldCrashRecoveryHandler.RecoveryState var5 = this.states.computeIfAbsent(var3, var0 -> new WorldCrashRecoveryHandler.RecoveryState());
class="kw">synchronized (var5) {
if (this.states.get(var3) == var5) {
if (!var5.loading) {
this.scheduleReload(var2.getName(), var3, var5, var4);
}
}
}
}
}
}
}
@Nullable
class="kw">private WorldCrashRecoveryHandler.ResolvedPolicy resolve(@Nonnull World var1) {
HytaleServerConfig var2 = HytaleServer.get().getConfig();
if (var2 == null) {
class="kw">return null;
}
String var3 = var2.getDefaults().getWorld();
boolean var4 = var3 != null && var3.equalsIgnoreCase(var1.getName());
CrashRecoveryConfig var5 = var1.getWorldConfig().getCrashRecovery();
if (var5 != null) {
WorldCrashRecovery var6 = var5.getMode();
if (var6 == null) {
var6 = var4 ? defaultWorldMode(var2) : WorldCrashRecovery.Reload;
}
class="kw">return WorldCrashRecoveryHandler.ResolvedPolicy.of(var5, var6);
} else {
class="kw">return var4 ? WorldCrashRecoveryHandler.ResolvedPolicy.of(var2.getDefaults().getCrashRecovery(), defaultWorldMode(var2)) : null;
}
}
@Nonnull
class="kw">private class="kw">static WorldCrashRecovery defaultWorldMode(@Nonnull HytaleServerConfig var0) {
WorldCrashRecovery var1 = var0.getDefaults().getCrashRecovery().getMode();
if (var1 != null) {
class="kw">return var1;
} else {
class="kw">return Constants.SINGLEPLAYER ? WorldCrashRecovery.None : WorldCrashRecovery.Reload;
}
}
class="kw">private void scheduleReload(
@Nonnull String var1, @Nonnull String var2, @Nonnull WorldCrashRecoveryHandler.RecoveryState var3, @Nonnull WorldCrashRecoveryHandler.ResolvedPolicy var4
) {
if (var3.pending != null) {
var3.pending.cancel(false);
var3.pending = null;
}
long var5 = System.nanoTime();
long var7 = CRASH_WINDOW_NANOS + TimeUnit.SECONDS.toNanos(var4.retryDelaySeconds());
var3.attempts = var5 - var3.lastCrashNanos > var7 ? 1 : var3.attempts + 1;
var3.lastCrashNanos = var5;
if (var3.attempts > var4.maxAttempts()) {
LOGGER.at(Level.WARNING).log("Gave up recovering world '%s' after %d reload attempt(s)", var1, var4.maxAttempts());
this.states.remove(var2);
this.applyFallback(var1, var4.fallback());
} else {
LOGGER.at(Level.INFO)
.log("Reloading crashed world '%s' in %d second(s) (attempt %d of %d)", var1, var4.retryDelaySeconds(), var3.attempts, var4.maxAttempts());
var3.pending = HytaleServer.SCHEDULED_EXECUTOR.schedule(() -> this.reloadNow(var1, var2, var4), var4.retryDelaySeconds(), TimeUnit.SECONDS);
}
}
class="kw">private void reloadNow(@Nonnull String var1, @Nonnull String var2, @Nonnull WorldCrashRecoveryHandler.ResolvedPolicy var3) {
WorldCrashRecoveryHandler.RecoveryState var4 = this.states.get(var2);
if (var4 != null) {
class="kw">synchronized (var4) {
if (this.states.get(var2) == var4) {
var4.pending = null;
if (HytaleServer.get().isShuttingDown()) {
this.states.remove(var2);
} else if (this.universe.getWorld(var1) != null) {
LOGGER.at(Level.INFO).log("World '%s' is already loaded, crash recovery superseded", var1);
this.states.remove(var2);
} else {
var4.loading = true;
try {
this.universe.loadWorld(var1).whenComplete((var4x, var5) -> this.onReloadComplete(var1, var2, var3, var5));
} catch (Throwable var8) {
var4.loading = false;
((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(var8)).log("Failed to start reload of crashed world '%s'", var1);
this.scheduleReload(var1, var2, var4, var3);
}
}
}
}
}
}
class="kw">private void onReloadComplete(@Nonnull String var1, @Nonnull String var2, @Nonnull WorldCrashRecoveryHandler.ResolvedPolicy var3, @Nullable Throwable var4) {
WorldCrashRecoveryHandler.RecoveryState var5 = this.states.get(var2);
if (var5 != null) {
class="kw">synchronized (var5) {
if (this.states.get(var2) == var5) {
var5.loading = false;
if (HytaleServer.get().isShuttingDown()) {
this.states.remove(var2);
} else {
if (var4 != null) {
((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(var4)).log("Failed to reload crashed world '%s'", var1);
this.scheduleReload(var1, var2, var5, var3);
} else {
LOGGER.at(Level.INFO).log("Reloaded crashed world '%s'", var1);
}
}
}
}
}
}
class="kw">private void clearState(@Nonnull String var1) {
WorldCrashRecoveryHandler.RecoveryState var2 = this.states.remove(var1);
if (var2 != null) {
class="kw">synchronized (var2) {
if (var2.pending != null) {
var2.pending.cancel(false);
var2.pending = null;
}
}
}
}
class="kw">private void applyFallback(@Nonnull String var1, @Nonnull WorldCrashRecovery var2) {
if (var2 == WorldCrashRecovery.Shutdown) {
LOGGER.at(Level.WARNING).log("World '%s' did not recover, shutting down the server", var1);
HytaleServer.get()
.shutdownServer(ShutdownReason.CRASH.withMessage(Message.translation("server.general.disconnect.worldNotRecovered").param("world", var1)));
} else {
LOGGER.at(Level.WARNING).log("World '%s' did not recover, the server is left without it", var1);
}
}
class="kw">private class="kw">static class="kw">final class RecoveryState {
class="kw">private int attempts;
class="kw">private long lastCrashNanos;
class="kw">private boolean loading;
@Nullable
class="kw">private ScheduledFuture<?> pending;
class="kw">private RecoveryState() {
}
}
class="kw">private record ResolvedPolicy(@Nonnull WorldCrashRecovery mode, int maxAttempts, int retryDelaySeconds, @Nonnull WorldCrashRecovery fallback) {
class="kw">private ResolvedPolicy {
}
@Nonnull
class="kw">private class="kw">static WorldCrashRecoveryHandler.ResolvedPolicy of(@Nonnull CrashRecoveryConfig var0, @Nonnull WorldCrashRecovery var1) {
class="kw">return new WorldCrashRecoveryHandler.ResolvedPolicy(var1, var0.getMaxAttempts(), var0.getRetryDelaySeconds(), var0.getFallback());
}
}
}