mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-01 15:36:45 +00:00
Merge pull request #1198 from VolmitSoftware/feat/versioned_mantle
This commit is contained in:
commit
2436ebb857
@ -113,6 +113,11 @@ shadowJar {
|
|||||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||||
relocate 'org.bstats', 'com.volmit.util.metrics'
|
relocate 'org.bstats', 'com.volmit.util.metrics'
|
||||||
archiveFileName.set("Iris-${project.version}.jar")
|
archiveFileName.set("Iris-${project.version}.jar")
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
exclude(dependency("org.ow2.asm:asm:"))
|
||||||
|
exclude(dependency("org.jetbrains:"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -23,6 +23,7 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.json.JSONException;
|
import com.volmit.iris.util.json.JSONException;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import com.volmit.iris.util.misc.getHardware;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -160,6 +161,14 @@ public class IrisSettings {
|
|||||||
public int resourceLoaderCacheSize = 1_024;
|
public int resourceLoaderCacheSize = 1_024;
|
||||||
public int objectLoaderCacheSize = 4_096;
|
public int objectLoaderCacheSize = 4_096;
|
||||||
public int scriptLoaderCacheSize = 512;
|
public int scriptLoaderCacheSize = 512;
|
||||||
|
public int tectonicPlateSize = -1;
|
||||||
|
|
||||||
|
public int getTectonicPlateSize() {
|
||||||
|
if (tectonicPlateSize > 0)
|
||||||
|
return tectonicPlateSize;
|
||||||
|
|
||||||
|
return (int) (getHardware.getProcessMemory() / 200L);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -191,6 +200,7 @@ public class IrisSettings {
|
|||||||
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||||
public boolean commandSounds = true;
|
public boolean commandSounds = true;
|
||||||
public boolean debug = false;
|
public boolean debug = false;
|
||||||
|
public boolean dumpMantleOnError = false;
|
||||||
public boolean disableNMS = false;
|
public boolean disableNMS = false;
|
||||||
public boolean pluginMetrics = true;
|
public boolean pluginMetrics = true;
|
||||||
public boolean splashLogoStartup = true;
|
public boolean splashLogoStartup = true;
|
||||||
|
@ -20,7 +20,6 @@ package com.volmit.iris.core.commands;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.ServerConfigurator;
|
import com.volmit.iris.core.ServerConfigurator;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
|
||||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||||
@ -68,53 +67,8 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
|
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
|
||||||
public void EngineStatus() {
|
public void EngineStatus() {
|
||||||
List<World> IrisWorlds = new ArrayList<>();
|
Iris.service(IrisEngineSVC.class)
|
||||||
int TotalLoadedChunks = 0;
|
.engineStatus(sender());
|
||||||
int TotalQueuedTectonicPlates = 0;
|
|
||||||
int TotalNotQueuedTectonicPlates = 0;
|
|
||||||
int TotalTectonicPlates = 0;
|
|
||||||
|
|
||||||
long lowestUnloadDuration = 0;
|
|
||||||
long highestUnloadDuration = 0;
|
|
||||||
|
|
||||||
for (World world : Bukkit.getWorlds()) {
|
|
||||||
try {
|
|
||||||
if (IrisToolbelt.access(world).getEngine() != null) {
|
|
||||||
IrisWorlds.add(world);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// no
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (World world : IrisWorlds) {
|
|
||||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
|
||||||
TotalQueuedTectonicPlates += (int) engine.getMantle().getToUnload();
|
|
||||||
TotalNotQueuedTectonicPlates += (int) engine.getMantle().getNotQueuedLoadedRegions();
|
|
||||||
TotalTectonicPlates += engine.getMantle().getLoadedRegionCount();
|
|
||||||
if (highestUnloadDuration <= (long) engine.getMantle().getTectonicDuration()) {
|
|
||||||
highestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
|
|
||||||
}
|
|
||||||
if (lowestUnloadDuration >= (long) engine.getMantle().getTectonicDuration()) {
|
|
||||||
lowestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
|
|
||||||
}
|
|
||||||
for (Chunk chunk : world.getLoadedChunks()) {
|
|
||||||
if (chunk.isLoaded()) {
|
|
||||||
TotalLoadedChunks++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iris.info("-------------------------");
|
|
||||||
Iris.info(C.DARK_PURPLE + "Engine Status");
|
|
||||||
Iris.info(C.DARK_PURPLE + "Total Loaded Chunks: " + C.LIGHT_PURPLE + TotalLoadedChunks);
|
|
||||||
Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + IrisEngineSVC.getTectonicLimit());
|
|
||||||
Iris.info(C.DARK_PURPLE + "Tectonic Total Plates: " + C.LIGHT_PURPLE + TotalTectonicPlates);
|
|
||||||
Iris.info(C.DARK_PURPLE + "Tectonic Active Plates: " + C.LIGHT_PURPLE + TotalNotQueuedTectonicPlates);
|
|
||||||
Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + TotalQueuedTectonicPlates);
|
|
||||||
Iris.info(C.DARK_PURPLE + "Lowest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(lowestUnloadDuration));
|
|
||||||
Iris.info(C.DARK_PURPLE + "Highest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(highestUnloadDuration));
|
|
||||||
Iris.info(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
|
|
||||||
Iris.info("-------------------------");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Test")
|
@Decree(description = "Test")
|
||||||
@ -166,7 +120,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
|
|
||||||
File tectonicplates = new File(folder, "mantle");
|
File tectonicplates = new File(folder, "mantle");
|
||||||
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
|
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
|
||||||
TectonicPlate.read(maxHeight, i);
|
TectonicPlate.read(maxHeight, i, true);
|
||||||
c++;
|
c++;
|
||||||
Iris.info("Loaded count: " + c );
|
Iris.info("Loaded count: " + c );
|
||||||
|
|
||||||
@ -272,7 +226,8 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
@Param(description = "base IrisWorld") World world,
|
@Param(description = "base IrisWorld") World world,
|
||||||
@Param(description = "raw TectonicPlate File") String path,
|
@Param(description = "raw TectonicPlate File") String path,
|
||||||
@Param(description = "Algorithm to Test") String algorithm,
|
@Param(description = "Algorithm to Test") String algorithm,
|
||||||
@Param(description = "Amount of Tests") int amount) {
|
@Param(description = "Amount of Tests") int amount,
|
||||||
|
@Param(description = "Is versioned", defaultValue = "false") boolean versioned) {
|
||||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||||
return;
|
return;
|
||||||
@ -289,7 +244,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
service.submit(() -> {
|
service.submit(() -> {
|
||||||
try {
|
try {
|
||||||
CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
|
CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
|
||||||
TectonicPlate plate = new TectonicPlate(height, raw);
|
TectonicPlate plate = new TectonicPlate(height, raw, versioned);
|
||||||
raw.close();
|
raw.close();
|
||||||
|
|
||||||
double d1 = 0;
|
double d1 = 0;
|
||||||
@ -308,7 +263,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
size = tmp.length();
|
size = tmp.length();
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
CountingDataInputStream din = createInput(tmp, algorithm);
|
CountingDataInputStream din = createInput(tmp, algorithm);
|
||||||
new TectonicPlate(height, din);
|
new TectonicPlate(height, din, true);
|
||||||
din.close();
|
din.close();
|
||||||
d2 += System.currentTimeMillis() - start;
|
d2 += System.currentTimeMillis() - start;
|
||||||
tmp.delete();
|
tmp.delete();
|
||||||
|
@ -1,317 +1,245 @@
|
|||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import com.volmit.iris.util.collection.KList;
|
|
||||||
import com.volmit.iris.util.collection.KMap;
|
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
|
||||||
import com.volmit.iris.util.misc.getHardware;
|
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.server.PluginDisableEvent;
|
|
||||||
import org.bukkit.event.server.ServerLoadEvent;
|
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
import org.checkerframework.checker.units.qual.A;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class IrisEngineSVC implements IrisService {
|
public class IrisEngineSVC implements IrisService {
|
||||||
public static IrisEngineSVC instance;
|
private final AtomicInteger tectonicLimit = new AtomicInteger(30);
|
||||||
public boolean isServerShuttingDown = false;
|
private final AtomicInteger tectonicPlates = new AtomicInteger();
|
||||||
public boolean isServerLoaded = false;
|
private final AtomicInteger queuedTectonicPlates = new AtomicInteger();
|
||||||
private static final AtomicInteger tectonicLimit = new AtomicInteger(30);
|
private final AtomicDouble maxIdleDuration = new AtomicDouble();
|
||||||
private ReentrantLock lastUseLock;
|
private final AtomicDouble minIdleDuration = new AtomicDouble();
|
||||||
private KMap<World, Long> lastUse;
|
private final AtomicLong loadedChunks = new AtomicLong();
|
||||||
private List<World> IrisWorlds;
|
private final List<Pair<World, PlatformChunkGenerator>> worlds = new CopyOnWriteArrayList<>();
|
||||||
private Looper cacheTicker;
|
|
||||||
private Looper trimTicker;
|
private Looper trimTicker;
|
||||||
private Looper unloadTicker;
|
private Looper unloadTicker;
|
||||||
private Looper updateTicker;
|
private Looper updateTicker;
|
||||||
private PrecisionStopwatch trimAlive;
|
|
||||||
private PrecisionStopwatch unloadAlive;
|
|
||||||
public PrecisionStopwatch trimActiveAlive;
|
|
||||||
public PrecisionStopwatch unloadActiveAlive;
|
|
||||||
private AtomicInteger TotalTectonicPlates;
|
|
||||||
private AtomicInteger TotalQueuedTectonicPlates;
|
|
||||||
private AtomicInteger TotalNotQueuedTectonicPlates;
|
|
||||||
private AtomicBoolean IsUnloadAlive;
|
|
||||||
private AtomicBoolean IsTrimAlive;
|
|
||||||
ChronoLatch cl;
|
|
||||||
|
|
||||||
public List<World> corruptedIrisWorlds = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
this.cl = new ChronoLatch(5000);
|
tectonicLimit.set(IrisSettings.get().getPerformance().getTectonicPlateSize());
|
||||||
lastUse = new KMap<>();
|
for (World world : Bukkit.getWorlds()) {
|
||||||
lastUseLock = new ReentrantLock();
|
var access = IrisToolbelt.access(world);
|
||||||
IrisWorlds = new ArrayList<>();
|
if (access == null) return;
|
||||||
IsUnloadAlive = new AtomicBoolean(true);
|
worlds.add(new Pair<>(world, access));
|
||||||
IsTrimAlive = new AtomicBoolean(true);
|
|
||||||
trimActiveAlive = new PrecisionStopwatch();
|
|
||||||
unloadActiveAlive = new PrecisionStopwatch();
|
|
||||||
trimAlive = new PrecisionStopwatch();
|
|
||||||
unloadAlive = new PrecisionStopwatch();
|
|
||||||
TotalTectonicPlates = new AtomicInteger();
|
|
||||||
TotalQueuedTectonicPlates = new AtomicInteger();
|
|
||||||
TotalNotQueuedTectonicPlates = new AtomicInteger();
|
|
||||||
tectonicLimit.set(2);
|
|
||||||
long t = getHardware.getProcessMemory();
|
|
||||||
while (t > 200) {
|
|
||||||
tectonicLimit.getAndAdd(1);
|
|
||||||
t = t - 200;
|
|
||||||
}
|
}
|
||||||
this.setup();
|
|
||||||
this.TrimLogic();
|
|
||||||
this.UnloadLogic();
|
|
||||||
|
|
||||||
trimAlive.begin();
|
|
||||||
unloadAlive.begin();
|
|
||||||
trimActiveAlive.begin();
|
|
||||||
unloadActiveAlive.begin();
|
|
||||||
|
|
||||||
updateTicker.start();
|
|
||||||
cacheTicker.start();
|
|
||||||
//trimTicker.start();
|
|
||||||
//unloadTicker.start();
|
|
||||||
instance = this;
|
|
||||||
|
|
||||||
|
trimLogic();
|
||||||
|
unloadLogic();
|
||||||
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void engineStatus() {
|
@Override
|
||||||
boolean trimAlive = trimTicker.isAlive();
|
public void onDisable() {
|
||||||
boolean unloadAlive = unloadTicker.isAlive();
|
updateTicker.interrupt();
|
||||||
Iris.info("Status:");
|
trimTicker.interrupt();
|
||||||
Iris.info("- Trim: " + trimAlive);
|
unloadTicker.interrupt();
|
||||||
Iris.info("- Unload: " + unloadAlive);
|
worlds.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getTectonicLimit() {
|
public void engineStatus(VolmitSender sender) {
|
||||||
return tectonicLimit.get();
|
sender.sendMessage(C.DARK_PURPLE + "-------------------------");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "Status:");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Trim: " + C.LIGHT_PURPLE + trimTicker.isAlive());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Unload: " + C.LIGHT_PURPLE + unloadTicker.isAlive());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Update: " + C.LIGHT_PURPLE + updateTicker.isAlive());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "Tectonic Plates:");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Limit: " + C.LIGHT_PURPLE + tectonicLimit.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Total: " + C.LIGHT_PURPLE + tectonicPlates.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Queued: " + C.LIGHT_PURPLE + queuedTectonicPlates.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Max Idle Duration: " + C.LIGHT_PURPLE + Form.duration(maxIdleDuration.get(), 2));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Min Idle Duration: " + C.LIGHT_PURPLE + Form.duration(minIdleDuration.get(), 2));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "Other:");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Iris Worlds: " + C.LIGHT_PURPLE + worlds.size());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Loaded Chunks: " + C.LIGHT_PURPLE + loadedChunks.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "-------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldUnload(WorldUnloadEvent event) {
|
public void onWorldUnload(WorldUnloadEvent event) {
|
||||||
updateWorlds();
|
worlds.removeIf(p -> p.getA() == event.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldLoad(WorldLoadEvent event) {
|
public void onWorldLoad(WorldLoadEvent event) {
|
||||||
updateWorlds();
|
var world = event.getWorld();
|
||||||
|
var access = IrisToolbelt.access(world);
|
||||||
|
if (access == null) return;
|
||||||
|
worlds.add(new Pair<>(world, access));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
private synchronized void setup() {
|
||||||
public void onServerBoot(ServerLoadEvent event) {
|
if (updateTicker != null && updateTicker.isAlive())
|
||||||
isServerLoaded = true;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPluginDisable(PluginDisableEvent event) {
|
|
||||||
if (event.getPlugin().equals(Iris.instance)) {
|
|
||||||
isServerShuttingDown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateWorlds() {
|
|
||||||
for (World world : Bukkit.getWorlds()) {
|
|
||||||
try {
|
|
||||||
if (IrisToolbelt.access(world).getEngine() != null) {
|
|
||||||
IrisWorlds.add(world);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// no
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setup() {
|
|
||||||
cacheTicker = new Looper() {
|
|
||||||
@Override
|
|
||||||
protected long loop() {
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
lastUseLock.lock();
|
|
||||||
try {
|
|
||||||
for (World key : new ArrayList<>(lastUse.keySet())) {
|
|
||||||
Long last = lastUse.get(key);
|
|
||||||
if (last == null)
|
|
||||||
continue;
|
|
||||||
if (now - last > 60000) {
|
|
||||||
lastUse.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
lastUseLock.unlock();
|
|
||||||
}
|
|
||||||
return 1000;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateTicker = new Looper() {
|
updateTicker = new Looper() {
|
||||||
@Override
|
@Override
|
||||||
protected long loop() {
|
protected long loop() {
|
||||||
try {
|
try {
|
||||||
TotalQueuedTectonicPlates.set(0);
|
queuedTectonicPlates.set(0);
|
||||||
TotalNotQueuedTectonicPlates.set(0);
|
tectonicPlates.set(0);
|
||||||
TotalTectonicPlates.set(0);
|
loadedChunks.set(0);
|
||||||
for (World world : IrisWorlds) {
|
|
||||||
Engine engine = Objects.requireNonNull(IrisToolbelt.access(world)).getEngine();
|
|
||||||
TotalQueuedTectonicPlates.addAndGet((int) engine.getMantle().getToUnload());
|
|
||||||
TotalNotQueuedTectonicPlates.addAndGet((int) engine.getMantle().getNotQueuedLoadedRegions());
|
|
||||||
TotalTectonicPlates.addAndGet(engine.getMantle().getLoadedRegionCount());
|
|
||||||
}
|
|
||||||
if (!isServerShuttingDown && isServerLoaded) {
|
|
||||||
if (!trimTicker.isAlive()) {
|
|
||||||
Iris.info(C.RED + "TrimTicker found dead! Booting it up!");
|
|
||||||
try {
|
|
||||||
TrimLogic();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Iris.error("What happened?");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!unloadTicker.isAlive()) {
|
double maxDuration = Long.MIN_VALUE;
|
||||||
Iris.info(C.RED + "UnloadTicker found dead! Booting it up!");
|
double minDuration = Long.MAX_VALUE;
|
||||||
try {
|
for (var pair : worlds) {
|
||||||
UnloadLogic();
|
var engine = pair.getB().getEngine();
|
||||||
} catch (Exception e) {
|
if (engine == null) continue;
|
||||||
Iris.error("What happened?");
|
|
||||||
e.printStackTrace();
|
queuedTectonicPlates.addAndGet((int) engine.getMantle().getUnloadRegionCount());
|
||||||
}
|
tectonicPlates.addAndGet(engine.getMantle().getLoadedRegionCount());
|
||||||
|
loadedChunks.addAndGet(pair.getA().getLoadedChunks().length);
|
||||||
|
|
||||||
|
double duration = engine.getMantle().getAdjustedIdleDuration();
|
||||||
|
if (duration > maxDuration) maxDuration = duration;
|
||||||
|
if (duration < minDuration) minDuration = duration;
|
||||||
|
}
|
||||||
|
maxIdleDuration.set(maxDuration);
|
||||||
|
minIdleDuration.set(minDuration);
|
||||||
|
|
||||||
|
if (!trimTicker.isAlive()) {
|
||||||
|
Iris.error("TrimTicker found dead! Booting it up!");
|
||||||
|
try {
|
||||||
|
trimLogic();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.error("What happened?");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
if (!unloadTicker.isAlive()) {
|
||||||
return -1;
|
Iris.error("UnloadTicker found dead! Booting it up!");
|
||||||
|
try {
|
||||||
|
unloadLogic();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.error("What happened?");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
updateTicker.start();
|
||||||
}
|
}
|
||||||
public void TrimLogic() {
|
|
||||||
if (trimTicker == null || !trimTicker.isAlive()) {
|
|
||||||
trimTicker = new Looper() {
|
|
||||||
private final Supplier<Engine> supplier = createSupplier();
|
|
||||||
|
|
||||||
@Override
|
private synchronized void trimLogic() {
|
||||||
protected long loop() {
|
if (trimTicker != null && trimTicker.isAlive())
|
||||||
long start = System.currentTimeMillis();
|
return;
|
||||||
trimAlive.reset();
|
|
||||||
try {
|
trimTicker = new Looper() {
|
||||||
Engine engine = supplier.get();
|
private final Supplier<Engine> supplier = createSupplier();
|
||||||
if (engine != null) {
|
|
||||||
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
|
@Override
|
||||||
}
|
protected long loop() {
|
||||||
} catch (Throwable e) {
|
long start = System.currentTimeMillis();
|
||||||
Iris.reportError(e);
|
try {
|
||||||
Iris.info(C.RED + "EngineSVC: Failed to trim.");
|
Engine engine = supplier.get();
|
||||||
e.printStackTrace();
|
if (engine != null) {
|
||||||
return -1;
|
engine.getMantle().trim(tectonicLimit.get() / worlds.size());
|
||||||
}
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
int size = lastUse.size();
|
Iris.reportError(e);
|
||||||
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
|
Iris.error("EngineSVC: Failed to trim.");
|
||||||
if (time <= 0)
|
e.printStackTrace();
|
||||||
return 0;
|
return -1;
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
trimTicker.start();
|
int size = worlds.size();
|
||||||
}
|
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
|
||||||
|
if (time <= 0)
|
||||||
|
return 0;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
trimTicker.start();
|
||||||
}
|
}
|
||||||
public void UnloadLogic() {
|
|
||||||
if (unloadTicker == null || !unloadTicker.isAlive()) {
|
|
||||||
unloadTicker = new Looper() {
|
|
||||||
private final Supplier<Engine> supplier = createSupplier();
|
|
||||||
|
|
||||||
@Override
|
private synchronized void unloadLogic() {
|
||||||
protected long loop() {
|
if (unloadTicker != null && unloadTicker.isAlive())
|
||||||
long start = System.currentTimeMillis();
|
return;
|
||||||
unloadAlive.reset();
|
|
||||||
try {
|
unloadTicker = new Looper() {
|
||||||
Engine engine = supplier.get();
|
private final Supplier<Engine> supplier = createSupplier();
|
||||||
if (engine != null) {
|
|
||||||
long unloadStart = System.currentTimeMillis();
|
@Override
|
||||||
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / lastUse.size());
|
protected long loop() {
|
||||||
if (count > 0) {
|
long start = System.currentTimeMillis();
|
||||||
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
|
try {
|
||||||
}
|
Engine engine = supplier.get();
|
||||||
|
if (engine != null) {
|
||||||
|
long unloadStart = System.currentTimeMillis();
|
||||||
|
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / worlds.size());
|
||||||
|
if (count > 0) {
|
||||||
|
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
Iris.info(C.RED + "EngineSVC: Failed to unload.");
|
|
||||||
e.printStackTrace();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
int size = lastUse.size();
|
Iris.reportError(e);
|
||||||
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
|
Iris.error("EngineSVC: Failed to unload.");
|
||||||
if (time <= 0)
|
e.printStackTrace();
|
||||||
return 0;
|
return -1;
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
unloadTicker.start();
|
int size = worlds.size();
|
||||||
}
|
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
|
||||||
|
if (time <= 0)
|
||||||
|
return 0;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unloadTicker.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Supplier<Engine> createSupplier() {
|
private Supplier<Engine> createSupplier() {
|
||||||
AtomicInteger i = new AtomicInteger();
|
AtomicInteger i = new AtomicInteger();
|
||||||
return () -> {
|
return () -> {
|
||||||
List<World> worlds = Bukkit.getWorlds();
|
|
||||||
if (i.get() >= worlds.size()) {
|
if (i.get() >= worlds.size()) {
|
||||||
i.set(0);
|
i.set(0);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
for (int j = 0; j < worlds.size(); j++) {
|
for (int j = 0; j < worlds.size(); j++) {
|
||||||
World world = worlds.get(i.getAndIncrement());
|
var pair = worlds.get(i.getAndIncrement());
|
||||||
PlatformChunkGenerator generator = IrisToolbelt.access(world);
|
|
||||||
if (i.get() >= worlds.size()) {
|
if (i.get() >= worlds.size()) {
|
||||||
i.set(0);
|
i.set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generator != null) {
|
var engine = pair.getB().getEngine();
|
||||||
Engine engine = generator.getEngine();
|
if (engine != null && !engine.isClosed() && engine.getMantle().getMantle().shouldReduce(engine)) {
|
||||||
boolean closed = engine.getMantle().getData().isClosed();
|
return engine;
|
||||||
if (engine != null && !engine.isStudio() && !closed) {
|
|
||||||
lastUseLock.lock();
|
|
||||||
lastUse.put(world, System.currentTimeMillis());
|
|
||||||
lastUseLock.unlock();
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.info(C.RED + "EngineSVC: Failed to create supplier.");
|
Iris.error("EngineSVC: Failed to create supplier.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisable() {
|
|
||||||
cacheTicker.interrupt();
|
|
||||||
trimTicker.interrupt();
|
|
||||||
unloadTicker.interrupt();
|
|
||||||
lastUse.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -299,13 +299,11 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default long getToUnload(){
|
default long getUnloadRegionCount() {
|
||||||
return getMantle().getToUnload().size();
|
return getMantle().getUnloadRegionCount();
|
||||||
}
|
}
|
||||||
default long getNotQueuedLoadedRegions(){
|
|
||||||
return getMantle().getLoadedRegions().size() - getMantle().getToUnload().size();
|
default double getAdjustedIdleDuration() {
|
||||||
}
|
return getMantle().getAdjustedIdleDuration();
|
||||||
default double getTectonicDuration(){
|
|
||||||
return getMantle().getAdjustedIdleDuration().get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -86,12 +86,12 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
|||||||
private final boolean studio;
|
private final boolean studio;
|
||||||
private final AtomicInteger a = new AtomicInteger(0);
|
private final AtomicInteger a = new AtomicInteger(0);
|
||||||
private final CompletableFuture<Integer> spawnChunks = new CompletableFuture<>();
|
private final CompletableFuture<Integer> spawnChunks = new CompletableFuture<>();
|
||||||
private Engine engine;
|
private volatile Engine engine;
|
||||||
private Looper hotloader;
|
private volatile Looper hotloader;
|
||||||
private StudioMode lastMode;
|
private volatile StudioMode lastMode;
|
||||||
private DummyBiomeProvider dummyBiomeProvider;
|
private volatile DummyBiomeProvider dummyBiomeProvider;
|
||||||
@Setter
|
@Setter
|
||||||
private StudioGenerator studioGenerator;
|
private volatile StudioGenerator studioGenerator;
|
||||||
|
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
|
|
||||||
@ -110,20 +110,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
|||||||
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
|
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Field getField(Class clazz, String fieldName)
|
|
||||||
throws NoSuchFieldException {
|
|
||||||
try {
|
|
||||||
return clazz.getDeclaredField(fieldName);
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
Class superClass = clazz.getSuperclass();
|
|
||||||
if (superClass == null) {
|
|
||||||
throw e;
|
|
||||||
} else {
|
|
||||||
return getField(superClass, fieldName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onWorldInit(WorldInitEvent event) {
|
public void onWorldInit(WorldInitEvent event) {
|
||||||
try {
|
try {
|
||||||
|
@ -31,11 +31,11 @@ import com.volmit.iris.util.data.DoubleArrayUtils;
|
|||||||
*/
|
*/
|
||||||
public class AtomicAverage {
|
public class AtomicAverage {
|
||||||
protected final AtomicDoubleArray values;
|
protected final AtomicDoubleArray values;
|
||||||
protected int cursor;
|
protected transient int cursor;
|
||||||
private double average;
|
private transient double average;
|
||||||
private double lastSum;
|
private transient double lastSum;
|
||||||
private boolean dirty;
|
private transient boolean dirty;
|
||||||
private boolean brandNew;
|
private transient boolean brandNew;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an average holder
|
* Create an average holder
|
||||||
@ -57,7 +57,7 @@ public class AtomicAverage {
|
|||||||
*
|
*
|
||||||
* @param i the value
|
* @param i the value
|
||||||
*/
|
*/
|
||||||
public void put(double i) {
|
public synchronized void put(double i) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
@ -18,29 +18,67 @@
|
|||||||
|
|
||||||
package com.volmit.iris.util.collection;
|
package com.volmit.iris.util.collection;
|
||||||
|
|
||||||
import java.util.Collection;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
public class KSet<T> extends HashSet<T> {
|
import java.io.Serializable;
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class KSet<T> extends AbstractSet<T> implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final ConcurrentHashMap<T, Boolean> map;
|
||||||
|
|
||||||
public KSet() {
|
public KSet() {
|
||||||
super();
|
map = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KSet(Collection<? extends T> c) {
|
public KSet(Collection<? extends T> c) {
|
||||||
super(c);
|
this();
|
||||||
|
addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KSet(int initialCapacity, float loadFactor) {
|
public KSet(int initialCapacity, float loadFactor) {
|
||||||
super(initialCapacity, loadFactor);
|
map = new ConcurrentHashMap<>(initialCapacity, loadFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KSet(int initialCapacity) {
|
public KSet(int initialCapacity) {
|
||||||
super(initialCapacity);
|
map = new ConcurrentHashMap<>(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return map.containsKey(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(T t) {
|
||||||
|
return map.putIfAbsent(t, Boolean.TRUE) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return map.remove(o) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return map.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KSet<T> copy() {
|
public KSet<T> copy() {
|
||||||
return new KSet<T>(this);
|
return new KSet<>(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,13 @@ package com.volmit.iris.util.mantle;
|
|||||||
import com.google.common.util.concurrent.AtomicDouble;
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
import com.volmit.iris.engine.mantle.MantleWriter;
|
||||||
import com.volmit.iris.util.collection.KList;
|
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.documentation.RegionCoordinates;
|
import com.volmit.iris.util.documentation.RegionCoordinates;
|
||||||
@ -51,8 +50,6 @@ import java.util.*;
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mantle can store any type of data slice anywhere and manage regions & IO on it's own.
|
* The mantle can store any type of data slice anywhere and manage regions & IO on it's own.
|
||||||
@ -60,18 +57,18 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class Mantle {
|
public class Mantle {
|
||||||
private static final boolean disableClear = System.getProperty("disableClear", "false").equals("true");
|
|
||||||
private final File dataFolder;
|
private final File dataFolder;
|
||||||
@Getter
|
@Getter
|
||||||
private final int worldHeight;
|
private final int worldHeight;
|
||||||
private final Map<Long, Long> lastUse;
|
private final Map<Long, Long> lastUse;
|
||||||
@Getter
|
|
||||||
private final Map<Long, TectonicPlate> loadedRegions;
|
private final Map<Long, TectonicPlate> loadedRegions;
|
||||||
private final HyperLock hyperLock;
|
private final HyperLock hyperLock;
|
||||||
private final AtomicBoolean closed;
|
private final AtomicBoolean closed;
|
||||||
private final MultiBurst ioBurst;
|
private final MultiBurst ioBurst;
|
||||||
private final AtomicBoolean ioTrim;
|
private final AtomicBoolean ioTrim;
|
||||||
private final AtomicBoolean ioTectonicUnload;
|
private final AtomicBoolean ioTectonicUnload;
|
||||||
|
private final AtomicDouble adjustedIdleDuration;
|
||||||
|
private final KSet<Long> toUnload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new mantle
|
* Create a new mantle
|
||||||
@ -91,6 +88,8 @@ public class Mantle {
|
|||||||
loadedRegions = new KMap<>();
|
loadedRegions = new KMap<>();
|
||||||
lastUse = new KMap<>();
|
lastUse = new KMap<>();
|
||||||
ioBurst = MultiBurst.burst;
|
ioBurst = MultiBurst.burst;
|
||||||
|
adjustedIdleDuration = new AtomicDouble(0);
|
||||||
|
toUnload = new KSet<>();
|
||||||
Iris.debug("Opened The Mantle " + C.DARK_AQUA + dataFolder.getAbsolutePath());
|
Iris.debug("Opened The Mantle " + C.DARK_AQUA + dataFolder.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ public class Mantle {
|
|||||||
* @return the file
|
* @return the file
|
||||||
*/
|
*/
|
||||||
public static File fileForRegion(File folder, int x, int z) {
|
public static File fileForRegion(File folder, int x, int z) {
|
||||||
return fileForRegion(folder, key(x, z));
|
return fileForRegion(folder, key(x, z), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,12 +112,28 @@ public class Mantle {
|
|||||||
* @param key the region key
|
* @param key the region key
|
||||||
* @return the file
|
* @return the file
|
||||||
*/
|
*/
|
||||||
public static File fileForRegion(File folder, Long key) {
|
public static File fileForRegion(File folder, Long key, boolean convert) {
|
||||||
File f = new File(folder, "p." + key + ".ttp.lz4b");
|
File f = oldFileForRegion(folder, key);
|
||||||
if (!f.getParentFile().exists()) {
|
File fv = new File(folder, "pv." + key + ".ttp.lz4b");
|
||||||
f.getParentFile().mkdirs();
|
if (f.exists() && !fv.exists() && convert)
|
||||||
|
return f;
|
||||||
|
|
||||||
|
if (!fv.getParentFile().exists()) {
|
||||||
|
fv.getParentFile().mkdirs();
|
||||||
}
|
}
|
||||||
return f;
|
return fv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the old file for the given region
|
||||||
|
*
|
||||||
|
* @param folder the data folder
|
||||||
|
* @param key the region key
|
||||||
|
* @return the file
|
||||||
|
*/
|
||||||
|
public static File oldFileForRegion(File folder, Long key) {
|
||||||
|
return new File(folder, "p." + key + ".ttp.lz4b");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,7 +225,7 @@ public class Mantle {
|
|||||||
@RegionCoordinates
|
@RegionCoordinates
|
||||||
public boolean hasTectonicPlate(int x, int z) {
|
public boolean hasTectonicPlate(int x, int z) {
|
||||||
Long k = key(x, z);
|
Long k = key(x, z);
|
||||||
return loadedRegions.containsKey(k) || fileForRegion(dataFolder, k).exists();
|
return loadedRegions.containsKey(k) || fileForRegion(dataFolder, k, true).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -364,7 +379,8 @@ public class Mantle {
|
|||||||
loadedRegions.forEach((i, plate) -> b.queue(() -> {
|
loadedRegions.forEach((i, plate) -> b.queue(() -> {
|
||||||
try {
|
try {
|
||||||
plate.close();
|
plate.close();
|
||||||
plate.write(fileForRegion(dataFolder, i));
|
plate.write(fileForRegion(dataFolder, i, false));
|
||||||
|
oldFileForRegion(dataFolder, i).delete();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Failed to write Tectonic Plate " + C.DARK_GREEN + Cache.keyX(i) + " " + Cache.keyZ(i));
|
Iris.error("Failed to write Tectonic Plate " + C.DARK_GREEN + Cache.keyX(i) + " " + Cache.keyZ(i));
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -393,16 +409,6 @@ public class Mantle {
|
|||||||
return numberOfEntries * bytesPerEntry;
|
return numberOfEntries * bytesPerEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final AtomicDouble adjustedIdleDuration = new AtomicDouble(0);
|
|
||||||
@Getter
|
|
||||||
private final AtomicInteger forceAggressiveThreshold = new AtomicInteger(30);
|
|
||||||
@Getter
|
|
||||||
private final AtomicLong oldestTectonicPlate = new AtomicLong(0);
|
|
||||||
private final ReentrantLock unloadLock = new ReentrantLock();
|
|
||||||
@Getter
|
|
||||||
private final KList<Long> toUnload = new KList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save & unload regions that have not been used for more than the
|
* Save & unload regions that have not been used for more than the
|
||||||
* specified amount of milliseconds
|
* specified amount of milliseconds
|
||||||
@ -424,84 +430,75 @@ public class Mantle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ioTrim.set(true);
|
ioTrim.set(true);
|
||||||
unloadLock.lock();
|
|
||||||
try {
|
try {
|
||||||
if (lastUse != null && IrisEngineSVC.instance != null) {
|
double adjustedIdleDuration = this.adjustedIdleDuration.get();
|
||||||
if (!lastUse.isEmpty()) {
|
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration, 0));
|
||||||
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0));
|
|
||||||
for (long i : new ArrayList<>(lastUse.keySet())) {
|
|
||||||
double finalAdjustedIdleDuration = adjustedIdleDuration.get();
|
|
||||||
hyperLock.withLong(i, () -> {
|
|
||||||
Long lastUseTime = lastUse.get(i);
|
|
||||||
if (lastUseTime != null && M.ms() - lastUseTime >= finalAdjustedIdleDuration) {
|
|
||||||
toUnload.add(i);
|
|
||||||
Iris.debug("Tectonic Region added to unload");
|
|
||||||
IrisEngineSVC.instance.trimActiveAlive.reset();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (lastUse.isEmpty()) return;
|
||||||
|
double unloadTime = M.ms() - adjustedIdleDuration;
|
||||||
|
for (long id : lastUse.keySet()) {
|
||||||
|
hyperLock.withLong(id, () -> {
|
||||||
|
Long lastUseTime = lastUse.get(id);
|
||||||
|
if (lastUseTime != null && lastUseTime < unloadTime) {
|
||||||
|
toUnload.add(id);
|
||||||
|
Iris.debug("Tectonic Region added to unload");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
} finally {
|
} finally {
|
||||||
ioTrim.set(false);
|
ioTrim.set(false);
|
||||||
unloadLock.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int unloadTectonicPlate(int tectonicLimit) {
|
public synchronized int unloadTectonicPlate(int tectonicLimit) {
|
||||||
|
if (closed.get()) {
|
||||||
|
throw new RuntimeException("The Mantle is closed");
|
||||||
|
}
|
||||||
|
|
||||||
AtomicInteger i = new AtomicInteger();
|
AtomicInteger i = new AtomicInteger();
|
||||||
unloadLock.lock();
|
BurstExecutor burst = ioBurst.burst(toUnload.size());
|
||||||
BurstExecutor burst = null;
|
burst.setMulticore(toUnload.size() > tectonicLimit);
|
||||||
if (IrisEngineSVC.instance != null) {
|
|
||||||
try {
|
ioTectonicUnload.set(true);
|
||||||
KList<Long> copy = toUnload.copy();
|
try {
|
||||||
if (!disableClear) toUnload.clear();
|
for (long id : toUnload) {
|
||||||
burst = MultiBurst.burst.burst(copy.size());
|
burst.queue(() -> hyperLock.withLong(id, () -> {
|
||||||
burst.setMulticore(copy.size() > tectonicLimit);
|
TectonicPlate m = loadedRegions.get(id);
|
||||||
for (int j = 0; j < copy.size(); j++) {
|
if (m == null) {
|
||||||
Long id = copy.get(j);
|
Iris.debug("Tectonic Plate was added to unload while not loaded " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
||||||
if (id == null) {
|
toUnload.remove(id);
|
||||||
Iris.error("Null id in unloadTectonicPlate at index " + j);
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
burst.queue(() ->
|
if (m.inUse()) {
|
||||||
hyperLock.withLong(id, () -> {
|
Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ());
|
||||||
TectonicPlate m = loadedRegions.get(id);
|
lastUse.put(id, M.ms());
|
||||||
if (m != null) {
|
toUnload.remove(id);
|
||||||
if (m.inUse()) {
|
return;
|
||||||
Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ());
|
}
|
||||||
if (disableClear) toUnload.remove(id);
|
|
||||||
lastUse.put(id, M.ms());
|
try {
|
||||||
return;
|
m.write(fileForRegion(dataFolder, id, false));
|
||||||
}
|
oldFileForRegion(dataFolder, id).delete();
|
||||||
try {
|
loadedRegions.remove(id);
|
||||||
m.write(fileForRegion(dataFolder, id));
|
lastUse.remove(id);
|
||||||
loadedRegions.remove(id);
|
toUnload.remove(id);
|
||||||
lastUse.remove(id);
|
i.incrementAndGet();
|
||||||
if (disableClear) toUnload.remove(id);
|
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
||||||
i.incrementAndGet();
|
} catch (IOException e) {
|
||||||
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
Iris.reportError(e);
|
||||||
IrisEngineSVC.instance.unloadActiveAlive.reset();
|
}
|
||||||
} catch (IOException e) {
|
}));
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
burst.complete();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
if (burst != null)
|
|
||||||
burst.complete();
|
|
||||||
} finally {
|
|
||||||
unloadLock.unlock();
|
|
||||||
ioTectonicUnload.set(true);
|
|
||||||
}
|
}
|
||||||
return i.get();
|
burst.complete();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
burst.complete();
|
||||||
|
} finally {
|
||||||
|
ioTectonicUnload.set(false);
|
||||||
}
|
}
|
||||||
return i.get();
|
return i.get();
|
||||||
}
|
}
|
||||||
@ -517,7 +514,7 @@ public class Mantle {
|
|||||||
*/
|
*/
|
||||||
@RegionCoordinates
|
@RegionCoordinates
|
||||||
private TectonicPlate get(int x, int z) {
|
private TectonicPlate get(int x, int z) {
|
||||||
if (ioTrim.get()) {
|
if (ioTrim.get() || ioTectonicUnload.get()) {
|
||||||
try {
|
try {
|
||||||
return getSafe(x, z).get();
|
return getSafe(x, z).get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -577,7 +574,7 @@ public class Mantle {
|
|||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
try {
|
try {
|
||||||
Iris.addPanic("reading.tectonic-plate", file.getAbsolutePath());
|
Iris.addPanic("reading.tectonic-plate", file.getAbsolutePath());
|
||||||
region = TectonicPlate.read(worldHeight, file);
|
region = TectonicPlate.read(worldHeight, file, file.getName().startsWith("pv."));
|
||||||
|
|
||||||
if (region.getX() != x || region.getZ() != z) {
|
if (region.getX() != x || region.getZ() != z) {
|
||||||
Iris.warn("Loaded Tectonic Plate " + x + "," + z + " but read it as " + region.getX() + "," + region.getZ() + "... Assuming " + x + "," + z);
|
Iris.warn("Loaded Tectonic Plate " + x + "," + z + " but read it as " + region.getX() + "," + region.getZ() + "... Assuming " + x + "," + z);
|
||||||
@ -627,6 +624,14 @@ public class Mantle {
|
|||||||
return loadedRegions.size();
|
return loadedRegions.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getUnloadRegionCount() {
|
||||||
|
return toUnload.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAdjustedIdleDuration() {
|
||||||
|
return adjustedIdleDuration.get();
|
||||||
|
}
|
||||||
|
|
||||||
public <T> void set(int x, int y, int z, MatterSlice<T> slice) {
|
public <T> void set(int x, int y, int z, MatterSlice<T> slice) {
|
||||||
if (slice.isEmpty()) {
|
if (slice.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.util.mantle;
|
package com.volmit.iris.util.mantle;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.data.Varint;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.function.Consumer4;
|
import com.volmit.iris.util.function.Consumer4;
|
||||||
import com.volmit.iris.util.io.CountingDataInputStream;
|
import com.volmit.iris.util.io.CountingDataInputStream;
|
||||||
@ -74,11 +75,12 @@ public class MantleChunk {
|
|||||||
* @throws IOException shit happens
|
* @throws IOException shit happens
|
||||||
* @throws ClassNotFoundException shit happens
|
* @throws ClassNotFoundException shit happens
|
||||||
*/
|
*/
|
||||||
public MantleChunk(int sectionHeight, CountingDataInputStream din) throws IOException {
|
public MantleChunk(int version, int sectionHeight, CountingDataInputStream din) throws IOException {
|
||||||
this(sectionHeight, din.readByte(), din.readByte());
|
this(sectionHeight, din.readByte(), din.readByte());
|
||||||
int s = din.readByte();
|
int s = din.readByte();
|
||||||
|
int l = version < 0 ? flags.length() : Varint.readUnsignedVarInt(din);
|
||||||
|
|
||||||
for (int i = 0; i < flags.length(); i++) {
|
for (int i = 0; i < flags.length() && i < l; i++) {
|
||||||
flags.set(i, din.readBoolean() ? 1 : 0);
|
flags.set(i, din.readBoolean() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +89,10 @@ public class MantleChunk {
|
|||||||
long size = din.readInt();
|
long size = din.readInt();
|
||||||
if (size == 0) continue;
|
if (size == 0) continue;
|
||||||
long start = din.count();
|
long start = din.count();
|
||||||
|
if (i >= sectionHeight) {
|
||||||
|
din.skipTo(start + size);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sections.set(i, Matter.readDin(din));
|
sections.set(i, Matter.readDin(din));
|
||||||
@ -210,6 +216,7 @@ public class MantleChunk {
|
|||||||
dos.writeByte(x);
|
dos.writeByte(x);
|
||||||
dos.writeByte(z);
|
dos.writeByte(z);
|
||||||
dos.writeByte(sections.length());
|
dos.writeByte(sections.length());
|
||||||
|
Varint.writeUnsignedVarInt(flags.length(), dos);
|
||||||
|
|
||||||
for (int i = 0; i < flags.length(); i++) {
|
for (int i = 0; i < flags.length(); i++) {
|
||||||
dos.writeBoolean(flags.get(i) == 1);
|
dos.writeBoolean(flags.get(i) == 1);
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
package com.volmit.iris.util.mantle;
|
package com.volmit.iris.util.mantle;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.engine.EnginePanic;
|
import com.volmit.iris.engine.EnginePanic;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.data.Varint;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
@ -44,7 +45,9 @@ import java.util.concurrent.atomic.AtomicReferenceArray;
|
|||||||
* Tectonic Plates are fully atomic & thread safe
|
* Tectonic Plates are fully atomic & thread safe
|
||||||
*/
|
*/
|
||||||
public class TectonicPlate {
|
public class TectonicPlate {
|
||||||
private static final KSet<Thread> errors = new KSet<>();
|
private static final ThreadLocal<Boolean> errors = ThreadLocal.withInitial(() -> false);
|
||||||
|
public static final int MISSING = -1;
|
||||||
|
public static final int CURRENT = 0;
|
||||||
|
|
||||||
private final int sectionHeight;
|
private final int sectionHeight;
|
||||||
private final AtomicReferenceArray<MantleChunk> chunks;
|
private final AtomicReferenceArray<MantleChunk> chunks;
|
||||||
@ -74,11 +77,12 @@ public class TectonicPlate {
|
|||||||
* @param din the data input
|
* @param din the data input
|
||||||
* @throws IOException shit happens yo
|
* @throws IOException shit happens yo
|
||||||
*/
|
*/
|
||||||
public TectonicPlate(int worldHeight, CountingDataInputStream din) throws IOException {
|
public TectonicPlate(int worldHeight, CountingDataInputStream din, boolean versioned) throws IOException {
|
||||||
this(worldHeight, din.readInt(), din.readInt());
|
this(worldHeight, din.readInt(), din.readInt());
|
||||||
if (!din.markSupported())
|
if (!din.markSupported())
|
||||||
throw new IOException("Mark not supported!");
|
throw new IOException("Mark not supported!");
|
||||||
|
|
||||||
|
int v = versioned ? Varint.readUnsignedVarInt(din) : MISSING;
|
||||||
for (int i = 0; i < chunks.length(); i++) {
|
for (int i = 0; i < chunks.length(); i++) {
|
||||||
long size = din.readInt();
|
long size = din.readInt();
|
||||||
if (size == 0) continue;
|
if (size == 0) continue;
|
||||||
@ -86,7 +90,7 @@ public class TectonicPlate {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Iris.addPanic("read-chunk", "Chunk[" + i + "]");
|
Iris.addPanic("read-chunk", "Chunk[" + i + "]");
|
||||||
chunks.set(i, new MantleChunk(sectionHeight, din));
|
chunks.set(i, new MantleChunk(v, sectionHeight, din));
|
||||||
EnginePanic.saveLast();
|
EnginePanic.saveLast();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
long end = start + size;
|
long end = start + size;
|
||||||
@ -103,7 +107,7 @@ public class TectonicPlate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TectonicPlate read(int worldHeight, File file) throws IOException {
|
public static TectonicPlate read(int worldHeight, File file, boolean versioned) throws IOException {
|
||||||
try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.SYNC)) {
|
try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.SYNC)) {
|
||||||
fc.lock();
|
fc.lock();
|
||||||
|
|
||||||
@ -111,10 +115,10 @@ public class TectonicPlate {
|
|||||||
LZ4BlockInputStream lz4 = new LZ4BlockInputStream(fin);
|
LZ4BlockInputStream lz4 = new LZ4BlockInputStream(fin);
|
||||||
BufferedInputStream bis = new BufferedInputStream(lz4);
|
BufferedInputStream bis = new BufferedInputStream(lz4);
|
||||||
try (CountingDataInputStream din = CountingDataInputStream.wrap(bis)) {
|
try (CountingDataInputStream din = CountingDataInputStream.wrap(bis)) {
|
||||||
return new TectonicPlate(worldHeight, din);
|
return new TectonicPlate(worldHeight, din, versioned);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (errors.remove(Thread.currentThread())) {
|
if (IrisSettings.get().getGeneral().isDumpMantleOnError() && errors.get()) {
|
||||||
File dump = Iris.instance.getDataFolder("dump", file.getName() + ".bin");
|
File dump = Iris.instance.getDataFolder("dump", file.getName() + ".bin");
|
||||||
try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.SYNC)) {
|
try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.SYNC)) {
|
||||||
fc.lock();
|
fc.lock();
|
||||||
@ -124,6 +128,7 @@ public class TectonicPlate {
|
|||||||
Files.copy(lz4, dump.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(lz4, dump.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
errors.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +227,7 @@ public class TectonicPlate {
|
|||||||
write(dos);
|
write(dos);
|
||||||
}
|
}
|
||||||
Files.move(temp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
|
Files.move(temp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
|
||||||
Iris.debug("Saved Tectonic Plate " + C.DARK_GREEN + file.getName().split("\\Q.\\E")[0] + C.RED + " in " + Form.duration(p.getMilliseconds(), 2));
|
Iris.debug("Saved Tectonic Plate " + C.DARK_GREEN + file.getName() + C.RED + " in " + Form.duration(p.getMilliseconds(), 2));
|
||||||
temp.delete();
|
temp.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +240,7 @@ public class TectonicPlate {
|
|||||||
public void write(DataOutputStream dos) throws IOException {
|
public void write(DataOutputStream dos) throws IOException {
|
||||||
dos.writeInt(x);
|
dos.writeInt(x);
|
||||||
dos.writeInt(z);
|
dos.writeInt(z);
|
||||||
|
Varint.writeUnsignedVarInt(CURRENT, dos);
|
||||||
|
|
||||||
var bytes = new ByteArrayOutputStream(8192);
|
var bytes = new ByteArrayOutputStream(8192);
|
||||||
var sub = new DataOutputStream(bytes);
|
var sub = new DataOutputStream(bytes);
|
||||||
@ -256,6 +262,6 @@ public class TectonicPlate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void addError() {
|
public static void addError() {
|
||||||
errors.add(Thread.currentThread());
|
errors.set(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,15 +154,16 @@ public interface Matter {
|
|||||||
matter.putSlice(type, slice);
|
matter.putSlice(type, slice);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
long end = start + size;
|
long end = start + size;
|
||||||
Iris.error("Failed to read matter slice, skipping it.");
|
if (!(e instanceof ClassNotFoundException)) {
|
||||||
Iris.addPanic("read.byte.range", start + " " + end);
|
Iris.error("Failed to read matter slice, skipping it.");
|
||||||
Iris.addPanic("read.byte.current", din.count() + "");
|
Iris.addPanic("read.byte.range", start + " " + end);
|
||||||
Iris.reportError(e);
|
Iris.addPanic("read.byte.current", din.count() + "");
|
||||||
e.printStackTrace();
|
Iris.reportError(e);
|
||||||
Iris.panic();
|
e.printStackTrace();
|
||||||
|
Iris.panic();
|
||||||
|
TectonicPlate.addError();
|
||||||
|
}
|
||||||
din.skipTo(end);
|
din.skipTo(end);
|
||||||
TectonicPlate.addError();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user