CachedEntry class
Пакет: com.hypixel.hytale.server.core.prefab.selection.buffer
Файл: com/hypixel/hytale/server/core/prefab/selection/buffer/PrefabBufferUtil.java
Поля (2)
| Модификаторы | Тип | Имя |
|---|---|---|
|
private PrefabBuffer |
buffer |
|
private final StampedLock |
lock |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.prefab.selection.buffer;
class="kw">import com.hypixel.hytale.assetstore.AssetPack;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.logger.sentry.SkipSentryException;
class="kw">import com.hypixel.hytale.server.core.Options;
class="kw">import com.hypixel.hytale.server.core.asset.AssetModule;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.IPrefabBuffer;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.PrefabBuffer;
class="kw">import com.hypixel.hytale.server.core.util.BsonUtil;
class="kw">import com.hypixel.hytale.server.core.util.io.FileUtil;
class="kw">import com.hypixel.hytale.sneakythrow.SneakyThrow;
class="kw">import java.io.BufferedOutputStream;
class="kw">import java.io.DataOutputStream;
class="kw">import java.io.IOException;
class="kw">import java.lang.ref.WeakReference;
class="kw">import java.nio.ByteBuffer;
class="kw">import java.nio.file.Files;
class="kw">import java.nio.file.Path;
class="kw">import java.nio.file.attribute.BasicFileAttributes;
class="kw">import java.nio.file.attribute.FileTime;
class="kw">import java.util.Map;
class="kw">import java.util.Set;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.CompletionException;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.locks.StampedLock;
class="kw">import java.util.logging.Level;
class="kw">import java.util.regex.Pattern;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">public class PrefabBufferUtil {
class="kw">public class="kw">static class="kw">final Path CACHE_PATH = Options.getOrDefault(Options.PREFAB_CACHE_DIRECTORY, Options.getOptionSet(), Path.of(".cache/prefabs"));
class="kw">public class="kw">static class="kw">final String LPF_FILE_SUFFIX = ".lpf";
class="kw">public class="kw">static class="kw">final String JSON_FILE_SUFFIX = ".prefab.json";
class="kw">public class="kw">static class="kw">final String JSON_LPF_FILE_SUFFIX = ".prefab.json.lpf";
class="kw">public class="kw">static class="kw">final String FILE_SUFFIX_REGEX = "((?<!\\.prefab\\.json)\\.lpf|\\.prefab\\.json)$";
class="kw">public class="kw">static class="kw">final Pattern FILE_SUFFIX_PATTERN = Pattern.compile("((?<!\\.prefab\\.json)\\.lpf|\\.prefab\\.json)$");
class="kw">public class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
class="kw">private class="kw">static class="kw">final Map<Path, WeakReference<PrefabBufferUtil.CachedEntry>> CACHE = new ConcurrentHashMap<>();
class="kw">private class="kw">static class="kw">final Set<Path> SAVING_PREFABS = ConcurrentHashMap.newKeySet();
class="kw">public PrefabBufferUtil() {
}
@Nonnull
class="kw">public class="kw">static IPrefabBuffer getCached(@Nonnull Path var0) {
WeakReference var1 = CACHE.get(var0);
PrefabBufferUtil.CachedEntry var2 = var1 != null ? var1.get() : null;
if (var2 != null) {
long var3 = var2.lock.readLock();
try {
if (var2.buffer != null) {
class="kw">return var2.buffer.newAccess();
}
} class="kw">finally {
var2.lock.unlockRead(var3);
}
}
var2 = getOrCreateCacheEntry(var0);
long var15 = var2.lock.writeLock();
try {
if (var2.buffer != null) {
class="kw">return var2.buffer.newAccess();
}
var2.buffer = loadBuffer(var0);
class="kw">return var2.buffer.newAccess();
} class="kw">finally {
var2.lock.unlockWrite(var15);
}
}
class="kw">public class="kw">static void removeCached(@Nonnull Path var0) {
CACHE.remove(var0);
}
@Nonnull
class="kw">public class="kw">static PrefabBuffer loadBuffer(@Nonnull Path var0) {
String var1 = var0.getFileName().toString();
String var2 = var1.replace(".prefab.json.lpf", "").replace(".prefab.json", "");
if (var2.endsWith(".lpf")) {
var2 = var2.substring(0, var2.length() - ".lpf".length());
}
String var3 = var2;
Path var4 = var0.resolveSibling(var3 + ".lpf");
if (Files.exists(var4)) {
class="kw">return loadFromLPF(var0, var4);
}
Path var5;
AssetPack var6;
if (AssetModule.get().isAssetPathImmutable(var0)) {
Path var7 = var0.resolveSibling(var3 + ".prefab.json.lpf");
if (Files.exists(var7)) {
class="kw">return loadFromLPF(var0, var7);
}
var6 = AssetModule.get().findAssetPackForPath(var0);
if (var6 != null) {
String var8 = FileUtil.INVALID_FILENAME_CHARACTERS.matcher(var6.getName()).replaceAll("_");
var5 = CACHE_PATH.resolve(var8).resolve(var6.getRoot().relativize(var7).toString());
} else if (var7.getRoot() != null) {
var5 = CACHE_PATH.resolve(var7.subpath(1, var7.getNameCount()).toString());
} else {
var5 = CACHE_PATH.resolve(var7.toString());
}
} else {
var5 = var0.resolveSibling(var3 + ".prefab.json.lpf");
var6 = null;
}
Path var11 = var0.resolveSibling(var3 + ".prefab.json");
if (!Files.exists(var11)) {
try {
Files.deleteIfExists(var5);
} catch (IOException var9) {
}
throw new Error("Error loading Prefab from " + var11.toAbsolutePath() + " (.lpf and .prefab.json) File NOT found!");
} else {
try {
class="kw">return loadFromJson(var6, var0, var5, var11);
} catch (IOException var10) {
throw SneakyThrow.sneakyThrow(var10);
}
}
}
@Nonnull
class="kw">public class="kw">static CompletableFuture<Void> writeToFileAsync(@Nonnull PrefabBuffer var0, @Nonnull Path var1) {
class="kw">return CompletableFuture.runAsync(SneakyThrow.sneakyRunnable(() -> {
Path var2 = var1.resolveSibling(var1.getFileName() + ".tmp");
try (DataOutputStream var3 = new DataOutputStream(new BufferedOutputStream(Files.newOutputStream(var2)))) {
BinaryPrefabBufferCodec.INSTANCE.serialize(var0, var3);
}
FileUtil.atomicMove(var2, var1);
}));
}
class="kw">public class="kw">static PrefabBuffer readFromFile(@Nonnull Path var0) {
class="kw">return readFromFileAsync(var0).join();
}
@Nonnull
class="kw">public class="kw">static CompletableFuture<PrefabBuffer> readFromFileAsync(@Nonnull Path var0) {
class="kw">return CompletableFuture.supplyAsync(SneakyThrow.sneakySupplier(() -> {
byte[] var1 = Files.readAllBytes(var0);
class="kw">return BinaryPrefabBufferCodec.INSTANCE.deserialize(ByteBuffer.wrap(var1));
}));
}
@Nonnull
class="kw">public class="kw">static PrefabBuffer loadFromLPF(@Nonnull Path var0, @Nonnull Path var1) {
try {
class="kw">return readFromFile(var1);
} catch (Exception var3) {
throw new Error("Error while loading prefab " + var0.toAbsolutePath() + " from " + var1.toAbsolutePath(), var3);
}
}
@Nonnull
class="kw">public class="kw">static PrefabBuffer loadFromJson(@Nullable AssetPack var0, Path var1, @Nonnull Path var2, @Nonnull Path var3) class="kw">throws IOException {
BasicFileAttributes var4 = null;
try {
var4 = Files.readAttributes(var2, BasicFileAttributes.class);
} catch (IOException var12) {
}
FileTime var5;
if (var0 != null && var0.isImmutable()) {
var5 = Files.readAttributes(var0.getPackLocation(), BasicFileAttributes.class).lastModifiedTime();
} else {
var5 = Files.readAttributes(var3, BasicFileAttributes.class).lastModifiedTime();
}
if (var4 != null && var5.compareTo(var4.lastModifiedTime()) <= 0) {
try {
class="kw">return readFromFile(var2);
} catch (CompletionException var13) {
if (!Options.getOptionSet().has(Options.VALIDATE_PREFABS)) {
if (var13.getCause() class="kw">instanceof UpdateBinaryPrefabException) {
LOGGER.at(Level.FINE).log("Ignoring LPF %s due to: %s", var1, var13.getMessage());
} else {
((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(new SkipSentryException(var13))).log("Failed to load %s", var2);
}
}
}
}
try {
PrefabBuffer var6 = BsonPrefabBufferDeserializer.INSTANCE.deserialize(var3, BsonUtil.readDocument(var3, false).join());
Path var7 = var1.normalize();
if (!Options.getOptionSet().has(Options.DISABLE_CPB_BUILD) && SAVING_PREFABS.add(var7)) {
try {
Files.createDirectories(var2.getParent());
writeToFileAsync(var6, var2)
.thenRun(() -> {
try {
Files.setLastModifiedTime(var2, var5);
} catch (IOException var3x) {
}
})
.exceptionally(
var1x -> {
((HytaleLogger.Api)HytaleLogger.getLogger().at(Level.FINE).withCause(new SkipSentryException(var1x)))
.log("Failed to save prefab cache %s", var2);
class="kw">return null;
}
)
.whenComplete((var1x, var2x) -> SAVING_PREFABS.remove(var7));
} catch (IOException var9) {
LOGGER.at(Level.FINE).log("Cannot create cache directory for %s: %s", var2, var9.getMessage());
SAVING_PREFABS.remove(var7);
} catch (Throwable var10) {
SAVING_PREFABS.remove(var7);
throw var10;
}
}
class="kw">return var6;
} catch (Exception var11) {
throw new Error("Error while loading Prefab from " + var3.toAbsolutePath(), var11);
}
}
@Nonnull
class="kw">private class="kw">static PrefabBufferUtil.CachedEntry getOrCreateCacheEntry(Path var0) {
PrefabBufferUtil.CachedEntry[] var1 = new PrefabBufferUtil.CachedEntry[1];
CACHE.compute(var0, (var1x, var2) -> {
if (var2 != null) {
PrefabBufferUtil.CachedEntry var3 = var2.get();
var1[0] = var3;
if (var3 != null) {
class="kw">return var2;
}
}
class="kw">return new WeakReference<>(var1[0] = new PrefabBufferUtil.CachedEntry());
});
class="kw">return var1[0];
}
class="kw">private class="kw">static class CachedEntry {
class="kw">private class="kw">final StampedLock lock = new StampedLock();
class="kw">private PrefabBuffer buffer;
class="kw">private CachedEntry() {
}
}
}