Add r/w lock around marker file operations and commands

This commit is contained in:
Mike Primm 2019-01-27 15:04:05 -06:00
parent e7113dc163
commit 648e11bb53

View File

@ -46,11 +46,13 @@ import org.dynmap.markers.PlayerSet;
import org.dynmap.markers.PolyLineMarker; import org.dynmap.markers.PolyLineMarker;
import org.dynmap.utils.BufferOutputStream; import org.dynmap.utils.BufferOutputStream;
import org.dynmap.web.Json; import org.dynmap.web.Json;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/** /**
* Implementation class for MarkerAPI - should not be called directly * Implementation class for MarkerAPI - should not be called directly
*/ */
public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> { public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private File markerpersist; private File markerpersist;
private File markerpersist_old; private File markerpersist_old;
private File markerdir; /* Local store for markers (internal) */ private File markerdir; /* Local store for markers (internal) */
@ -336,17 +338,22 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
public void run() { public void run() {
if(stop) if(stop)
return; return;
/* Write markers first - drives JSON updates too */ lock.readLock().lock();
if(dirty_markers) { try {
doSaveMarkers(); /* Write markers first - drives JSON updates too */
dirty_markers = false; if(dirty_markers) {
} doSaveMarkers();
/* Process any dirty worlds */ dirty_markers = false;
if(!dirty_worlds.isEmpty()) {
for(String world : dirty_worlds) {
writeMarkersFile(world);
} }
dirty_worlds.clear(); /* Process any dirty worlds */
if(!dirty_worlds.isEmpty()) {
for(String world : dirty_worlds) {
writeMarkersFile(world);
}
dirty_worlds.clear();
}
} finally {
lock.readLock().unlock();
} }
core.getServer().scheduleServerTask(this, 20); core.getServer().scheduleServerTask(this, 20);
} }
@ -412,17 +419,26 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
plugin.events.removeListener("worldactivated", api); plugin.events.removeListener("worldactivated", api);
stop = true; stop = true;
if(dirty_markers) { lock.readLock().lock();
doSaveMarkers(); try {
dirty_markers = false; if(dirty_markers) {
doSaveMarkers();
dirty_markers = false;
}
} finally {
lock.readLock().unlock();
}
lock.writeLock().lock();
try {
for(MarkerIconImpl icn : markericons.values())
icn.cleanup();
markericons.clear();
for(MarkerSetImpl set : markersets.values())
set.cleanup();
markersets.clear();
} finally {
lock.writeLock().unlock();
} }
for(MarkerIconImpl icn : markericons.values())
icn.cleanup();
markericons.clear();
for(MarkerSetImpl set : markersets.values())
set.cleanup();
markersets.clear();
} }
private MarkerIcon createBuiltinMarkerIcon(String id, String label) { private MarkerIcon createBuiltinMarkerIcon(String id, String label) {
@ -668,35 +684,39 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
private boolean loadMarkers() { private boolean loadMarkers() {
ConfigurationNode conf = new ConfigurationNode(api.markerpersist); /* Make configuration object */ ConfigurationNode conf = new ConfigurationNode(api.markerpersist); /* Make configuration object */
conf.load(); /* Load persistence */ conf.load(); /* Load persistence */
/* Get icons */ lock.writeLock().lock();
try {
ConfigurationNode icons = conf.getNode("icons"); /* Get icons */
if(icons == null) return false; ConfigurationNode icons = conf.getNode("icons");
for(String id : icons.keySet()) { if(icons == null) return false;
MarkerIconImpl ico = new MarkerIconImpl(id); for(String id : icons.keySet()) {
if(ico.loadPersistentData(icons.getNode(id))) { MarkerIconImpl ico = new MarkerIconImpl(id);
markericons.put(id, ico); if(ico.loadPersistentData(icons.getNode(id))) {
} markericons.put(id, ico);
}
/* Get marker sets */
ConfigurationNode sets = conf.getNode("sets");
if(sets != null) {
for(String id: sets.keySet()) {
MarkerSetImpl set = new MarkerSetImpl(id);
if(set.loadPersistentData(sets.getNode(id))) {
markersets.put(id, set);
} }
} }
} /* Get marker sets */
/* Get player sets */ ConfigurationNode sets = conf.getNode("sets");
ConfigurationNode psets = conf.getNode("playersets"); if(sets != null) {
if(psets != null) { for(String id: sets.keySet()) {
for(String id: psets.keySet()) { MarkerSetImpl set = new MarkerSetImpl(id);
PlayerSetImpl set = new PlayerSetImpl(id); if(set.loadPersistentData(sets.getNode(id))) {
if(set.loadPersistentData(sets.getNode(id))) { markersets.put(id, set);
playersets.put(id, set); }
} }
} }
/* Get player sets */
ConfigurationNode psets = conf.getNode("playersets");
if(psets != null) {
for(String id: psets.keySet()) {
PlayerSetImpl set = new PlayerSetImpl(id);
if(set.loadPersistentData(sets.getNode(id))) {
playersets.put(id, set);
}
}
}
} finally {
lock.writeLock().unlock();
} }
return true; return true;
@ -1104,131 +1124,142 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
if (!commands.contains(c)) { if (!commands.contains(c)) {
return false; return false;
} }
/* Process commands */ /* Process commands read commands */
if(c.equals("add") && api.core.checkPlayerPermission(sender, "marker.add")) { api.lock.readLock().lock();
return processAddMarker(plugin, sender, cmd, commandLabel, args, player); try {
/* List markers */
if(c.equals("list") && plugin.checkPlayerPermission(sender, "marker.list")) {
return processListMarker(plugin, sender, cmd, commandLabel, args);
}
/* List icons */
else if(c.equals("icons") && plugin.checkPlayerPermission(sender, "marker.icons")) {
return processListIcon(plugin, sender, cmd, commandLabel, args);
}
/* List sets */
else if(c.equals("listsets") && plugin.checkPlayerPermission(sender, "marker.listsets")) {
return processListSet(plugin, sender, cmd, commandLabel, args);
}
/* List areas */
else if(c.equals("listareas") && plugin.checkPlayerPermission(sender, "marker.listareas")) {
return processListArea(plugin, sender, cmd, commandLabel, args);
}
/* List poly-lines */
else if(c.equals("listlines") && plugin.checkPlayerPermission(sender, "marker.listlines")) {
return processListLine(plugin, sender, cmd, commandLabel, args);
}
/* List circles */
else if(c.equals("listcircles") && plugin.checkPlayerPermission(sender, "marker.listcircles")) {
return processListCircle(plugin, sender, cmd, commandLabel, args);
}
/* Get label for given item - must have ID and type parameter */
else if(c.equals("getlabel") && plugin.checkPlayerPermission(sender, "marker.getlabel")) {
return processGetLabel(plugin, sender, cmd, commandLabel, args);
}
} finally {
api.lock.readLock().unlock();
} }
/* Update position of bookmark - must have ID parameter */ // Handle modify commands
else if(c.equals("movehere") && plugin.checkPlayerPermission(sender, "marker.movehere")) { api.lock.writeLock().lock();
return processMoveHere(plugin, sender, cmd, commandLabel, args, player); try {
} if(c.equals("add") && api.core.checkPlayerPermission(sender, "marker.add")) {
/* Update other attributes of marker - must have ID parameter */ return processAddMarker(plugin, sender, cmd, commandLabel, args, player);
else if(c.equals("update") && plugin.checkPlayerPermission(sender, "marker.update")) { }
return processUpdateMarker(plugin, sender, cmd, commandLabel, args); /* Update position of bookmark - must have ID parameter */
} else if(c.equals("movehere") && plugin.checkPlayerPermission(sender, "marker.movehere")) {
/* Delete marker - must have ID parameter */ return processMoveHere(plugin, sender, cmd, commandLabel, args, player);
else if(c.equals("delete") && plugin.checkPlayerPermission(sender, "marker.delete")) { }
return processDeleteMarker(plugin, sender, cmd, commandLabel, args); /* Update other attributes of marker - must have ID parameter */
} else if(c.equals("update") && plugin.checkPlayerPermission(sender, "marker.update")) {
/* List markers */ return processUpdateMarker(plugin, sender, cmd, commandLabel, args);
else if(c.equals("list") && plugin.checkPlayerPermission(sender, "marker.list")) { }
return processListMarker(plugin, sender, cmd, commandLabel, args); /* Delete marker - must have ID parameter */
} else if(c.equals("delete") && plugin.checkPlayerPermission(sender, "marker.delete")) {
/* List icons */ return processDeleteMarker(plugin, sender, cmd, commandLabel, args);
else if(c.equals("icons") && plugin.checkPlayerPermission(sender, "marker.icons")) { }
return processListIcon(plugin, sender, cmd, commandLabel, args); else if(c.equals("addset") && plugin.checkPlayerPermission(sender, "marker.addset")) {
} return processAddSet(plugin, sender, cmd, commandLabel, args, player);
else if(c.equals("addset") && plugin.checkPlayerPermission(sender, "marker.addset")) { }
return processAddSet(plugin, sender, cmd, commandLabel, args, player); else if(c.equals("updateset") && plugin.checkPlayerPermission(sender, "marker.updateset")) {
} return processUpdateSet(plugin, sender, cmd, commandLabel, args);
else if(c.equals("updateset") && plugin.checkPlayerPermission(sender, "marker.updateset")) { }
return processUpdateSet(plugin, sender, cmd, commandLabel, args); else if(c.equals("deleteset") && plugin.checkPlayerPermission(sender, "marker.deleteset")) {
} return processDeleteSet(plugin, sender, cmd, commandLabel, args);
else if(c.equals("deleteset") && plugin.checkPlayerPermission(sender, "marker.deleteset")) { }
return processDeleteSet(plugin, sender, cmd, commandLabel, args); /* Add new icon */
} else if(c.equals("addicon") && plugin.checkPlayerPermission(sender, "marker.addicon")) {
/* List sets */ return processAddIcon(plugin, sender, cmd, commandLabel, args);
else if(c.equals("listsets") && plugin.checkPlayerPermission(sender, "marker.listsets")) { }
return processListSet(plugin, sender, cmd, commandLabel, args); else if(c.equals("updateicon") && plugin.checkPlayerPermission(sender, "marker.updateicon")) {
} return processUpdateIcon(plugin, sender, cmd, commandLabel, args);
/* Add new icon */ }
else if(c.equals("addicon") && plugin.checkPlayerPermission(sender, "marker.addicon")) { else if(c.equals("deleteicon") && plugin.checkPlayerPermission(sender, "marker.deleteicon")) {
return processAddIcon(plugin, sender, cmd, commandLabel, args); return processDeleteIcon(plugin, sender, cmd, commandLabel, args);
} }
else if(c.equals("updateicon") && plugin.checkPlayerPermission(sender, "marker.updateicon")) { /* Add point to accumulator */
return processUpdateIcon(plugin, sender, cmd, commandLabel, args); else if(c.equals("addcorner") && plugin.checkPlayerPermission(sender, "marker.addarea")) {
} return processAddCorner(plugin, sender, cmd, commandLabel, args, player);
else if(c.equals("deleteicon") && plugin.checkPlayerPermission(sender, "marker.deleteicon")) { }
return processDeleteIcon(plugin, sender, cmd, commandLabel, args); else if(c.equals("clearcorners") && plugin.checkPlayerPermission(sender, "marker.addarea")) {
} return processClearCorners(plugin, sender, cmd, commandLabel, args, player);
/* Add point to accumulator */ }
else if(c.equals("addcorner") && plugin.checkPlayerPermission(sender, "marker.addarea")) { else if(c.equals("addarea") && plugin.checkPlayerPermission(sender, "marker.addarea")) {
return processAddCorner(plugin, sender, cmd, commandLabel, args, player); return processAddArea(plugin, sender, cmd, commandLabel, args, player);
} }
else if(c.equals("clearcorners") && plugin.checkPlayerPermission(sender, "marker.addarea")) { /* Delete area - must have ID parameter */
return processClearCorners(plugin, sender, cmd, commandLabel, args, player); else if(c.equals("deletearea") && plugin.checkPlayerPermission(sender, "marker.deletearea")) {
} return processDeleteArea(plugin, sender, cmd, commandLabel, args);
else if(c.equals("addarea") && plugin.checkPlayerPermission(sender, "marker.addarea")) { }
return processAddArea(plugin, sender, cmd, commandLabel, args, player); /* Update other attributes of area - must have ID parameter */
} else if(c.equals("updatearea") && plugin.checkPlayerPermission(sender, "marker.updatearea")) {
/* List areas */ return processUpdateArea(plugin, sender, cmd, commandLabel, args);
else if(c.equals("listareas") && plugin.checkPlayerPermission(sender, "marker.listareas")) { }
return processListArea(plugin, sender, cmd, commandLabel, args); else if(c.equals("addline") && plugin.checkPlayerPermission(sender, "marker.addline")) {
} return processAddLine(plugin, sender, cmd, commandLabel, args, player);
/* Delete area - must have ID parameter */ }
else if(c.equals("deletearea") && plugin.checkPlayerPermission(sender, "marker.deletearea")) { /* Delete poly-line - must have ID parameter */
return processDeleteArea(plugin, sender, cmd, commandLabel, args); else if(c.equals("deleteline") && plugin.checkPlayerPermission(sender, "marker.deleteline")) {
} return processDeleteLine(plugin, sender, cmd, commandLabel, args);
/* Update other attributes of area - must have ID parameter */ }
else if(c.equals("updatearea") && plugin.checkPlayerPermission(sender, "marker.updatearea")) { /* Update other attributes of poly-line - must have ID parameter */
return processUpdateArea(plugin, sender, cmd, commandLabel, args); else if(c.equals("updateline") && plugin.checkPlayerPermission(sender, "marker.updateline")) {
} return processUpdateLine(plugin, sender, cmd, commandLabel, args);
else if(c.equals("addline") && plugin.checkPlayerPermission(sender, "marker.addline")) { }
return processAddLine(plugin, sender, cmd, commandLabel, args, player); else if(c.equals("addcircle") && plugin.checkPlayerPermission(sender, "marker.addcircle")) {
} return processAddCircle(plugin, sender, cmd, commandLabel, args, player);
/* List poly-lines */ }
else if(c.equals("listlines") && plugin.checkPlayerPermission(sender, "marker.listlines")) { /* Delete circle - must have ID parameter */
return processListLine(plugin, sender, cmd, commandLabel, args); else if(c.equals("deletecircle") && plugin.checkPlayerPermission(sender, "marker.deletecircle")) {
} return processDeleteCircle(plugin, sender, cmd, commandLabel, args);
/* Delete poly-line - must have ID parameter */ }
else if(c.equals("deleteline") && plugin.checkPlayerPermission(sender, "marker.deleteline")) { /* Update other attributes of circle - must have ID parameter */
return processDeleteLine(plugin, sender, cmd, commandLabel, args); else if(c.equals("updatecircle") && plugin.checkPlayerPermission(sender, "marker.updatecircle")) {
} return processUpdateCircle(plugin, sender, cmd, commandLabel, args);
/* Update other attributes of poly-line - must have ID parameter */ }
else if(c.equals("updateline") && plugin.checkPlayerPermission(sender, "marker.updateline")) { /* Get description for given item - must have ID and type parameter */
return processUpdateLine(plugin, sender, cmd, commandLabel, args); else if(c.equals("getdesc") && plugin.checkPlayerPermission(sender, "marker.getdesc")) {
} return processGetDesc(plugin, sender, cmd, commandLabel, args);
else if(c.equals("addcircle") && plugin.checkPlayerPermission(sender, "marker.addcircle")) { }
return processAddCircle(plugin, sender, cmd, commandLabel, args, player); /* Reset description for given item - must have ID and type parameter */
} else if(c.equals("resetdesc") && plugin.checkPlayerPermission(sender, "marker.resetdesc")) {
/* List circles */ return processResetDesc(plugin, sender, cmd, commandLabel, args);
else if(c.equals("listcircles") && plugin.checkPlayerPermission(sender, "marker.listcircles")) { }
return processListCircle(plugin, sender, cmd, commandLabel, args); /* Append to description for given item - must have ID and type parameter */
} else if(c.equals("appenddesc") && plugin.checkPlayerPermission(sender, "marker.appenddesc")) {
/* Delete circle - must have ID parameter */ return processAppendDesc(plugin, sender, cmd, commandLabel, args);
else if(c.equals("deletecircle") && plugin.checkPlayerPermission(sender, "marker.deletecircle")) { }
return processDeleteCircle(plugin, sender, cmd, commandLabel, args); /* Import description for given item from file - must have ID and type parameter */
} else if(c.equals("importdesc") && plugin.checkPlayerPermission(sender, "marker.importdesc")) {
/* Update other attributes of circle - must have ID parameter */ return processImportDesc(plugin, sender, cmd, commandLabel, args);
else if(c.equals("updatecircle") && plugin.checkPlayerPermission(sender, "marker.updatecircle")) { }
return processUpdateCircle(plugin, sender, cmd, commandLabel, args); /* Import description for given item from file - must have ID and type parameter */
} else if(c.equals("importlabel") && plugin.checkPlayerPermission(sender, "marker.importlabel")) {
/* Get description for given item - must have ID and type parameter */ return processImportLabel(plugin, sender, cmd, commandLabel, args);
else if(c.equals("getdesc") && plugin.checkPlayerPermission(sender, "marker.getdesc")) { }
return processGetDesc(plugin, sender, cmd, commandLabel, args); else {
} return false;
/* Reset description for given item - must have ID and type parameter */ }
else if(c.equals("resetdesc") && plugin.checkPlayerPermission(sender, "marker.resetdesc")) { } finally {
return processResetDesc(plugin, sender, cmd, commandLabel, args); api.lock.writeLock().unlock();
}
/* Append to description for given item - must have ID and type parameter */
else if(c.equals("appenddesc") && plugin.checkPlayerPermission(sender, "marker.appenddesc")) {
return processAppendDesc(plugin, sender, cmd, commandLabel, args);
}
/* Import description for given item from file - must have ID and type parameter */
else if(c.equals("importdesc") && plugin.checkPlayerPermission(sender, "marker.importdesc")) {
return processImportDesc(plugin, sender, cmd, commandLabel, args);
}
/* Import description for given item from file - must have ID and type parameter */
else if(c.equals("importlabel") && plugin.checkPlayerPermission(sender, "marker.importlabel")) {
return processImportLabel(plugin, sender, cmd, commandLabel, args);
}
/* Get label for given item - must have ID and type parameter */
else if(c.equals("getlabel") && plugin.checkPlayerPermission(sender, "marker.getlabel")) {
return processGetLabel(plugin, sender, cmd, commandLabel, args);
}
else {
return false;
} }
} }