Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 1.19.0 #153

Merged
merged 2 commits into from
Dec 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@
<!-- Non-minecraft related dependencies -->
<powermock.version>2.0.9</powermock.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.16.1-R0.1-SNAPSHOT</spigot.version>
<spigot.version>1.16.5-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.18.0-SNAPSHOT</bentobox.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>1.18.1</build.version>
<build.version>1.19.0</build.version>
<sonar.projectKey>BentoBoxWorld_Limits</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
Expand Down
151 changes: 151 additions & 0 deletions src/main/java/world/bentobox/limits/calculators/Pipeliner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package world.bentobox.limits.calculators;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;

import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.limits.Limits;
import world.bentobox.limits.calculators.Results.Result;

/**
* A pipeliner that will process one island at a time
* @author tastybento
*
*/
public class Pipeliner {

private static final int START_DURATION = 10; // 10 seconds
private static final int CONCURRENT_COUNTS = 1;
private final Queue<RecountCalculator> toProcessQueue;
private final Map<RecountCalculator, Long> inProcessQueue;
private final BukkitTask task;
private final Limits addon;
private long time;
private long count;

/**
* Construct the pipeliner
*/
public Pipeliner(Limits addon) {
this.addon = addon;
toProcessQueue = new ConcurrentLinkedQueue<>();
inProcessQueue = new HashMap<>();
// Loop continuously - check every tick if there is an island to scan
task = Bukkit.getScheduler().runTaskTimer(BentoBox.getInstance(), () -> {
if (!BentoBox.getInstance().isEnabled()) {
cancel();
return;
}
// Complete the current to Process queue first
if (!inProcessQueue.isEmpty() || toProcessQueue.isEmpty()) return;
for (int j = 0; j < CONCURRENT_COUNTS && !toProcessQueue.isEmpty(); j++) {
RecountCalculator iD = toProcessQueue.poll();
// Ignore deleted or unonwed islands
if (!iD.getIsland().isDeleted() && !iD.getIsland().isUnowned()) {
inProcessQueue.put(iD, System.currentTimeMillis());
// Start the scanning of a island with the first chunk
scanIsland(iD);
}
}
}, 1L, 10L);
}

private void cancel() {
task.cancel();
}

/**
* @return number of islands currently in the queue or in process
*/
public int getIslandsInQueue() {
return inProcessQueue.size() + toProcessQueue.size();
}

/**
* Scans one chunk of an island and adds the results to a results object
* @param iD
*/
private void scanIsland(RecountCalculator iD) {
if (iD.getIsland().isDeleted() || iD.getIsland().isUnowned() || task.isCancelled()) {
// Island is deleted, so finish early with nothing
inProcessQueue.remove(iD);
iD.getR().complete(null);
return;
}
iD.scanIsland(this);
}


/**
* Adds an island to the scanning queue but only if the island is not already in the queue
* @param island - the island to scan
* @return CompletableFuture of the results. Results will be null if the island is already in the queue
*/
public CompletableFuture<Results> addIsland(Island island) {
// Check if queue already contains island
if (inProcessQueue.keySet().parallelStream().map(RecountCalculator::getIsland).anyMatch(island::equals)
|| toProcessQueue.parallelStream().map(RecountCalculator::getIsland).anyMatch(island::equals)) {
return CompletableFuture.completedFuture(new Results(Result.IN_PROGRESS));
}
return addToQueue(island);
}

private CompletableFuture<Results> addToQueue(Island island) {
CompletableFuture<Results> r = new CompletableFuture<>();
toProcessQueue.add(new RecountCalculator(addon, island, r));
count++;
return r;
}

/**
* Get the average time it takes to run a level check
* @return the average time in seconds
*/
public int getTime() {
return time == 0 || count == 0 ? START_DURATION : (int)((double)time/count/1000);
}

/**
* Submit how long a level check took
* @param time the time to set
*/
public void setTime(long time) {
// Running average
this.time += time;
}

/**
* Stop the current queue.
*/
public void stop() {
addon.log("Stopping Level queue");
task.cancel();
this.inProcessQueue.clear();
this.toProcessQueue.clear();
}

/**
* @return the inProcessQueue
*/
protected Map<RecountCalculator, Long> getInProcessQueue() {
return inProcessQueue;
}

/**
* @return the task
*/
protected BukkitTask getTask() {
return task;
}




}
Loading