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

View File

@ -1,62 +1,35 @@
package com.boydti.fawe.object.brush.visualization; package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer; 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.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player; 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() { @Override
playerMap = new ConcurrentHashMap<>(); public void operate(FawePlayer fp) {
Runnable task = new Runnable() { LocalSession session = fp.getSession();
@Override Player player = fp.getPlayer();
public void run() { Tool tool = session.getTool(player);
long allowedTick = Fawe.get().getTimer().getTick() - 1; Brush brush;
Iterator<Map.Entry<FawePlayer, Long>> iter = playerMap.entrySet().iterator(); if (tool instanceof BrushTool) {
while (iter.hasNext()) { BrushTool brushTool = (BrushTool) tool;
Map.Entry<FawePlayer, Long> entry = iter.next(); if (brushTool.getVisualMode() != VisualMode.NONE) {
Long time = entry.getValue(); try {
if (time < allowedTick) { brushTool.visualize(BrushTool.BrushAction.PRIMARY, player);
FawePlayer fp = entry.getKey(); } catch (Throwable e) {
iter.remove(); WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player);
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; 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 @Override
public Extent getExtent() { public Extent getExtent() {
return this; 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();
}