Fix ZSTD implementation and test-loading. Don't allow disabling of the test on startup

This commit is contained in:
dordsor21 2021-09-17 14:38:28 +01:00
parent 9fb6ebe7ac
commit 74697ee312
No known key found for this signature in database
GPG Key ID: 1E53E88969FFCF0B
4 changed files with 124 additions and 132 deletions

View File

@ -36,7 +36,7 @@ truezip = "6.8.4"
auto-value = "1.7.4"
findbugs = "3.0.2"
rhino-runtime = "1.7.13"
zstd-jni = "1.5.0-4"
zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs
antlr4 = "4.9.1"
json-simple = "1.1.1"
paranamer = "2.8"

View File

@ -147,6 +147,9 @@ tasks.named<ShadowJar>("shadowJar") {
// If it turns out not to be true for Spigot/Paper, our only two official platforms, this can be uncommented.
// include(dependency("org.apache.logging.log4j:log4j-api"))
include(dependency("org.antlr:antlr4-runtime"))
// ZSTD does not work if relocated. https://github.com/luben/zstd-jni/issues/189 Use not latest as it can be difficult
// to obtain latest ZSTD lib
include(dependency("com.github.luben:zstd-jni:1.4.8-1"))
relocate("org.bstats", "com.sk89q.worldedit.bstats") {
include(dependency("org.bstats:"))
}
@ -162,9 +165,6 @@ tasks.named<ShadowJar>("shadowJar") {
relocate("com.intellectualsites.paster", "com.fastasyncworldedit.paster") {
include(dependency("com.intellectualsites.paster:Paster:1.1.1"))
}
relocate("com.github.luben", "com.fastasyncworldedit.core.zstd") {
include(dependency("com.github.luben:zstd-jni:1.5.0-4"))
}
relocate("net.jpountz", "com.fastasyncworldedit.core.jpountz") {
include(dependency("net.jpountz:lz4-java-stream:1.0.0"))
}

View File

@ -12,9 +12,10 @@ import com.fastasyncworldedit.core.util.RandomTextureUtil;
import com.fastasyncworldedit.core.util.TaskManager;
import com.fastasyncworldedit.core.util.TextureUtil;
import com.fastasyncworldedit.core.util.WEManager;
import com.github.luben.zstd.util.Native;
import com.github.luben.zstd.Zstd;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import net.jpountz.lz4.LZ4Factory;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
@ -81,44 +82,13 @@ public class Fawe {
* The ticks-per-second timer.
*/
private final FaweTimer timer;
private FaweVersion version;
private TextureUtil textures;
private QueueHandler queueHandler;
/**
* Get the implementation specific class.
*/
@SuppressWarnings("unchecked")
public static <T extends IFawe> T imp() {
return instance != null ? (T) instance.implementation : null;
}
/**
* Get the implementation independent class.
*/
public static Fawe get() {
return instance;
}
/**
* This method is not for public use. If you have to ask what it does then you shouldn't be using it.
*/
public static void set(final IFawe implementation) throws InstanceAlreadyExistsException, IllegalArgumentException {
if (instance != null) {
throw new InstanceAlreadyExistsException("FAWE has already been initialized with: " + instance.implementation);
}
if (implementation == null) {
throw new IllegalArgumentException("Implementation may not be null.");
}
instance = new Fawe(implementation);
}
/**
* The platform specific implementation.
*/
private final IFawe implementation;
private FaweVersion version;
private TextureUtil textures;
private QueueHandler queueHandler;
private Thread thread;
private Fawe(final IFawe implementation) {
@ -163,6 +133,94 @@ public class Fawe {
TaskManager.IMP.repeat(timer, 1);
}
/**
* Get the implementation specific class.
*/
@SuppressWarnings("unchecked")
public static <T extends IFawe> T imp() {
return instance != null ? (T) instance.implementation : null;
}
/**
* Get the implementation independent class.
*/
public static Fawe get() {
return instance;
}
/**
* This method is not for public use. If you have to ask what it does then you shouldn't be using it.
*/
public static void set(final IFawe implementation) throws InstanceAlreadyExistsException, IllegalArgumentException {
if (instance != null) {
throw new InstanceAlreadyExistsException("FAWE has already been initialized with: " + instance.implementation);
}
if (implementation == null) {
throw new IllegalArgumentException("Implementation may not be null.");
}
instance = new Fawe(implementation);
}
public static void setupInjector() {
// Check Base OS Arch for Mismatching Architectures
boolean x86OS = System.getProperty("sun.arch.data.model").contains("32");
boolean x86JVM = System.getProperty("os.arch").contains("32");
if (x86OS != x86JVM) {
LOGGER.info("You are running 32-bit Java on a 64-bit machine. Please upgrade to 64-bit Java.");
}
}
public static boolean isMainThread() {
return instance == null || instance.thread == Thread.currentThread();
}
/**
* Non-api. Handles an input FAWE exception if not already handled, given the input boolean array.
* Looks at the {@link FaweException.Type} and decides what to do (rethrows if we want to attempt to show the error to the
* player, outputs to console where necessary).
*
* @param faweExceptionReasonsUsed boolean array that should be cached where this method is called from of length {@code
* FaweException.Type.values().length}
* @param e {@link FaweException} to handle
* @param logger {@link Logger} of the calling class
*/
public static void handleFaweException(
boolean[] faweExceptionReasonsUsed,
FaweException e,
final Logger logger
) {
FaweException.Type type = e.getType();
switch (type) {
case OTHER:
logger.catching(e);
throw e;
case LOW_MEMORY:
if (!faweExceptionReasonsUsed[type.ordinal()]) {
logger.warn("FaweException: " + e.getMessage());
faweExceptionReasonsUsed[type.ordinal()] = true;
throw e;
}
case MAX_TILES:
case NO_REGION:
case MAX_CHECKS:
case MAX_CHANGES:
case MAX_ENTITIES:
case MAX_ITERATIONS:
case OUTSIDE_REGION:
if (!faweExceptionReasonsUsed[type.ordinal()]) {
faweExceptionReasonsUsed[type.ordinal()] = true;
throw e;
} else {
return;
}
default:
if (!faweExceptionReasonsUsed[type.ordinal()]) {
faweExceptionReasonsUsed[type.ordinal()] = true;
logger.warn("FaweException: " + e.getMessage());
}
}
}
public void onDisable() {
if (imp().getPreloader(false) != null) {
imp().getPreloader(false).cancel();
@ -254,45 +312,35 @@ public class Fawe {
LOGGER.error("Failed to load config.", e);
}
Settings.IMP.QUEUE.TARGET_SIZE = Math.max(Settings.IMP.QUEUE.TARGET_SIZE, Settings.IMP.QUEUE.PARALLEL_THREADS);
}
public WorldEdit getWorldEdit() {
return WorldEdit.getInstance();
}
public static void setupInjector() {
/*
* Modify the sessions
* - EditSession supports a custom queue, and a lot of optimizations
* - LocalSession supports VirtualPlayers and undo on disk
*/
if (!Settings.IMP.EXPERIMENTAL.DISABLE_NATIVES) {
// A higher amount is currently not supported by ZSTD / ZSTD JNI
try {
byte[] in = new byte[0];
byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in);
byte[] ob = new byte[100];
assert (LZ4Factory.fastestJavaInstance().fastDecompressor().decompress(ob, compressed) == 0);
LOGGER.info("LZ4 Compression Binding loaded successfully");
} catch (Throwable e) {
LOGGER.error("LZ4 Compression Binding Not Found.\n"
+ "FAWE will still work but compression will be slower.", e);
}
try {
byte[] in = new byte[0];
byte[] compressed = Zstd.compress(in);
byte[] ob = new byte[100];
assert (Zstd.decompress(ob, compressed) == 0);
LOGGER.info("ZSTD Compression Binding loaded successfully");
} catch (Throwable e) {
if (Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL > 6 || Settings.IMP.HISTORY.COMPRESSION_LEVEL > 6) {
Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL = Math.min(6, Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL);
Settings.IMP.HISTORY.COMPRESSION_LEVEL = Math.min(6, Settings.IMP.HISTORY.COMPRESSION_LEVEL);
}
try {
Native.load();
} catch (Throwable e) {
LOGGER.error("ZSTD compression binding not found.\n"
+ "FAWE will still work but compression won't work as well.\n", e);
}
try {
net.jpountz.util.Native.load();
} catch (Throwable e) {
LOGGER.error("LZ4 Compression Binding Not Found.\n"
+ "FAWE will still work but compression will be slower.\n", e);
LOGGER.error("ZSTD Compression Binding Not Found.\n"
+ "FAWE will still work but compression won't work as well.", e);
}
}
Settings.IMP.save(file);
}
// Check Base OS Arch for Mismatching Architectures
boolean x86OS = System.getProperty("sun.arch.data.model").contains("32");
boolean x86JVM = System.getProperty("os.arch").contains("32");
if (x86OS != x86JVM) {
LOGGER.info("You are running 32-bit Java on a 64-bit machine. Please upgrade to 64-bit Java.");
}
public WorldEdit getWorldEdit() {
return WorldEdit.getInstance();
}
private void setupMemoryListener() {
@ -338,10 +386,6 @@ public class Fawe {
return this.thread;
}
public static boolean isMainThread() {
return instance == null || instance.thread == Thread.currentThread();
}
/**
* Sets the main thread to the current thread.
*/
@ -349,51 +393,4 @@ public class Fawe {
return this.thread = Thread.currentThread();
}
/**
* Non-api. Handles an input FAWE exception if not already handled, given the input boolean array.
* Looks at the {@link FaweException.Type} and decides what to do (rethrows if we want to attempt to show the error to the
* player, outputs to console where necessary).
*
* @param faweExceptionReasonsUsed boolean array that should be cached where this method is called from of length {@code
* FaweException.Type.values().length}
* @param e {@link FaweException} to handle
* @param logger {@link Logger} of the calling class
*/
public static void handleFaweException(
boolean[] faweExceptionReasonsUsed,
FaweException e,
final Logger logger
) {
FaweException.Type type = e.getType();
switch (type) {
case OTHER:
logger.catching(e);
throw e;
case LOW_MEMORY:
if (!faweExceptionReasonsUsed[type.ordinal()]) {
logger.warn("FaweException: " + e.getMessage());
faweExceptionReasonsUsed[type.ordinal()] = true;
throw e;
}
case MAX_TILES:
case NO_REGION:
case MAX_CHECKS:
case MAX_CHANGES:
case MAX_ENTITIES:
case MAX_ITERATIONS:
case OUTSIDE_REGION:
if (!faweExceptionReasonsUsed[type.ordinal()]) {
faweExceptionReasonsUsed[type.ordinal()] = true;
throw e;
} else {
return;
}
default:
if (!faweExceptionReasonsUsed[type.ordinal()]) {
faweExceptionReasonsUsed[type.ordinal()] = true;
logger.warn("FaweException: " + e.getMessage());
}
}
}
}

View File

@ -224,12 +224,11 @@ public class Settings extends Config {
"4 = 1 x medium, 1 x fast",
"5 = 1 x medium, 2 x fast",
"6 = 1 x medium, 3 x fast",
/* A higher value is currently not supported by ZSTD / ZSTD-JNI
"7 = 1 x high, 1 x medium, 1 x fast",
"8 = 1 x high, 1 x medium, 2 x fast",
"9 = 1 x high, 1 x medium, 3 x fast (best compression)",
"NOTE: If using disk, do some compression (3+) as smaller files save faster"
*/
"NOTE: If using disk, do some compression (3+) as smaller files save faster",
" - levels over 6 require ZSTD 1.4.8+ to be installed to the system"
})
public int COMPRESSION_LEVEL = 3;
@Comment({
@ -390,11 +389,6 @@ public class Settings extends Config {
})
public boolean PERSISTENT_BRUSHES = true;
@Comment({
"Disable using native libraries",
})
public boolean DISABLE_NATIVES = false;
@Comment({
"[SAFE] Keep entities that are positioned in non-air blocks when editing an area",
"Might cause client-side FPS lagg in some situations"
@ -502,7 +496,8 @@ public class Settings extends Config {
" - TODO: Buffered random access with compression is not implemented on disk yet",
" - 0 = No compression",
" - 1 = Fast compression",
" - 2-6 = Slower compression"
" - 2-17 = Slower compression",
" - levels over 6 require ZSTD 1.4.8+ to be installed to the system"
})
public int COMPRESSION_LEVEL = 1;
@Comment("Number of days to keep history on disk before deleting it")