BlockState-DB Migration: Import from CreativeControl

Limit-Config: Remove button/level default
This commit is contained in:
Jascha Starke 2013-10-15 23:09:28 +02:00
parent 9eba342758
commit 2957233fbf
6 changed files with 179 additions and 23 deletions

View file

@ -187,10 +187,12 @@ public class BlockStateCommand extends BukkitCommand implements IHelpDescribed {
* Imports BlockState Data from a given Database to the current active Database. * Imports BlockState Data from a given Database to the current active Database.
* A Server-Restart is needed after migration! * A Server-Restart is needed after migration!
* Parameters: * Parameters:
* -u --update Don't delete existing records / only overwrite if newer * -u --update Don't delete existing records / only overwrite if newer
* --import=<type> Import from other Plugins. Supported Types:
* cc CreativeControl
*/ */
@IsCommand("migrate") @IsCommand("migrate")
@Usages("-u <dsn> [username] [password]") @Usages("-u --import=cc <dsn> [username] [password]")
public boolean migrateDatabase(final CommandContext context, String... args) throws CommandException, MissingPermissionCommandException { public boolean migrateDatabase(final CommandContext context, String... args) throws CommandException, MissingPermissionCommandException {
DefinedParameterParser params = new DefinedParameterParser(args, new String[]{"debug", "d", "update", "u", "confirm"}); DefinedParameterParser params = new DefinedParameterParser(args, new String[]{"debug", "d", "update", "u", "confirm"});
if (params.getArgumentCount() < 1) {// doesn't count parameters if (params.getArgumentCount() < 1) {// doesn't count parameters
@ -219,19 +221,31 @@ public class BlockStateCommand extends BukkitCommand implements IHelpDescribed {
return true; return true;
} }
if (!params.getFlags().contains("confirm")) { DatabaseMigrationThread thread;
context.responseFormatted(ChatFormattings.INFO, L("command.blockstate.migrate_confirm", "--confirm")); if (params.getParameter("import") != null) {
return true; if (params.getParameter("import").equals("cc")) {
thread = new CreativeControlImportThread(mod, context, source, target);
} else {
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migrate_importtype_error", params.getParameter("import")));
return false;
}
} else {
thread = new DatabaseMigrationThread(mod, context, source, target);
} }
mod.getModuleEntry().disable();
DatabaseMigrationThread thread = new DatabaseMigrationThread(mod, context, source, target);
if (params.getFlags().contains("update") || params.getFlags().contains("u")) { if (params.getFlags().contains("update") || params.getFlags().contains("u")) {
thread.setMode(DatabaseMigrationThread.Mode.UPDATE); thread.setMode(DatabaseMigrationThread.Mode.UPDATE);
} }
if (params.getFlags().contains("debug") || params.getFlags().contains("d")) { if (params.getFlags().contains("debug") || params.getFlags().contains("d")) {
thread.setDebug(true); thread.setDebug(true);
} }
if (!params.getFlags().contains("confirm")) {
context.responseFormatted(ChatFormattings.INFO, L("command.blockstate.migrate_confirm", "--confirm"));
return true;
}
mod.getModuleEntry().disable();
thread.start(); thread.start();
context.response(L("command.blockstate.migrate_started", source.getType(), target.getType())); context.response(L("command.blockstate.migrate_started", source.getType(), target.getType()));
return true; return true;

View file

@ -0,0 +1,139 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World;
import de.jaschastarke.bukkit.lib.chat.ChatFormattings;
import de.jaschastarke.bukkit.lib.commands.CommandContext;
import de.jaschastarke.bukkit.lib.database.ResultIterator;
import de.jaschastarke.database.db.Database;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
public class CreativeControlImportThread extends DatabaseMigrationThread {
public CreativeControlImportThread(ModBlockStates mod, CommandContext context, Database source, Database target) {
super(mod, context, source, target);
}
@Override
public void run() {
try {
if (!target.isInTransaction())
target.startTransaction();
int rowCount = 0;
Connection sourceConnection = source.getConnection();
Connection targetConnection = target.getConnection();
if (mode == Mode.REPLACE) {
targetConnection.createStatement().execute("DELETE FROM lc_block_state");
}
DBQueries targetDB = new DBQueries(this, target);
List<WorldSize> worldBounds = new ArrayList<WorldSize>();
for (World w : mod.getPlugin().getServer().getWorlds()) {
try {
ResultSet fetchBounds = sourceConnection.createStatement().executeQuery("SELECT MIN(x), MIN(z), MAX(x), MAX(z) FROM crcr_blocks_" + w.getName());
while (fetchBounds.next()) {
worldBounds.add(new WorldSize(w,
fetchBounds.getInt(1),
fetchBounds.getInt(2),
fetchBounds.getInt(3),
fetchBounds.getInt(4)));
}
fetchBounds.close();
} catch (SQLException e) {
if (isDebug())
mod.getLog().debug("crcr_blocks_" + w.getName() + " not found: " + e.getMessage());
mod.getLog().info("CreativeControl has BlockData for World " + w.getName());
}
}
for (WorldSize bounds : worldBounds) {
World world = mod.getPlugin().getServer().getWorld(bounds.getWorld());
if (world != null) {
long time = System.currentTimeMillis();
int itCount = 0;
if (mod.isDebug())
mod.getLog().debug("Processing world " + world.getName() + " with bounds: " + bounds);
for (int x = bounds.getMinX(); x <= bounds.getMaxX(); x += CHUNK_SIZE + 1) {
for (int z = bounds.getMinZ(); z <= bounds.getMaxZ(); z += CHUNK_SIZE + 1) {
Cuboid c = new Cuboid();
c.add(new Location(world, x, 0, z));
c.add(new Location(world, x + CHUNK_SIZE, world.getMaxHeight(), z + CHUNK_SIZE));
System.out.println("Fetching Cuboid: " + c.toString());
for (BlockState bs : iterateAllIn(c)) {
if (mode == Mode.UPDATE) {
BlockState xs = targetDB.find(bs.getLocation());
if (xs == null) {
targetDB.insert(bs);
} else if (xs.getDate().before(bs.getDate())) {
targetDB.update(bs);
}
} else {
targetDB.insert(bs);
}
rowCount++;
itCount++;
}
Thread.yield();
}
}
String region = "Region{world = " + world.getName() + ", x = [" + bounds.getMinX() + "; " + (bounds.getMinX() + CHUNK_SIZE) + "], z = [" + bounds.getMinZ() + "; " + (bounds.getMinZ() + CHUNK_SIZE) + "]}";
mod.getLog().info("Migration processed " + itCount + " BlockStates in " + region + " within " + ((System.currentTimeMillis() - time) / 1000.0) + " seconds");
}
}
target.endTransaction();
context.responseFormatted(ChatFormattings.SUCCESS, L("command.blockstate.migration_finished", rowCount) + " " +
context.getFormatter().formatString(ChatFormattings.ERROR, L("command.blockstate.migration_finished_restart")));
} catch (SQLException e) {
try {
target.revertTransaction();
} catch (SQLException e1) {}
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migration_error", e.getMessage()));
}
}
private PreparedStatement findall = null;
private Iterable<BlockState> iterateAllIn(final DBModel.Cuboid c) throws SQLException {
if (isDebug())
getLog().debug("DBQuery: iterateAllIn: " + c.toString());
if (findall == null) {
findall = source.prepare("SELECT * FROM crcr_blocks_" + c.getWorld().getName() + " LEFT JOIN crcr_players ON owner = id WHERE x >= ? AND x <= ? AND y >= ? AND y <= ? AND z >= ? AND z <= ?");
}
findall.setInt(1, c.getMinX());
findall.setInt(2, c.getMaxX());
findall.setInt(3, c.getMinY());
findall.setInt(4, c.getMaxY());
findall.setInt(5, c.getMinZ());
findall.setInt(6, c.getMaxZ());
ResultSet rs = findall.executeQuery();
return new ResultIterator<BlockState>(rs) {
@Override
protected BlockState fetch(ResultSet rs) throws SQLException {
BlockState bs = new BlockState();
bs.setLocation(new Location(c.getWorld(), rs.getInt("x"), rs.getInt("y"), rs.getInt("z")));
bs.setDate(new Date(rs.getLong("time")));
bs.setGameMode(GameMode.CREATIVE);
bs.setPlayerName(rs.getString("player"));
bs.setSource(Source.PLAYER);
return bs;
}
};
}
}

View file

@ -20,12 +20,12 @@ import de.jaschastarke.utils.IDebugLogHolder;
import de.jaschastarke.utils.ISimpleLogger; import de.jaschastarke.utils.ISimpleLogger;
public class DatabaseMigrationThread extends Thread implements IDebugLogHolder { public class DatabaseMigrationThread extends Thread implements IDebugLogHolder {
private static final int CHUNK_SIZE = 512; protected static final int CHUNK_SIZE = 512;
private ModBlockStates mod; protected ModBlockStates mod;
private CommandContext context; protected CommandContext context;
private Database source; protected Database source;
private Database target; protected Database target;
private Mode mode = Mode.REPLACE; protected Mode mode = Mode.REPLACE;
private boolean debug = false; private boolean debug = false;
public static enum Mode { public static enum Mode {
@ -139,11 +139,11 @@ public class DatabaseMigrationThread extends Thread implements IDebugLogHolder {
} }
} }
private String L(String msg, Object... args) { protected String L(String msg, Object... args) {
return mod.getPlugin().getLocale().trans(msg, args); return mod.getPlugin().getLocale().trans(msg, args);
} }
private static class WorldSize { protected static class WorldSize {
UUID w; UUID w;
int minX, minZ, maxX, maxZ; int minX, minZ, maxX, maxZ;
@ -154,6 +154,13 @@ public class DatabaseMigrationThread extends Thread implements IDebugLogHolder {
this.maxX = maxX; this.maxX = maxX;
this.maxZ = maxZ; this.maxZ = maxZ;
} }
public WorldSize(World w, int minX, int minZ, int maxX, int maxZ) {
this.w = w.getUID();
this.minX = minX;
this.minZ = minZ;
this.maxX = maxX;
this.maxZ = maxZ;
}
public String toString() { public String toString() {
World world = Bukkit.getServer().getWorld(w); World world = Bukkit.getServer().getWorld(w);
String wn = world == null ? w.toString() : world.getName(); String wn = world == null ? w.toString() : world.getName();

View file

@ -174,11 +174,8 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
* values aren't supported yet. If you don't add a data-value, all blocks of this material are blocked. * values aren't supported yet. If you don't add a data-value, all blocks of this material are blocked.
* *
* default: * default:
* - SIGN * - WALL_SIGN
* - SIGN_POST * - SIGN_POST
* - LEVER
* - STONE_BUTTON
* - WOOD_BUTTON
* - JUKEBOX * - JUKEBOX
*/ */
@IsConfigurationNode(name = "interact", order = 600) @IsConfigurationNode(name = "interact", order = 600)
@ -188,9 +185,6 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
if (!config.contains("interact")) { if (!config.contains("interact")) {
interactList.add(new BlackList.Blacklisted(Material.WALL_SIGN)); interactList.add(new BlackList.Blacklisted(Material.WALL_SIGN));
interactList.add(new BlackList.Blacklisted(Material.SIGN_POST)); interactList.add(new BlackList.Blacklisted(Material.SIGN_POST));
interactList.add(new BlackList.Blacklisted(Material.LEVER));
interactList.add(new BlackList.Blacklisted(Material.STONE_BUTTON));
interactList.add(new BlackList.Blacklisted(Material.WOOD_BUTTON));
interactList.add(new BlackList.Blacklisted(Material.JUKEBOX)); interactList.add(new BlackList.Blacklisted(Material.JUKEBOX));
} }
} }

View file

@ -32,6 +32,7 @@ command.blockstate.command_updated: Successfully updated {0} blocks.
command.blockstate.command_failed: Failed to update blocks. See server.log for details. command.blockstate.command_failed: Failed to update blocks. See server.log for details.
command.blockstate.migrate_started: Database migration from {0} to {1} started... command.blockstate.migrate_started: Database migration from {0} to {1} started...
command.blockstate.migrate_connect_error: Connection to database failed with error: {0} command.blockstate.migrate_connect_error: Connection to database failed with error: {0}
command.blockstate.migrate_importtype_error: Unknown --import-type: {0}
command.blockstate.migration_finished: Database migration of {0} records successful. command.blockstate.migration_finished: Database migration of {0} records successful.
command.blockstate.migration_finished_restart: A Server-Restart is required! command.blockstate.migration_finished_restart: A Server-Restart is required!
command.blockstate.migration_error: Migration failed with error: {0} command.blockstate.migration_error: Migration failed with error: {0}

View file

@ -32,6 +32,7 @@ command.blockstate.command_updated: Erfolgreich {0} Bl
command.blockstate.command_failed: Fehler beim aktualisieren der Blöcke. Siehe server.log für Details command.blockstate.command_failed: Fehler beim aktualisieren der Blöcke. Siehe server.log für Details
command.blockstate.migrate_started: Datenbank-Migration von {0} nach {1} gestartet... command.blockstate.migrate_started: Datenbank-Migration von {0} nach {1} gestartet...
command.blockstate.migrate_connect_error: Verbindung zur Datenbank mit folgendem Fehler fehlgeschlafen: {0} command.blockstate.migrate_connect_error: Verbindung zur Datenbank mit folgendem Fehler fehlgeschlafen: {0}
command.blockstate.migrate_importtype_error: Unbekannter --import-Typ: {0}
command.blockstate.migration_finished: Datenbank-Migration von {0} Datensätzen erfolgreich command.blockstate.migration_finished: Datenbank-Migration von {0} Datensätzen erfolgreich
command.blockstate.migration_finished_restart: Server-Neustart notwendig! command.blockstate.migration_finished_restart: Server-Neustart notwendig!
command.blockstate.migration_error: Migration mit folgendem Fehler fehlgeschlagen: {0} command.blockstate.migration_error: Migration mit folgendem Fehler fehlgeschlagen: {0}