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() {
      }
   }
}