From 002d0eb720d1d92893a9a3c100033601507541cc Mon Sep 17 00:00:00 2001 From: Xzavier0722 Date: Tue, 16 Jan 2024 15:05:04 +0800 Subject: [PATCH] feat(controller): add clear world data if --- .../storage/controller/ADataController.java | 12 +++++ .../controller/BlockDataController.java | 51 ++++++++++++++++++- .../storage/controller/SlimefunChunkData.java | 4 ++ .../storage/task/QueuedWriteTask.java | 13 ++++- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java index a18b5e55e2..ca9b67a09d 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataController.java @@ -164,6 +164,11 @@ protected void scheduleReadTask(Runnable run) { readExecutor.submit(run); } + protected void scheduleWriteTask(Runnable run) { + checkDestroy(); + writeExecutor.submit(run); + } + protected List getData(RecordKey key) { return getData(key, false); } @@ -180,6 +185,13 @@ protected void deleteData(RecordKey key) { dataAdapter.deleteData(key); } + protected void abortScopeTask(ScopeKey key) { + var task = scheduledWriteTasks.remove(key); + if (task != null) { + task.abort(); + } + } + public final DataType getDataType() { return dataType; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 35da58c937..de18caa5e5 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -537,9 +537,56 @@ public Set getAllLoadedChunkData() { return new HashSet<>(loadedChunk.values()); } - public void clearWorldData(World world) { - // 1. remove cache + public void removeAllDataInWorld(World world) { + // 1. remove block cache + var loadedBlockData = new HashSet(); + for (var chunkData : getAllLoadedChunkData(world)) { + loadedBlockData.addAll(chunkData.getAllBlockData()); + chunkData.removeAllCacheInternal(); + } + + // 2. remove ticker and delayed tasks + for (var blockData : loadedBlockData) { + if (Slimefun.getRegistry().getTickerBlocks().contains(blockData.getSfId())) { + Slimefun.getTickerTask().disableTicker(blockData.getLocation()); + } + + var scopeKey = new LocationKey(DataScope.NONE, blockData.getLocation()); + removeDelayedBlockDataUpdates(scopeKey); + abortScopeTask(scopeKey); + } + + // 3. remove from database + var prefix = world.getName() + ";"; + var condition = prefix + "%"; + var req = new RecordKey(DataScope.BLOCK_DATA); + req.addCondition(FieldKey.CHUNK, condition); + deleteData(req); + + req = new RecordKey(DataScope.CHUNK_DATA); + req.addCondition(FieldKey.CHUNK, condition); + deleteData(req); + + // 4. remove chunk cache + loadedChunk.entrySet().removeIf(entry -> entry.getKey().startsWith(prefix)); + } + public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) { + scheduleWriteTask(() -> { + removeAllDataInWorld(world); + onFinishedCallback.run(); + }); + } + + public Set getAllLoadedChunkData(World world) { + var prefix = world.getName() + ";"; + var re = new HashSet(); + loadedChunk.forEach((k, v) -> { + if (k.startsWith(prefix)) { + re.add(v); + } + }); + return re; } private void scheduleDelayedBlockInvUpdate(SlimefunBlockData blockData, int slot) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java index 1999e2d0de..9dadc5afd0 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java @@ -94,6 +94,10 @@ Set getAllCacheInternal() { return re; } + void removeAllCacheInternal() { + sfBlocks.clear(); + } + boolean hasBlockCache(String lKey) { return sfBlocks.containsKey(lKey); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/QueuedWriteTask.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/QueuedWriteTask.java index bd87ff9ca7..6074b36877 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/QueuedWriteTask.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/task/QueuedWriteTask.java @@ -10,11 +10,16 @@ public class QueuedWriteTask implements Runnable { private final Queue queue = new LinkedList<>(); private final Map tasks = new HashMap<>(); private volatile boolean done = false; + private volatile boolean aborted = false; @Override public final void run() { + if (aborted) { + return; + } + var task = next(); - while (task != null) { + while (!aborted && task != null) { try { task.run(); } catch (Throwable e) { @@ -35,7 +40,7 @@ protected void onSuccess() {} protected void onError(Throwable e) {} public synchronized boolean queue(RecordKey key, Runnable next) { - if (done) { + if (done || aborted) { return false; } @@ -45,6 +50,10 @@ public synchronized boolean queue(RecordKey key, Runnable next) { return true; } + public void abort() { + aborted = true; + } + private synchronized Runnable next() { var key = queue.poll(); if (key == null) {