From 0c98279ef1a2bae2168ce0b3a7b8228e552f687b Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Fri, 12 Apr 2024 13:49:22 +0000 Subject: [PATCH] Rewrite linear region flush task dispatching --- ...linear-region-flush-task-dispatching.patch | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 patches/server/0064-Rewrite-linear-region-flush-task-dispatching.patch diff --git a/patches/server/0064-Rewrite-linear-region-flush-task-dispatching.patch b/patches/server/0064-Rewrite-linear-region-flush-task-dispatching.patch new file mode 100644 index 0000000..f5dfafa --- /dev/null +++ b/patches/server/0064-Rewrite-linear-region-flush-task-dispatching.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Fri, 12 Apr 2024 13:48:09 +0000 +Subject: [PATCH] Rewrite linear region flush task dispatching + + +diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java +index e40989889f3821bb7484fc0bae5d94b033013904..dc5a5f42c9ca7a50295c18424722568a3ad33fa5 100644 +--- a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java ++++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java +@@ -126,7 +126,7 @@ public class LinearRegionFile implements AbstractRegionFile, AutoCloseable { + } + + public void flush() throws IOException { +- if (isMarkedToSave()) flushWrapper(); // sync ++ if (getAndResetSaveMarker()) flushWrapper(); // sync + } + + private void markToSave() { +@@ -134,10 +134,18 @@ public class LinearRegionFile implements AbstractRegionFile, AutoCloseable { + markedToSave.set(true); + } + +- public boolean isMarkedToSave() { ++ public boolean getAndResetSaveMarker() { + return markedToSave.getAndSet(false); + } + ++ public boolean isMarkedToSave(){ ++ return this.markedToSave.get(); ++ } ++ ++ public void resetSaveMarker(){ ++ this.markedToSave.set(false); ++ } ++ + public void flushWrapper() { + try { + save(); +diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java +index f06d7767c79e465f999b2032086cc224de95152a..65435eb666b2e1cabffc145e016faa5e3b373464 100644 +--- a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java ++++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java +@@ -1,17 +1,14 @@ + package dev.kaiijumc.kaiiju.region; + + import com.google.common.util.concurrent.ThreadFactoryBuilder; +-import java.util.Queue; ++ ++import java.util.Set; + import java.util.concurrent.*; + import org.bukkit.Bukkit; + + public class LinearRegionFileFlusher { +- private final Queue savingQueue = new LinkedBlockingQueue<>(); +- private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor( +- new ThreadFactoryBuilder() +- .setNameFormat("linear-flush-scheduler") +- .build() +- ); ++ private final Set pendingSaving = ConcurrentHashMap.newKeySet(); ++ + private final ExecutorService executor = Executors.newFixedThreadPool( + me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushThreads, + new ThreadFactoryBuilder() +@@ -19,26 +16,42 @@ public class LinearRegionFileFlusher { + .build() + ); + ++ private final Executor delayedFlusher = CompletableFuture.delayedExecutor( ++ me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushFrequency, ++ TimeUnit.SECONDS, ++ executor ++ ); ++ + public LinearRegionFileFlusher() { + Bukkit.getLogger().info("Using " + me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushThreads + " threads for linear region flushing."); +- scheduler.scheduleAtFixedRate(this::pollAndFlush, 0L, me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushFrequency, TimeUnit.SECONDS); + } + + public void scheduleSave(LinearRegionFile regionFile) { +- if (savingQueue.contains(regionFile)) return; +- savingQueue.add(regionFile); +- } +- +- private void pollAndFlush() { +- while (!savingQueue.isEmpty()) { +- LinearRegionFile regionFile = savingQueue.poll(); +- if (!regionFile.closed && regionFile.isMarkedToSave()) +- executor.execute(regionFile::flushWrapper); ++ if (this.pendingSaving.contains(regionFile) || !regionFile.isMarkedToSave()){ ++ return; + } ++ ++ this.pendingSaving.add(regionFile); ++ this.delayedFlusher.execute(()->{ ++ try { ++ if (!regionFile.closed && regionFile.isMarkedToSave()){ ++ regionFile.flushWrapper(); ++ } ++ }finally { ++ regionFile.resetSaveMarker(); ++ this.pendingSaving.remove(regionFile); ++ } ++ }); + } + + public void shutdown() { +- executor.shutdown(); +- scheduler.shutdown(); ++ this.executor.shutdown(); ++ for (;;) { ++ try { ++ if (this.executor.awaitTermination(5_00,TimeUnit.MILLISECONDS)) break; ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ } ++ } + } + }