mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-19 15:09:18 +00:00
hopefully fix the DataContainer this time
This commit is contained in:
@@ -19,12 +19,12 @@
|
|||||||
package com.volmit.iris.util.hunk.bits;
|
package com.volmit.iris.util.hunk.bits;
|
||||||
|
|
||||||
import com.volmit.iris.util.data.Varint;
|
import com.volmit.iris.util.data.Varint;
|
||||||
|
import lombok.Getter;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLongArray;
|
import java.util.concurrent.atomic.AtomicLongArray;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
@@ -52,8 +52,10 @@ public class DataBits {
|
|||||||
0, 5};
|
0, 5};
|
||||||
|
|
||||||
private final AtomicLongArray data;
|
private final AtomicLongArray data;
|
||||||
|
@Getter
|
||||||
private final int bits;
|
private final int bits;
|
||||||
private final long mask;
|
private final long mask;
|
||||||
|
@Getter
|
||||||
private final int size;
|
private final int size;
|
||||||
private final int valuesPerLong;
|
private final int valuesPerLong;
|
||||||
private final int divideMul;
|
private final int divideMul;
|
||||||
@@ -149,18 +151,9 @@ public class DataBits {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBits() {
|
|
||||||
return bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataBits setBits(int newBits) {
|
public DataBits setBits(int newBits) {
|
||||||
if (bits != newBits) {
|
if (bits != newBits) {
|
||||||
DataBits newData = new DataBits(newBits, size);
|
DataBits newData = new DataBits(newBits, size);
|
||||||
AtomicInteger c = new AtomicInteger(0);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
newData.set(i, get(i));
|
newData.set(i, get(i));
|
||||||
|
|||||||
@@ -19,78 +19,32 @@
|
|||||||
package com.volmit.iris.util.hunk.bits;
|
package com.volmit.iris.util.hunk.bits;
|
||||||
|
|
||||||
import com.volmit.iris.util.data.Varint;
|
import com.volmit.iris.util.data.Varint;
|
||||||
|
import lombok.Synchronized;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
public class DataContainer<T> {
|
public class DataContainer<T> {
|
||||||
protected static final int INITIAL_BITS = 3;
|
protected static final int INITIAL_BITS = 3;
|
||||||
protected static final int LINEAR_BITS_LIMIT = 4;
|
protected static final int LINEAR_BITS_LIMIT = 4;
|
||||||
protected static final int LINEAR_INITIAL_LENGTH = (int) Math.pow(2, LINEAR_BITS_LIMIT) + 1;
|
protected static final int LINEAR_INITIAL_LENGTH = (int) Math.pow(2, LINEAR_BITS_LIMIT) + 1;
|
||||||
protected static final int[] BIT = computeBitLimits();
|
protected static final int[] BIT = computeBitLimits();
|
||||||
private final AtomicReference<Palette<T>> palette;
|
private volatile Palette<T> palette;
|
||||||
private final AtomicReference<DataBits> data;
|
private volatile DataBits data;
|
||||||
private final AtomicInteger bits;
|
|
||||||
private final int length;
|
private final int length;
|
||||||
private final Writable<T> writer;
|
private final Writable<T> writer;
|
||||||
|
|
||||||
public DataContainer(Writable<T> writer, int length) {
|
public DataContainer(Writable<T> writer, int length) {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.bits = new AtomicInteger(INITIAL_BITS);
|
this.data = new DataBits(INITIAL_BITS, length);
|
||||||
this.data = new AtomicReference<>(new DataBits(INITIAL_BITS, length));
|
this.palette = newPalette(INITIAL_BITS);
|
||||||
this.palette = new AtomicReference<>(newPalette(INITIAL_BITS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataContainer(DataInputStream din, Writable<T> writer) throws IOException {
|
public DataContainer(DataInputStream din, Writable<T> writer) throws IOException {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.length = Varint.readUnsignedVarInt(din);
|
this.length = Varint.readUnsignedVarInt(din);
|
||||||
this.palette = new AtomicReference<>(newPalette(din));
|
this.palette = newPalette(din);
|
||||||
this.data = new AtomicReference<>(new DataBits(palette.get().bits(), length, din));
|
this.data = new DataBits(palette.bits(), length, din);
|
||||||
this.bits = new AtomicInteger(palette.get().bits());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String readBitString(DataInputStream din) throws IOException {
|
|
||||||
DataContainer<Character> c = new DataContainer<>(din, new Writable<Character>() {
|
|
||||||
@Override
|
|
||||||
public Character readNodeData(DataInputStream din) throws IOException {
|
|
||||||
return din.readChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeNodeData(DataOutputStream dos, Character character) throws IOException {
|
|
||||||
dos.writeChar(character);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
for (int i = c.size() - 1; i >= 0; i--) {
|
|
||||||
sb.setCharAt(i, c.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeBitString(String s, DataOutputStream dos) throws IOException {
|
|
||||||
DataContainer<Character> c = new DataContainer<>(new Writable<Character>() {
|
|
||||||
@Override
|
|
||||||
public Character readNodeData(DataInputStream din) throws IOException {
|
|
||||||
return din.readChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeNodeData(DataOutputStream dos, Character character) throws IOException {
|
|
||||||
dos.writeChar(character);
|
|
||||||
}
|
|
||||||
}, s.length());
|
|
||||||
|
|
||||||
for (int i = 0; i < s.length(); i++) {
|
|
||||||
c.set(i, s.charAt(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeDos(dos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] computeBitLimits() {
|
private static int[] computeBitLimits() {
|
||||||
@@ -117,17 +71,9 @@ public class DataContainer<T> {
|
|||||||
return DataContainer.BIT.length - 1;
|
return DataContainer.BIT.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataBits getData() {
|
|
||||||
return data.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Palette<T> getPalette() {
|
|
||||||
return palette.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DataContainer <" + length + " x " + bits + " bits> -> Palette<" + palette.get().getClass().getSimpleName().replaceAll("\\QPalette\\E", "") + ">: " + palette.get().size() +
|
return "DataContainer <" + length + " x " + data.getBits() + " bits> -> Palette<" + palette.getClass().getSimpleName().replaceAll("\\QPalette\\E", "") + ">: " + palette.size() +
|
||||||
" " + data.get().toString() + " PalBit: " + palette.get().bits();
|
" " + data.toString() + " PalBit: " + palette.bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] write() throws IOException {
|
public byte[] write() throws IOException {
|
||||||
@@ -140,14 +86,13 @@ public class DataContainer<T> {
|
|||||||
writeDos(new DataOutputStream(out));
|
writeDos(new DataOutputStream(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
public void writeDos(DataOutputStream dos) throws IOException {
|
public void writeDos(DataOutputStream dos) throws IOException {
|
||||||
synchronized (this) {
|
Varint.writeUnsignedVarInt(length, dos);
|
||||||
Varint.writeUnsignedVarInt(length, dos);
|
Varint.writeUnsignedVarInt(palette.size(), dos);
|
||||||
Varint.writeUnsignedVarInt(palette.get().size(), dos);
|
palette.iterateIO((data, __) -> writer.writeNodeData(dos, data));
|
||||||
palette.get().iterateIO((data, __) -> writer.writeNodeData(dos, data));
|
data.write(dos);
|
||||||
data.get().write(dos);
|
dos.flush();
|
||||||
dos.flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Palette<T> newPalette(DataInputStream din) throws IOException {
|
private Palette<T> newPalette(DataInputStream din) throws IOException {
|
||||||
@@ -165,45 +110,44 @@ public class DataContainer<T> {
|
|||||||
return new HashPalette<>();
|
return new HashPalette<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
public void set(int position, T t) {
|
public void set(int position, T t) {
|
||||||
synchronized (this) {
|
int id = palette.id(t);
|
||||||
int id = palette.get().id(t);
|
|
||||||
|
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
id = palette.get().add(t);
|
id = palette.add(t);
|
||||||
updateBits();
|
updateBits();
|
||||||
}
|
|
||||||
|
|
||||||
data.get().set(position, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.set(position, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
@SuppressWarnings("NonAtomicOperationOnVolatileField")
|
||||||
private void updateBits() {
|
private void updateBits() {
|
||||||
if (palette.get().bits() == bits.get())
|
if (palette.bits() == data.getBits())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int bits = palette.get().bits();
|
int bits = palette.bits();
|
||||||
if (this.bits.get() <= LINEAR_BITS_LIMIT != bits <= LINEAR_BITS_LIMIT) {
|
if (data.getBits() <= LINEAR_BITS_LIMIT != bits <= LINEAR_BITS_LIMIT) {
|
||||||
palette.updateAndGet(p -> newPalette(bits).from(p));
|
palette = newPalette(bits).from(palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.updateAndGet(d -> d.setBits(bits));
|
data = data.setBits(bits);
|
||||||
this.bits.set(bits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
public T get(int position) {
|
public T get(int position) {
|
||||||
synchronized (this) {
|
int id = data.get(position);
|
||||||
int id = data.get().get(position);
|
|
||||||
|
|
||||||
if (id <= 0) {
|
if (id <= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
return palette.get().get(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return palette.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return getData().getSize();
|
return data.getSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -468,8 +468,8 @@ public class Mantle {
|
|||||||
|
|
||||||
ioTectonicUnload.acquireUninterruptibly(LOCK_SIZE);
|
ioTectonicUnload.acquireUninterruptibly(LOCK_SIZE);
|
||||||
try {
|
try {
|
||||||
|
double unloadTime = M.ms() - adjustedIdleDuration.get();
|
||||||
for (long id : toUnload) {
|
for (long id : toUnload) {
|
||||||
double unloadTime = M.ms() - adjustedIdleDuration.get();
|
|
||||||
burst.queue(() -> hyperLock.withLong(id, () -> {
|
burst.queue(() -> hyperLock.withLong(id, () -> {
|
||||||
TectonicPlate m = loadedRegions.get(id);
|
TectonicPlate m = loadedRegions.get(id);
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
@@ -490,6 +490,7 @@ public class Mantle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
m.close();
|
||||||
worker.write(fileForRegion(dataFolder, id, false).getName(), m);
|
worker.write(fileForRegion(dataFolder, id, false).getName(), m);
|
||||||
oldFileForRegion(dataFolder, id).delete();
|
oldFileForRegion(dataFolder, id).delete();
|
||||||
loadedRegions.remove(id, m);
|
loadedRegions.remove(id, m);
|
||||||
@@ -497,7 +498,7 @@ public class Mantle {
|
|||||||
toUnload.remove(id);
|
toUnload.remove(id);
|
||||||
i.incrementAndGet();
|
i.incrementAndGet();
|
||||||
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
||||||
} catch (IOException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ public interface Matter {
|
|||||||
long size = din.readInt();
|
long size = din.readInt();
|
||||||
if (size == 0) continue;
|
if (size == 0) continue;
|
||||||
long start = din.count();
|
long start = din.count();
|
||||||
|
long end = start + size;
|
||||||
|
|
||||||
Iris.addPanic("read.matter.slice", i + "");
|
Iris.addPanic("read.matter.slice", i + "");
|
||||||
try {
|
try {
|
||||||
@@ -150,9 +151,9 @@ public interface Matter {
|
|||||||
Class<?> type = Class.forName(cn);
|
Class<?> type = Class.forName(cn);
|
||||||
MatterSlice<?> slice = matter.createSlice(type, matter);
|
MatterSlice<?> slice = matter.createSlice(type, matter);
|
||||||
slice.read(din);
|
slice.read(din);
|
||||||
|
if (din.count() < end) throw new IOException("Matter slice read size mismatch!");
|
||||||
matter.putSlice(type, slice);
|
matter.putSlice(type, slice);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
long end = start + size;
|
|
||||||
if (!(e instanceof ClassNotFoundException)) {
|
if (!(e instanceof ClassNotFoundException)) {
|
||||||
Iris.error("Failed to read matter slice, skipping it.");
|
Iris.error("Failed to read matter slice, skipping it.");
|
||||||
Iris.addPanic("read.byte.range", start + " " + end);
|
Iris.addPanic("read.byte.range", start + " " + end);
|
||||||
@@ -165,7 +166,7 @@ public interface Matter {
|
|||||||
din.skipTo(end);
|
din.skipTo(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (din.count() != start + size) {
|
if (din.count() != end) {
|
||||||
throw new IOException("Matter slice read size mismatch!");
|
throw new IOException("Matter slice read size mismatch!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user