From e6b1308590098db40ea346c8d2412d02dcdb35bc Mon Sep 17 00:00:00 2001 From: Jordan Date: Sat, 15 Jul 2023 16:40:52 +0100 Subject: [PATCH] feat: synchronise disk clipboard loading and deletion to clipboardLock (#2342) - another possible help towards the OverlappingFileLockException --- .../com/fastasyncworldedit/core/Fawe.java | 1 - .../com/sk89q/worldedit/LocalSession.java | 57 +++++++++++++++++++ .../com/sk89q/worldedit/entity/Player.java | 35 +----------- 3 files changed, 59 insertions(+), 34 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index eb7eaf8ce..b4d2816c3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -449,7 +449,6 @@ public class Fawe { * @return Executor used for clipboard IO if clipboard on disk is enabled or null * @since 2.6.2 */ - @Nullable public KeyQueuedExecutorService getClipboardExecutor() { return this.clipboardExecutor; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index dfa29a2e3..3391bad80 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -23,8 +23,10 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.ResettableExtent; +import com.fastasyncworldedit.core.extent.clipboard.DiskOptimizedClipboard; import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder; import com.fastasyncworldedit.core.history.DiskStorageHistory; +import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismatchException; import com.fastasyncworldedit.core.internal.io.FaweInputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; import com.fastasyncworldedit.core.limit.FaweLimit; @@ -50,6 +52,8 @@ import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Locatable; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.ChangeSetExecutor; @@ -93,6 +97,7 @@ import java.util.ListIterator; import java.util.Objects; import java.util.TimeZone; import java.util.UUID; +import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -877,6 +882,58 @@ public class LocalSession implements TextureHolder { } } } + + /** + * Load a clipboard from disk and into this localsession. Synchronises with other clipboard setting/getting to and from + * this session + * + * @param file Clipboard file to load + * @throws FaweClipboardVersionMismatchException in clipboard version mismatch (between saved and internal, expected, version) + * @throws ExecutionException if the computation threw an exception + * @throws InterruptedException if the current thread was interrupted while waiting + */ + public void loadClipboardFromDisk(File file) throws FaweClipboardVersionMismatchException, ExecutionException, + InterruptedException { + synchronized (clipboardLock) { + if (file.exists() && file.length() > 5) { + try { + if (getClipboard() != null) { + return; + } + } catch (EmptyClipboardException ignored) { + } + DiskOptimizedClipboard doc = Fawe.instance().getClipboardExecutor().submit( + uuid, + () -> DiskOptimizedClipboard.loadFromFile(file) + ).get(); + Clipboard clip = doc.toClipboard(); + ClipboardHolder holder = new ClipboardHolder(clip); + setClipboard(holder); + } + } + } + + public void deleteClipboardOnDisk() { + synchronized (clipboardLock) { + ClipboardHolder holder = getExistingClipboard(); + if (holder != null) { + for (Clipboard clipboard : holder.getClipboards()) { + DiskOptimizedClipboard doc; + if (clipboard instanceof DiskOptimizedClipboard) { + doc = (DiskOptimizedClipboard) clipboard; + } else if (clipboard instanceof BlockArrayClipboard && ((BlockArrayClipboard) clipboard).getParent() instanceof DiskOptimizedClipboard) { + doc = (DiskOptimizedClipboard) ((BlockArrayClipboard) clipboard).getParent(); + } else { + continue; + } + Fawe.instance().getClipboardExecutor().submit(uuid, () -> { + doc.close(); // Ensure closed before deletion + doc.getFile().delete(); + }); + } + } + } + } //FAWE end /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java index 8f5b5cb53..277d755b1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java @@ -426,23 +426,7 @@ public interface Player extends Entity, Actor { cancel(true); LocalSession session = getSession(); if (Settings.settings().CLIPBOARD.USE_DISK && Settings.settings().CLIPBOARD.DELETE_ON_LOGOUT) { - ClipboardHolder holder = session.getExistingClipboard(); - if (holder != null) { - for (Clipboard clipboard : holder.getClipboards()) { - DiskOptimizedClipboard doc; - if (clipboard instanceof DiskOptimizedClipboard) { - doc = (DiskOptimizedClipboard) clipboard; - } else if (clipboard instanceof BlockArrayClipboard && ((BlockArrayClipboard) clipboard).getParent() instanceof DiskOptimizedClipboard) { - doc = (DiskOptimizedClipboard) ((BlockArrayClipboard) clipboard).getParent(); - } else { - continue; - } - Fawe.instance().getClipboardExecutor().submit(getUniqueId(), () -> { - doc.close(); // Ensure closed before deletion - doc.getFile().delete(); - }); - } - } + session.deleteClipboardOnDisk(); } else if (Settings.settings().CLIPBOARD.USE_DISK) { Fawe.instance().getClipboardExecutor().submit(getUniqueId(), () -> session.setClipboard(null)); } else if (Settings.settings().CLIPBOARD.DELETE_ON_LOGOUT) { @@ -464,22 +448,7 @@ public interface Player extends Entity, Actor { Settings.settings().PATHS.CLIPBOARD + File.separator + getUniqueId() + ".bd" ); try { - if (file.exists() && file.length() > 5) { - LocalSession session = getSession(); - try { - if (session.getClipboard() != null) { - return; - } - } catch (EmptyClipboardException ignored) { - } - DiskOptimizedClipboard doc = Fawe.instance().getClipboardExecutor().submit( - getUniqueId(), - () -> DiskOptimizedClipboard.loadFromFile(file) - ).get(); - Clipboard clip = doc.toClipboard(); - ClipboardHolder holder = new ClipboardHolder(clip); - session.setClipboard(holder); - } + getSession().loadClipboardFromDisk(file); } catch (FaweClipboardVersionMismatchException e) { print(e.getComponent()); } catch (RuntimeException e) {