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;
}
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) {
final int SIZE = 100;
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
* @param plots
@ -613,7 +816,7 @@ public class PS {
Collections.sort(worlds, new Comparator<String>() {
@Override
public int compare(String a, String b) {
if (StringMan.isEqual(a, priorityWorld)) {
if (priorityWorld != null && StringMan.isEqual(a, priorityWorld)) {
return -1;
}
return a.hashCode() - b.hashCode();

View File

@ -92,7 +92,10 @@ public class DebugExec extends SubCommand {
if (engine != null) {
return;
}
engine = (new ScriptEngineManager()).getEngineByName("JavaScript");
engine = (new ScriptEngineManager()).getEngineByName("nashorn");
if (engine == null) {
engine = (new ScriptEngineManager()).getEngineByName("JavaScript");
}
ScriptContext context = new SimpleScriptContext();
scope = context.getBindings(ScriptContext.ENGINE_SCOPE);
@ -128,21 +131,14 @@ public class DebugExec extends SubCommand {
scope.put("MainCommand", MainCommand.getInstance());
// enums
for (Enum value : C.values()) {
for (Enum<?> value : C.values()) {
scope.put("C_" + value.name(), value);
}
for (Enum value : Permissions.values()) {
for (Enum<?> value : Permissions.values()) {
scope.put("Permissions_" + value.name(), value);
}
addEnums(scope, C.values());
}
private void addEnums(Bindings scope2, C[] values) {
// TODO Auto-generated method stub
}
@Override
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");

View File

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

View File

@ -62,7 +62,7 @@ public class SetOwner extends SubCommand {
public boolean onCommand(final PlotPlayer plr, final String[] args) {
final Location loc = plr.getLocation();
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);
return false;
}
@ -107,10 +107,17 @@ public class SetOwner extends SubCommand {
return false;
}
for (final PlotId id : plots) {
final Plot current = PS.get().getPlots(world).get(id);
current.owner = uuid;
Plot current = PS.get().getPlots(world).get(id);
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);
DBFunc.setOwner(current, current.owner);
}
MainUtil.setSign(args[0], plot);
MainUtil.sendMessage(plr, C.SET_OWNER);

View File

@ -67,10 +67,10 @@ public class Visit extends SubCommand {
UUID user = UUIDHandler.getCachedUUID(args[0], null);
if (user != null ) {
// 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])) {
// do plots by world
plots.addAll(PS.get().getPlots(args[0]).values());
plots = PS.get().sortPlots(PS.get().getPlots(args[0]).values(), null);
}
else {
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) {
if (sort) {
if (world != null) {
plots = PS.get().sortPlots(plots, world);
}
else {
plots = PS.get().sortPlots(plots);
}
plots = PS.get().sortPlots(plots, world);
}
if (page < 0) {
page = 0;

View File

@ -84,10 +84,10 @@ public class SQLManager implements AbstractDB {
// Public final
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.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_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(?, ?, ?, ?, ?, ?)";
// schedule reconnect
if (Settings.DB.USE_MYSQL) {
@ -296,7 +296,7 @@ public class SQLManager implements AbstractDB {
final StmtMod<Plot> mod = new StmtMod<Plot>() {
@Override
public String getCreateMySQL(int size) {
return getCreateMySQL(size, CREATE_PLOTS, 4);
return getCreateMySQL(size, CREATE_PLOTS, 5);
}
@Override
@ -311,14 +311,15 @@ public class SQLManager implements AbstractDB {
@Override
public void setMySQL(PreparedStatement stmt, int i, Plot plot) throws SQLException {
stmt.setInt((i * 4) + 1, plot.id.x);
stmt.setInt((i * 4) + 2, plot.id.y);
stmt.setInt((i * 5) + 1, plot.id.x);
stmt.setInt((i * 5) + 2, plot.id.y);
try {
stmt.setString((i * 4) + 3, plot.owner.toString());
} catch (final Exception e) {
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
@ -332,7 +333,7 @@ public class SQLManager implements AbstractDB {
stmt.setString((i * 6) + 4, DBFunc.everyone.toString());
}
stmt.setString((i * 6) + 5, plot.world);
stmt.setString((i * 6) + 6, System.currentTimeMillis() + "");
stmt.setTimestamp((i * 6) + 6, new Timestamp(plot.getTimestamp()));
}
@Override
@ -341,6 +342,8 @@ public class SQLManager implements AbstractDB {
stmt.setInt(2, plot.id.y);
stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.world);
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
}
};
setBulk(myList, mod, whenDone);
@ -642,6 +645,7 @@ public class SQLManager implements AbstractDB {
stmt.setInt(2, plot.id.y);
stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.world);
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
stmt.executeUpdate();
stmt.close();
} catch (final Exception e) {
@ -664,6 +668,7 @@ public class SQLManager implements AbstractDB {
stmt.setInt(2, plot.id.y);
stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.world);
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
stmt.executeUpdate();
stmt.close();
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"} ) {
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()) {
PS.debug("BACKING UP: " + table);
PS.debug("BACKING UP: " + this.prefix + table);
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("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");
PS.debug("RESTORING: " + table);
PS.debug("RESTORING: " + this.prefix + table);
}
}
statement.close();
@ -919,7 +924,7 @@ public class SQLManager implements AbstractDB {
* Getting plots
*/
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;
int id;
Plot p;
@ -942,7 +947,15 @@ public class SQLManager implements AbstractDB {
user = UUID.fromString(o);
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);
}
if (Settings.CACHE_RATINGS) {

View File

@ -48,17 +48,30 @@ import com.intellectualcrafters.plot.util.TaskManager;
public class Plot {
/**
* plot ID
* Direct access is Deprecated: use getId()
*/
@Deprecated
public final PlotId id;
/**
* plot world
* Direct access is Deprecated: use getWorld()
*/
@Deprecated
public final String world;
/**
* plot owner
* Direct access is Deprecated: use getOwners()
*/
@Deprecated
public UUID owner;
/**
* Plot creation timestamp (rough)
* Direct access is Deprecated: use getTimestamp()
*/
@Deprecated
public long timestamp;
/**
* List of trusted (with plot permissions)
* Direct access is Deprecated: use getTrusted()
@ -132,10 +145,11 @@ public class Plot {
* @param denied
* @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.settings = new PlotSettings(this);
this.world = world;
this.owner = owner;
this.settings = new PlotSettings(this);
this.members = members;
this.trusted = trusted;
this.denied = denied;
@ -147,7 +161,7 @@ public class Plot {
this.settings.flags.put(flag.getKey(), flag);
}
}
this.world = world;
this.timestamp = timestamp;
this.temp = false;
}
@ -201,7 +215,7 @@ public class Plot {
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)));
}
/**
* Get the plot ID
*/
@ -209,6 +223,14 @@ public class Plot {
return this.id;
}
/**
* Get the world
* @return
*/
public String getWorld() {
return this.world;
}
/**
* Get or create plot settings
* @return PlotSettings
@ -227,6 +249,13 @@ public class Plot {
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
* @param direction