Sorting / Tweaks / Fixes

Fixes #499
Add sortPlotsByTimestamp method to PS
tweak to debugexec
This commit is contained in:
boy0001 2015-08-04 00:54:35 +10:00
parent b0859b250a
commit 0a0c72bc7d
8 changed files with 284 additions and 41 deletions

View File

@ -543,6 +543,181 @@ public class PS {
return result; return result;
} }
public static ArrayList<Plot> sortPlotsByTimestamp(Collection<Plot> input) {
List<Plot> list;
if (input instanceof ArrayList<?>) {
list = (List<Plot>) input;
}
else {
list = new ArrayList<Plot>(input);
}
long min = Integer.MAX_VALUE;
long max = 0;
int size = list.size();
int limit = Math.min(1048576, size * 2);
for (int i = 0; i < size; i++) {
Plot plot = list.get(i);
long time = plot.getTimestamp();
if (time < min) {
min = time;
}
if (time > max) {
max = time;
}
}
long range = max - min;
Plot[] plots;
try {
ArrayList<Plot> overflow = new ArrayList<>();
if (range > limit && size > 1024) {
plots = new Plot[Math.min((int) range, limit)];
int factor = (int) ((range / limit));
for (int i = 0; i < size; i++) {
Plot plot = list.get(i);
int index = (int) (plot.getTimestamp() - min) / factor;
if (index < 0) {
index = 0;
}
if (index >= plots.length) {
overflow.add(plot);
continue;
}
Plot current = plots[index];
while (true) {
if (current == null) {
plots[index] = plot;
break;
}
if (current.getTimestamp() > plot.getTimestamp()) {
plots[index] = plot;
plot = current;
}
index++;
if (index >= plots.length) {
overflow.add(plot);
break;
}
current = plots[index];
}
}
}
else if (range < size || size < 1024) {
ArrayList<Plot> result = new ArrayList<Plot>(list);
Collections.sort(result, new Comparator<Plot>() {
@Override
public int compare(Plot a, Plot b) {
if (a.getTimestamp() > b.getTimestamp()) {
return -1;
}
else if (b.getTimestamp() > a.getTimestamp()) {
return 1;
}
return 0;
}
});
return result;
}
else if (min != 0) {
plots = new Plot[(int) range];
for (int i = 0; i < size; i++) {
Plot plot = list.get(i);
int index = (int) (plot.getTimestamp() - min);
if (index >= plots.length) {
overflow.add(plot);
continue;
}
Plot current = plots[index];
while (true) {
if (current == null) {
plots[index] = plot;
break;
}
if (current.getTimestamp() > plot.getTimestamp()) {
plots[index] = plot;
plot = current;
}
index++;
if (index >= plots.length) {
overflow.add(plot);
break;
}
current = plots[index];
}
}
}
else {
plots = new Plot[(int) range];
for (int i = 0; i < size; i++) {
Plot plot = list.get(i);
int index = (int) (plot.getTimestamp());
if (index >= plots.length) {
overflow.add(plot);
continue;
}
Plot current = plots[index];
// Move everything along until a free spot is found
while (true) {
if (current == null) {
plots[index] = plot;
break;
}
if (current.getTimestamp() > plot.getTimestamp()) {
plots[index] = plot;
plot = current;
}
index++;
if (index >= plots.length) {
overflow.add(plot);
break;
}
current = plots[index];
}
}
}
ArrayList<Plot> result = new ArrayList<>(size);
if (overflow.size() > 0) {
Collections.sort(overflow, new Comparator<Plot>() {
@Override
public int compare(Plot a, Plot b) {
if (a.getTimestamp() > b.getTimestamp()) {
return -1;
}
else if (b.getTimestamp() > a.getTimestamp()) {
return 1;
}
return 0;
}
});
for (Plot plot : overflow) {
result.add(plot);
}
}
for (int i = plots.length - 1; i >= 0; i--) {
if (plots[i] != null) {
result.add(plots[i]);
}
}
return result;
}
catch (Exception e) {
e.printStackTrace();
ArrayList<Plot> result = new ArrayList<Plot>(list);
Collections.sort(result, new Comparator<Plot>() {
@Override
public int compare(Plot a, Plot b) {
if (a.getTimestamp() > b.getTimestamp()) {
return -1;
}
else if (b.getTimestamp() > a.getTimestamp()) {
return 1;
}
return 0;
}
});
return result;
}
}
public static void sortPlotsByHash(Plot[] input) { public static void sortPlotsByHash(Plot[] input) {
final int SIZE = 100; final int SIZE = 100;
List<Plot>[] bucket = new ArrayList[SIZE]; List<Plot>[] bucket = new ArrayList[SIZE];
@ -571,6 +746,34 @@ public class PS {
} }
} }
public static void sortPlotsByTimestamp(Plot[] input) {
final int SIZE = 100;
List<Plot>[] bucket = new ArrayList[SIZE];
for (int i = 0; i < bucket.length; i++) {
bucket[i] = new ArrayList<Plot>();
}
boolean maxLength = false;
int tmp = -1, placement = 1;
while (!maxLength) {
maxLength = true;
for (Plot i : input) {
tmp = MathMan.getPositiveId(i.hashCode()) / placement;
bucket[tmp % SIZE].add(i);
if (maxLength && tmp > 0) {
maxLength = false;
}
}
int a = 0;
for (int b = 0; b < SIZE; b++) {
for (Plot i : bucket[b]) {
input[a++] = i;
}
bucket[b].clear();
}
placement *= SIZE;
}
}
/** /**
* Sort a collection of plots by world (with a priority world), then by hashcode * Sort a collection of plots by world (with a priority world), then by hashcode
* @param plots * @param plots
@ -613,7 +816,7 @@ public class PS {
Collections.sort(worlds, new Comparator<String>() { Collections.sort(worlds, new Comparator<String>() {
@Override @Override
public int compare(String a, String b) { public int compare(String a, String b) {
if (StringMan.isEqual(a, priorityWorld)) { if (priorityWorld != null && StringMan.isEqual(a, priorityWorld)) {
return -1; return -1;
} }
return a.hashCode() - b.hashCode(); return a.hashCode() - b.hashCode();

View File

@ -92,7 +92,10 @@ public class DebugExec extends SubCommand {
if (engine != null) { if (engine != null) {
return; return;
} }
engine = (new ScriptEngineManager()).getEngineByName("JavaScript"); engine = (new ScriptEngineManager()).getEngineByName("nashorn");
if (engine == null) {
engine = (new ScriptEngineManager()).getEngineByName("JavaScript");
}
ScriptContext context = new SimpleScriptContext(); ScriptContext context = new SimpleScriptContext();
scope = context.getBindings(ScriptContext.ENGINE_SCOPE); scope = context.getBindings(ScriptContext.ENGINE_SCOPE);
@ -128,21 +131,14 @@ public class DebugExec extends SubCommand {
scope.put("MainCommand", MainCommand.getInstance()); scope.put("MainCommand", MainCommand.getInstance());
// enums // enums
for (Enum value : C.values()) { for (Enum<?> value : C.values()) {
scope.put("C_" + value.name(), value); scope.put("C_" + value.name(), value);
} }
for (Enum value : Permissions.values()) { for (Enum<?> value : Permissions.values()) {
scope.put("Permissions_" + value.name(), value); scope.put("Permissions_" + value.name(), value);
} }
addEnums(scope, C.values());
} }
private void addEnums(Bindings scope2, C[] values) {
// TODO Auto-generated method stub
}
@Override @Override
public boolean onCommand(final PlotPlayer player, String[] args) { public boolean onCommand(final PlotPlayer player, String[] args) {
final List<String> allowed_params = Arrays.asList("calibrate-analysis", "remove-flag", "stop-expire", "start-expire", "show-expired", "update-expired", "seen", "trim-check"); final List<String> allowed_params = Arrays.asList("calibrate-analysis", "remove-flag", "stop-expire", "start-expire", "show-expired", "update-expired", "seen", "trim-check");

View File

@ -40,7 +40,7 @@ import com.plotsquared.general.commands.CommandDeclaration;
permission = "plots.delete", permission = "plots.delete",
description = "Delete a plot", description = "Delete a plot",
usage = "/plot delete", usage = "/plot delete",
aliases = "dispose", aliases = {"dispose", "del"},
category = CommandCategory.ACTIONS, category = CommandCategory.ACTIONS,
requiredType = RequiredType.NONE requiredType = RequiredType.NONE
) )

View File

@ -62,7 +62,7 @@ public class SetOwner extends SubCommand {
public boolean onCommand(final PlotPlayer plr, final String[] args) { public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation(); final Location loc = plr.getLocation();
final Plot plot = MainUtil.getPlot(loc); final Plot plot = MainUtil.getPlot(loc);
if ((plot == null) || (plot.owner == null)) { if ((plot == null) || (plot.owner == null && !Permissions.hasPermission(plr, "plots.admin.command.setowner"))) {
MainUtil.sendMessage(plr, C.NOT_IN_PLOT); MainUtil.sendMessage(plr, C.NOT_IN_PLOT);
return false; return false;
} }
@ -107,10 +107,17 @@ public class SetOwner extends SubCommand {
return false; return false;
} }
for (final PlotId id : plots) { for (final PlotId id : plots) {
final Plot current = PS.get().getPlots(world).get(id); Plot current = PS.get().getPlots(world).get(id);
current.owner = uuid; if (current == null) {
current = MainUtil.getPlot(world, id);
current.owner = uuid;
current.create();
}
else {
current.owner = uuid;
DBFunc.setOwner(current, current.owner);
}
PS.get().updatePlot(current); PS.get().updatePlot(current);
DBFunc.setOwner(current, current.owner);
} }
MainUtil.setSign(args[0], plot); MainUtil.setSign(args[0], plot);
MainUtil.sendMessage(plr, C.SET_OWNER); MainUtil.sendMessage(plr, C.SET_OWNER);

View File

@ -67,10 +67,10 @@ public class Visit extends SubCommand {
UUID user = UUIDHandler.getCachedUUID(args[0], null); UUID user = UUIDHandler.getCachedUUID(args[0], null);
if (user != null ) { if (user != null ) {
// do plots by username // do plots by username
plots.addAll(PS.get().getPlots(user)); plots = PS.get().sortPlots(PS.get().getPlots(user), null);
} else if (PS.get().isPlotWorld(args[0])) { } else if (PS.get().isPlotWorld(args[0])) {
// do plots by world // do plots by world
plots.addAll(PS.get().getPlots(args[0]).values()); plots = PS.get().sortPlots(PS.get().getPlots(args[0]).values(), null);
} }
else { else {
Plot plot = MainUtil.getPlotFromString(plr, args[0], true); Plot plot = MainUtil.getPlotFromString(plr, args[0], true);

View File

@ -303,12 +303,7 @@ public class list extends SubCommand {
public void displayPlots(PlotPlayer player, List<Plot> plots, int pageSize, int page, String world, String[] args, boolean sort) { public void displayPlots(PlotPlayer player, List<Plot> plots, int pageSize, int page, String world, String[] args, boolean sort) {
if (sort) { if (sort) {
if (world != null) { plots = PS.get().sortPlots(plots, world);
plots = PS.get().sortPlots(plots, world);
}
else {
plots = PS.get().sortPlots(plots);
}
} }
if (page < 0) { if (page < 0) {
page = 0; page = 0;

View File

@ -84,10 +84,10 @@ public class SQLManager implements AbstractDB {
// Public final // Public final
this.SET_OWNER = "UPDATE `" + this.prefix + "plot` SET `owner` = ? WHERE `plot_id_x` = ? AND `plot_id_z` = ? AND `world` = ?"; this.SET_OWNER = "UPDATE `" + this.prefix + "plot` SET `owner` = ? WHERE `plot_id_x` = ? AND `plot_id_z` = ? AND `world` = ?";
this.GET_ALL_PLOTS = "SELECT `id`, `plot_id_x`, `plot_id_z`, `world` FROM `" + this.prefix + "plot`"; this.GET_ALL_PLOTS = "SELECT `id`, `plot_id_x`, `plot_id_z`, `world` FROM `" + this.prefix + "plot`";
this.CREATE_PLOTS = "INSERT INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`) values "; this.CREATE_PLOTS = "INSERT INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) values ";
this.CREATE_SETTINGS = "INSERT INTO `" + this.prefix + "plot_settings` (`plot_plot_id`) values "; this.CREATE_SETTINGS = "INSERT INTO `" + this.prefix + "plot_settings` (`plot_plot_id`) values ";
this.CREATE_TIERS = "INSERT INTO `" + this.prefix + "plot_%tier%` (`plot_plot_id`, `user_uuid`) values "; this.CREATE_TIERS = "INSERT INTO `" + this.prefix + "plot_%tier%` (`plot_plot_id`, `user_uuid`) values ";
this.CREATE_PLOT = "INSERT INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`) VALUES(?, ?, ?, ?)"; this.CREATE_PLOT = "INSERT INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) VALUES(?, ?, ?, ?, ?)";
this.CREATE_CLUSTER = "INSERT INTO `" + this.prefix + "cluster`(`pos1_x`, `pos1_z`, `pos2_x`, `pos2_z`, `owner`, `world`) VALUES(?, ?, ?, ?, ?, ?)"; this.CREATE_CLUSTER = "INSERT INTO `" + this.prefix + "cluster`(`pos1_x`, `pos1_z`, `pos2_x`, `pos2_z`, `owner`, `world`) VALUES(?, ?, ?, ?, ?, ?)";
// schedule reconnect // schedule reconnect
if (Settings.DB.USE_MYSQL) { if (Settings.DB.USE_MYSQL) {
@ -296,7 +296,7 @@ public class SQLManager implements AbstractDB {
final StmtMod<Plot> mod = new StmtMod<Plot>() { final StmtMod<Plot> mod = new StmtMod<Plot>() {
@Override @Override
public String getCreateMySQL(int size) { public String getCreateMySQL(int size) {
return getCreateMySQL(size, CREATE_PLOTS, 4); return getCreateMySQL(size, CREATE_PLOTS, 5);
} }
@Override @Override
@ -311,14 +311,15 @@ public class SQLManager implements AbstractDB {
@Override @Override
public void setMySQL(PreparedStatement stmt, int i, Plot plot) throws SQLException { public void setMySQL(PreparedStatement stmt, int i, Plot plot) throws SQLException {
stmt.setInt((i * 4) + 1, plot.id.x); stmt.setInt((i * 5) + 1, plot.id.x);
stmt.setInt((i * 4) + 2, plot.id.y); stmt.setInt((i * 5) + 2, plot.id.y);
try { try {
stmt.setString((i * 4) + 3, plot.owner.toString()); stmt.setString((i * 4) + 3, plot.owner.toString());
} catch (final Exception e) { } catch (final Exception e) {
stmt.setString((i * 4) + 3, DBFunc.everyone.toString()); stmt.setString((i * 4) + 3, DBFunc.everyone.toString());
} }
stmt.setString((i * 4) + 4, plot.world); stmt.setString((i * 5) + 4, plot.world);
stmt.setTimestamp((i * 5) + 5, new Timestamp(plot.getTimestamp()));
} }
@Override @Override
@ -332,7 +333,7 @@ public class SQLManager implements AbstractDB {
stmt.setString((i * 6) + 4, DBFunc.everyone.toString()); stmt.setString((i * 6) + 4, DBFunc.everyone.toString());
} }
stmt.setString((i * 6) + 5, plot.world); stmt.setString((i * 6) + 5, plot.world);
stmt.setString((i * 6) + 6, System.currentTimeMillis() + ""); stmt.setTimestamp((i * 6) + 6, new Timestamp(plot.getTimestamp()));
} }
@Override @Override
@ -341,6 +342,8 @@ public class SQLManager implements AbstractDB {
stmt.setInt(2, plot.id.y); stmt.setInt(2, plot.id.y);
stmt.setString(3, plot.owner.toString()); stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.world); stmt.setString(4, plot.world);
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
} }
}; };
setBulk(myList, mod, whenDone); setBulk(myList, mod, whenDone);
@ -642,6 +645,7 @@ public class SQLManager implements AbstractDB {
stmt.setInt(2, plot.id.y); stmt.setInt(2, plot.id.y);
stmt.setString(3, plot.owner.toString()); stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.world); stmt.setString(4, plot.world);
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
stmt.executeUpdate(); stmt.executeUpdate();
stmt.close(); stmt.close();
} catch (final Exception e) { } catch (final Exception e) {
@ -664,6 +668,7 @@ public class SQLManager implements AbstractDB {
stmt.setInt(2, plot.id.y); stmt.setInt(2, plot.id.y);
stmt.setString(3, plot.owner.toString()); stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.world); stmt.setString(4, plot.world);
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
stmt.executeUpdate(); stmt.executeUpdate();
stmt.close(); stmt.close();
final int id = getId(plot.world, plot.id); final int id = getId(plot.world, plot.id);
@ -879,13 +884,13 @@ public class SQLManager implements AbstractDB {
for (String table : new String[]{"plot_denied", "plot_helpers", "plot_trusted"} ) { for (String table : new String[]{"plot_denied", "plot_helpers", "plot_trusted"} ) {
ResultSet result = statement.executeQuery("SELECT plot_plot_id, user_uuid, COUNT(*) FROM " + this.prefix + table + " GROUP BY plot_plot_id, user_uuid HAVING COUNT(*) > 1"); ResultSet result = statement.executeQuery("SELECT plot_plot_id, user_uuid, COUNT(*) FROM " + this.prefix + table + " GROUP BY plot_plot_id, user_uuid HAVING COUNT(*) > 1");
if (result.next()) { if (result.next()) {
PS.debug("BACKING UP: " + table); PS.debug("BACKING UP: " + this.prefix + table);
result.close(); result.close();
statement.executeUpdate("CREATE TABLE " + table + "_tmp AS SELECT * FROM " + this.prefix + table + " GROUP BY plot_plot_id, user_uuid"); statement.executeUpdate("CREATE TABLE " + this.prefix + table + "_tmp AS SELECT * FROM " + this.prefix + table + " GROUP BY plot_plot_id, user_uuid");
statement.executeUpdate("DROP TABLE " + this.prefix + table); statement.executeUpdate("DROP TABLE " + this.prefix + table);
statement.executeUpdate("CREATE TABLE " + this.prefix + table + " AS SELECT * FROM " + table + "_tmp"); statement.executeUpdate("CREATE TABLE " + this.prefix + table + " AS SELECT * FROM " + this.prefix + table + "_tmp");
statement.executeUpdate("DROP TABLE " + this.prefix + table + "_tmp"); statement.executeUpdate("DROP TABLE " + this.prefix + table + "_tmp");
PS.debug("RESTORING: " + table); PS.debug("RESTORING: " + this.prefix + table);
} }
} }
statement.close(); statement.close();
@ -919,7 +924,7 @@ public class SQLManager implements AbstractDB {
* Getting plots * Getting plots
*/ */
stmt = this.connection.createStatement(); stmt = this.connection.createStatement();
ResultSet r = stmt.executeQuery("SELECT `id`, `plot_id_x`, `plot_id_z`, `owner`, `world` FROM `" + this.prefix + "plot`"); ResultSet r = stmt.executeQuery("SELECT `id`, `plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp` FROM `" + this.prefix + "plot`");
PlotId plot_id; PlotId plot_id;
int id; int id;
Plot p; Plot p;
@ -942,7 +947,15 @@ public class SQLManager implements AbstractDB {
user = UUID.fromString(o); user = UUID.fromString(o);
uuids.put(o, user); uuids.put(o, user);
} }
p = new Plot(plot_id, user, new HashSet<UUID>(), new HashSet<UUID>(), new HashSet<UUID>(), "", null, null, worldname, new boolean[]{false, false, false, false}); Timestamp timestamp = r.getTimestamp("timestamp");
long time;
if (timestamp == null) {
time = plot_id.hashCode();
}
else {
time = timestamp.getTime();
}
p = new Plot(plot_id, user, new HashSet<UUID>(), new HashSet<UUID>(), new HashSet<UUID>(), "", null, null, worldname, new boolean[]{false, false, false, false}, time);
plots.put(id, p); plots.put(id, p);
} }
if (Settings.CACHE_RATINGS) { if (Settings.CACHE_RATINGS) {

View File

@ -48,17 +48,30 @@ import com.intellectualcrafters.plot.util.TaskManager;
public class Plot { public class Plot {
/** /**
* plot ID * plot ID
* Direct access is Deprecated: use getId()
*/ */
@Deprecated
public final PlotId id; public final PlotId id;
/** /**
* plot world * plot world
* Direct access is Deprecated: use getWorld()
*/ */
@Deprecated
public final String world; public final String world;
/** /**
* plot owner * plot owner
* Direct access is Deprecated: use getOwners()
*/ */
@Deprecated
public UUID owner; public UUID owner;
/**
* Plot creation timestamp (rough)
* Direct access is Deprecated: use getTimestamp()
*/
@Deprecated
public long timestamp;
/** /**
* List of trusted (with plot permissions) * List of trusted (with plot permissions)
* Direct access is Deprecated: use getTrusted() * Direct access is Deprecated: use getTrusted()
@ -132,10 +145,11 @@ public class Plot {
* @param denied * @param denied
* @param merged * @param merged
*/ */
public Plot(final PlotId id, final UUID owner, final HashSet<UUID> trusted, final HashSet<UUID> members, final HashSet<UUID> denied, final String alias, final BlockLoc position, final Collection<Flag> flags, final String world, final boolean[] merged) { public Plot(final PlotId id, final UUID owner, final HashSet<UUID> trusted, final HashSet<UUID> members, final HashSet<UUID> denied, final String alias, final BlockLoc position, final Collection<Flag> flags, final String world, final boolean[] merged, final long timestamp) {
this.id = id; this.id = id;
this.settings = new PlotSettings(this); this.world = world;
this.owner = owner; this.owner = owner;
this.settings = new PlotSettings(this);
this.members = members; this.members = members;
this.trusted = trusted; this.trusted = trusted;
this.denied = denied; this.denied = denied;
@ -147,7 +161,7 @@ public class Plot {
this.settings.flags.put(flag.getKey(), flag); this.settings.flags.put(flag.getKey(), flag);
} }
} }
this.world = world; this.timestamp = timestamp;
this.temp = false; this.temp = false;
} }
@ -201,7 +215,7 @@ public class Plot {
public boolean isDenied(final UUID uuid) { public boolean isDenied(final UUID uuid) {
return (this.getDenied() != null) && ((this.denied.contains(DBFunc.everyone) && !this.isAdded(uuid)) || (!this.isAdded(uuid) && this.denied.contains(uuid))); return (this.getDenied() != null) && ((this.denied.contains(DBFunc.everyone) && !this.isAdded(uuid)) || (!this.isAdded(uuid) && this.denied.contains(uuid)));
} }
/** /**
* Get the plot ID * Get the plot ID
*/ */
@ -209,6 +223,14 @@ public class Plot {
return this.id; return this.id;
} }
/**
* Get the world
* @return
*/
public String getWorld() {
return this.world;
}
/** /**
* Get or create plot settings * Get or create plot settings
* @return PlotSettings * @return PlotSettings
@ -227,6 +249,13 @@ public class Plot {
return settings.getMerged(0) || settings.getMerged(2) || settings.getMerged(1) || settings.getMerged(3); return settings.getMerged(0) || settings.getMerged(2) || settings.getMerged(1) || settings.getMerged(3);
} }
public long getTimestamp() {
if (timestamp == 0) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
/** /**
* Get if the plot is merged in a direction * Get if the plot is merged in a direction
* @param direction * @param direction