9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-31 04:46:40 +00:00

fix ArrayIndexOutOfBoundsException

fix NullPointerException
fix ConcurrentModificationException x2
This commit is contained in:
CrazyDev22
2023-12-22 19:36:07 +01:00
parent bb4ad08cc5
commit af8778c6cd
3 changed files with 52 additions and 29 deletions

View File

@@ -16,11 +16,13 @@ import org.bukkit.World;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
public class IrisEngineSVC implements IrisService {
private static final AtomicInteger tectonicLimit = new AtomicInteger(30);
private final KMap<Engine, Long> cache = new KMap<>();
private final ReentrantLock lastUseLock = new ReentrantLock();
private final KMap<Engine, Long> lastUse = new KMap<>();
private Looper cacheTicker;
private Looper trimTicker;
private Looper unloadTicker;
@@ -52,13 +54,18 @@ public class IrisEngineSVC implements IrisService {
@Override
protected long loop() {
long now = System.currentTimeMillis();
for (Engine key : cache.keySet()) {
Long last = cache.get(key);
if (last == null)
continue;
if (now - last > 600000) { // 10 minutes
cache.remove(key);
lastUseLock.lock();
try {
for (Engine key : new ArrayList<>(lastUse.keySet())) {
Long last = lastUse.get(key);
if (last == null)
continue;
if (now - last > 60000) { // 1 minute
lastUse.remove(key);
}
}
} finally {
lastUseLock.unlock();
}
return 1000;
}
@@ -71,14 +78,14 @@ public class IrisEngineSVC implements IrisService {
try {
Engine engine = supplier.get();
if (engine != null) {
engine.getMantle().trim(tectonicLimit.get() / cache.size());
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
}
} catch (Throwable e) {
Iris.reportError(e);
return -1;
}
int size = cache.size();
int size = lastUse.size();
long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
@@ -106,7 +113,7 @@ public class IrisEngineSVC implements IrisService {
return -1;
}
int size = cache.size();
int size = lastUse.size();
long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
@@ -132,7 +139,9 @@ public class IrisEngineSVC implements IrisService {
if (generator != null) {
Engine engine = generator.getEngine();
if (engine != null) {
cache.put(engine, System.currentTimeMillis());
lastUseLock.lock();
lastUse.put(engine, System.currentTimeMillis());
lastUseLock.unlock();
return engine;
}
}
@@ -149,6 +158,6 @@ public class IrisEngineSVC implements IrisService {
cacheTicker.interrupt();
trimTicker.interrupt();
unloadTicker.interrupt();
cache.clear();
lastUse.clear();
}
}

View File

@@ -23,8 +23,10 @@ import com.volmit.iris.util.function.Consumer2;
import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
public class HashPalette<T> implements Palette<T> {
private final ReentrantLock lock = new ReentrantLock();
private final LinkedHashMap<T, Integer> palette;
private final KMap<Integer, T> lookup;
private final AtomicInteger size;
@@ -47,14 +49,18 @@ public class HashPalette<T> implements Palette<T> {
@Override
public int add(T t) {
int index = size.getAndIncrement();
palette.put(t, index);
lock.lock();
try {
int index = size.getAndIncrement();
palette.put(t, index);
if (t != null) {
lookup.put(index, t);
if (t != null) {
lookup.put(index, t);
}
return index;
} finally {
lock.unlock();
}
return index;
}
@Override
@@ -74,12 +80,17 @@ public class HashPalette<T> implements Palette<T> {
@Override
public void iterate(Consumer2<T, Integer> c) {
for (T i : palette.keySet()) {
if (i == null) {
continue;
}
lock.lock();
try {
for (T i : palette.keySet()) {
if (i == null) {
continue;
}
c.accept(i, id(i));
c.accept(i, id(i));
}
} finally {
lock.unlock();
}
}
}

View File

@@ -50,6 +50,7 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
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.
@@ -396,8 +397,9 @@ public class Mantle {
private final AtomicInteger forceAggressiveThreshold = new AtomicInteger(30);
@Getter
private final AtomicLong oldestTectonicPlate = new AtomicLong(0);
private final ReentrantLock unloadLock = new ReentrantLock();
@Getter
private Set<Long> toUnload = new HashSet<>();
private final Set<Long> toUnload = new HashSet<>();
/**
* Save & unload regions that have not been used for more than the
@@ -421,6 +423,7 @@ public class Mantle {
}
ioTrim.set(true);
unloadLock.lock();
try {
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0));
if (lastUse != null) {
@@ -438,14 +441,13 @@ public class Mantle {
} finally {
ioTrim.set(false);
unloadLock.unlock();
}
}
public int unloadTectonicPlate() {
AtomicInteger i = new AtomicInteger();
Set<Long> toUnload = this.toUnload;
this.toUnload = new HashSet<>();
toUnload.removeIf(Objects::isNull);
unloadLock.lock();
try {
List<Future<?>> futures = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(dynamicThreads.get());
@@ -471,15 +473,16 @@ public class Mantle {
try {
while (!futures.isEmpty()) {
futures.remove(0).get();
futures.removeIf(Future::isDone);
}
service.shutdown();
} catch (InterruptedException ignored) {}
} catch (Exception e) {
e.printStackTrace();
} finally {
this.toUnload.addAll(toUnload);
unloadLock.unlock();
ioTectonicUnload.set(true);
}
ioTectonicUnload.set(true);
return i.get();
}