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,29 +63,25 @@ 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 @Override
public void run() { public boolean hasQueued() {
long last = System.currentTimeMillis(); return connection != null && (!historyChanges.isEmpty() || !tasks.isEmpty());
while (true) { }
@Override
public void operate() {
synchronized (this) {
if (connection == null) { if (connection == null) {
break; return;
} }
if (!RollbackDatabase.this.sendBatch()) { while (sendBatch()) {
try { // Still processing
while (!notify.isEmpty()) {
Runnable runnable = notify.poll();
runnable.run();
}
Thread.sleep(50);
} catch (final InterruptedException e) {
e.printStackTrace();
} }
} }
} }
}
});
}
public void init() { public void init() {
try (PreparedStatement stmt = connection.prepareStatement(CREATE_TABLE)) { try (PreparedStatement stmt = connection.prepareStatement(CREATE_TABLE)) {
@ -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 {
@ -318,6 +309,10 @@ public class RollbackDatabase {
* @throws java.sql.SQLException if the connection cannot be closed * @throws java.sql.SQLException if the connection cannot be closed
*/ */
public boolean closeConnection() throws SQLException { public boolean closeConnection() throws SQLException {
if (connection == null) {
return false;
}
synchronized (this) {
if (connection == null) { if (connection == null) {
return false; return false;
} }
@ -325,6 +320,7 @@ public class RollbackDatabase {
connection = null; connection = null;
return true; return true;
} }
}
/** /**
* Checks if a connection is open with the database * Checks if a connection is open with the database

View File

@ -1,35 +1,22 @@
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() {
playerMap = new ConcurrentHashMap<>();
Runnable task = new Runnable() {
@Override @Override
public void run() { public void operate(FawePlayer fp) {
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(); LocalSession session = fp.getSession();
Player player = fp.getPlayer(); Player player = fp.getPlayer();
Tool tool = session.getTool(player); Tool tool = session.getTool(player);
@ -45,18 +32,4 @@ public class VisualQueue {
} }
} }
} }
}
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();
}