Various minor

Fix NullExtent for heightmaps
auto dequeue the database and visualization tasks
This commit is contained in:
Jesse Boyd 2018-05-12 10:55:06 +10:00
parent fe17434d00
commit 2a7e111f46
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
6 changed files with 158 additions and 82 deletions

View File

@ -262,7 +262,7 @@ public class Fawe {
TaskManager.IMP.later(() -> {
try {
transformParser = new DefaultTransformParser(getWorldEdit());
visualQueue = new VisualQueue();
visualQueue = new VisualQueue(3);
WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers());
WEManager.IMP.managers.add(new PlotSquaredFeature());
Fawe.debug("Plugin 'PlotSquared' found. Using it now.");

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.task.SingleThreadNotifyQueue;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.Vector;
@ -22,7 +23,7 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
public class RollbackDatabase {
public class RollbackDatabase extends SingleThreadNotifyQueue {
private final String prefix;
private final File dbLocation;
@ -40,7 +41,7 @@ public class RollbackDatabase {
private String PURGE;
private ConcurrentLinkedQueue<RollbackOptimizedHistory> historyChanges = new ConcurrentLinkedQueue<>();
private ConcurrentLinkedQueue<Runnable> notify = new ConcurrentLinkedQueue<>();
private final ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue<>();
public RollbackDatabase(String world) throws SQLException, ClassNotFoundException {
this(FaweAPI.getWorld(world));
@ -62,28 +63,24 @@ public class RollbackDatabase {
DELETE_EDIT_USER = "DELETE FROM `" + prefix + "edits` WHERE `player`=? AND `id`=?";
init();
purge((int) TimeUnit.DAYS.toMillis(Settings.IMP.HISTORY.DELETE_AFTER_DAYS));
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
long last = System.currentTimeMillis();
while (true) {
if (connection == null) {
break;
}
if (!RollbackDatabase.this.sendBatch()) {
try {
while (!notify.isEmpty()) {
Runnable runnable = notify.poll();
runnable.run();
}
Thread.sleep(50);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public boolean hasQueued() {
return connection != null && (!historyChanges.isEmpty() || !tasks.isEmpty());
}
@Override
public void operate() {
synchronized (this) {
if (connection == null) {
return;
}
});
while (sendBatch()) {
// Still processing
}
}
}
public void init() {
@ -94,10 +91,6 @@ public class RollbackDatabase {
}
}
public void addFinishTask(Runnable run) {
notify.add(run);
}
public void delete(final UUID uuid, final int id) {
addTask(new Runnable() {
@Override
@ -186,16 +179,14 @@ public class RollbackDatabase {
}
public void logEdit(RollbackOptimizedHistory history) {
historyChanges.add(history);
queue(() -> historyChanges.add(history));
}
private final ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue<>();
public void addTask(Runnable run) {
this.tasks.add(run);
queue(() -> tasks.add(run));
}
public void runTasks() {
private void runTasks() {
Runnable task;
while ((task = tasks.poll()) != null) {
try {
@ -321,9 +312,14 @@ public class RollbackDatabase {
if (connection == null) {
return false;
}
connection.close();
connection = null;
return true;
synchronized (this) {
if (connection == null) {
return false;
}
connection.close();
connection = null;
return true;
}
}
/**

View File

@ -1,62 +1,35 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.object.task.SingleThreadIntervalQueue;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class VisualQueue {
public class VisualQueue extends SingleThreadIntervalQueue<FawePlayer> {
private ConcurrentHashMap<FawePlayer, Long> playerMap;
public VisualQueue(int interval) {
super(interval);
}
public VisualQueue() {
playerMap = new ConcurrentHashMap<>();
Runnable task = new Runnable() {
@Override
public void run() {
long allowedTick = Fawe.get().getTimer().getTick() - 1;
Iterator<Map.Entry<FawePlayer, Long>> iter = playerMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<FawePlayer, Long> entry = iter.next();
Long time = entry.getValue();
if (time < allowedTick) {
FawePlayer fp = entry.getKey();
iter.remove();
LocalSession session = fp.getSession();
Player player = fp.getPlayer();
Tool tool = session.getTool(player);
Brush brush;
if (tool instanceof BrushTool) {
BrushTool brushTool = (BrushTool) tool;
if (brushTool.getVisualMode() != VisualMode.NONE) {
try {
brushTool.visualize(BrushTool.BrushAction.PRIMARY, player);
} catch (Throwable e) {
WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player);
}
}
}
}
@Override
public void operate(FawePlayer fp) {
LocalSession session = fp.getSession();
Player player = fp.getPlayer();
Tool tool = session.getTool(player);
Brush brush;
if (tool instanceof BrushTool) {
BrushTool brushTool = (BrushTool) tool;
if (brushTool.getVisualMode() != VisualMode.NONE) {
try {
brushTool.visualize(BrushTool.BrushAction.PRIMARY, player);
} catch (Throwable e) {
WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player);
}
TaskManager.IMP.laterAsync(this, 3);
}
};
TaskManager.IMP.laterAsync(task, 3);
}
public boolean dequeue(FawePlayer player) {
return playerMap.remove(player) != null;
}
public void queue(FawePlayer player) {
playerMap.put(player, Fawe.get().getTimer().getTick());
}
}
}

View File

@ -123,6 +123,21 @@ public class NullExtent extends FaweRegionExtent {
return null;
}
@Override
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
throw new FaweException(reason);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
throw new FaweException(reason);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
throw new FaweException(reason);
}
@Override
public Extent getExtent() {
return this;

View File

@ -0,0 +1,55 @@
package com.boydti.fawe.object.task;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TaskManager;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class SingleThreadIntervalQueue<T> {
private final ConcurrentHashMap<T, Long> objMap = new ConcurrentHashMap<>();
private final Runnable task;
private AtomicBoolean queued = new AtomicBoolean();
public SingleThreadIntervalQueue(int interval) {
this.task = new Runnable() {
@Override
public void run() {
long allowedTick = Fawe.get().getTimer().getTick() - 1;
Iterator<Map.Entry<T, Long>> iter = objMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<T, Long> entry = iter.next();
Long time = entry.getValue();
if (time < allowedTick) {
T obj = entry.getKey();
iter.remove();
operate(obj);
}
}
synchronized (objMap) {
if (!objMap.isEmpty()) TaskManager.IMP.laterAsync(this, interval);
else queued.set(false);
}
}
};
}
public abstract void operate(T obj);
public boolean dequeue(T obj) {
synchronized (objMap) {
return objMap.remove(obj) != null;
}
}
public void queue(T obj) {
synchronized (objMap) {
objMap.put(obj, Fawe.get().getTimer().getTick());
if (!queued.get()) {
queued.set(true);
TaskManager.IMP.laterAsync(task, 3);
}
}
}
}

View File

@ -0,0 +1,37 @@
package com.boydti.fawe.object.task;
import com.boydti.fawe.util.TaskManager;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class SingleThreadNotifyQueue {
private Object lock = new Object();
private final Runnable task;
private final AtomicBoolean running = new AtomicBoolean();
public SingleThreadNotifyQueue() {
this.task = new Runnable() {
@Override
public void run() {
operate();
synchronized (lock) {
if (hasQueued()) TaskManager.IMP.async(this);
else running.set(false);
}
}
};
}
public abstract boolean hasQueued();
public void queue(Runnable queueTask) {
synchronized (lock) {
queueTask.run();
if (!running.get()) {
running.set(true);
TaskManager.IMP.async(task);
}
}
}
public abstract void operate();
}