From 8c9be4f1f4c904f95c718f085e5c590565aef7cb Mon Sep 17 00:00:00 2001 From: Jascha Starke Date: Fri, 8 Nov 2013 11:57:36 +0100 Subject: [PATCH] WorldEdit in transaction. (Better WE Performance with BlockState) A special cookie for LordSaad, yummi. --- .../blockstate/BlockStateConfig.java | 6 +- .../limitedcreative/blockstate/DBQueries.java | 2 +- .../blockstate/thread/ThreadLink.java | 9 ++- .../blockstate/worldedit/LCEditSession.java | 68 ++++++++++++++++++- .../worldedit/LCEditSessionFactory.java | 61 +++++++++++++---- .../worldedit/LCEditSession_CoreProtect.java | 68 ++++++++++++++++++- .../worldedit/LCEditSession_LogBlock.java | 67 +++++++++++++++++- 7 files changed, 258 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java index 0a6f905..058fbe8 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java @@ -87,8 +87,10 @@ public class BlockStateConfig extends Configuration implements IConfigurationSub * BlockStateThreading * * Uses Threading to minimize lag. This fully relies on Bukkit metadata implementation. You only should need this, - * if there are often plays more then 10 players at once on your server. Be aware that this requires more memory, - * to increase the performance + * if there are often plays more then 10 players at once on your server, or you're about to use huge WorldEdits often. + * Be aware that this requires more memory, to increase the performance + * + * Without threading, huge WorldEdits becomes much noticeable slower. * * default: false */ diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/DBQueries.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/DBQueries.java index c7dc323..3826c71 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/DBQueries.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/DBQueries.java @@ -133,7 +133,7 @@ public class DBQueries { "WHERE x = ? AND y = ? AND z = ? AND world = ? "); } if (s.getGameMode() == null) - update.setNull(5, Types.INTEGER); + update.setNull(1, Types.INTEGER); else if (db.getType() == Type.MySQL) update.setString(1, s.getGameMode().name()); else diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/thread/ThreadLink.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/thread/ThreadLink.java index e511b7d..1ec58cf 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/thread/ThreadLink.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/thread/ThreadLink.java @@ -18,7 +18,7 @@ import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries; import de.jaschastarke.minecraft.limitedcreative.blockstate.ThreadedModel; public class ThreadLink { - private static final int BATCH_ACTION_LENGTH = 10; + private static final int BATCH_ACTION_LENGTH = 25; private static final int QUEUE_ACCESS_WARNING_DURATION = 5; // ms private static final int COUNT_WARNING_QUEUE = 5; private static final int COUNT_ERROR_QUEUE = 20; @@ -83,8 +83,11 @@ public class ThreadLink { acts.add(updateQueue.pop()); } } - if (getModule().isDebug()) + long t = 0; + if (getModule().isDebug()) { + t = System.currentTimeMillis(); log.debug("DB-Thread '" + Thread.currentThread().getName() + "' run: " + acts.size()); + } for (Action act : acts) { if (!shutdown || !(act instanceof CacheChunkAction)) { if (act instanceof CallableAction) { @@ -97,6 +100,8 @@ public class ThreadLink { } } } + if (getModule().isDebug()) + log.debug("DB-Thread '" + Thread.currentThread().getName() + "' execution time: " + (System.currentTimeMillis() - t) + "ms"); } catch (InterruptedException e) { e.printStackTrace(); log.severe("DB-Thread '" + Thread.currentThread().getName() + "' was harmfull interupted"); diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession.java index 203d5eb..edb8f13 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession.java @@ -3,9 +3,14 @@ package de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.patterns.Pattern; +import com.sk89q.worldedit.regions.Region; + +import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction; public class LCEditSession extends EditSession { private LCEditSessionFactory factory; @@ -23,11 +28,70 @@ public class LCEditSession extends EditSession { this.player = player; } + private DBTransaction transaction; + + @Override + public void flushQueue() { + transaction = factory.getModel().groupUpdate(); + super.flushQueue(); + if (transaction != null) { + transaction.finish(); + transaction = null; + } + } + + @Override + public int setBlocks(Region region, BaseBlock block) throws MaxChangedBlocksException { + boolean useTransaction = false; + if (transaction == null) { + transaction = factory.getModel().groupUpdate(); + useTransaction = true; + } + int ret; + try { + ret = super.setBlocks(region, block); + } catch (MaxChangedBlocksException e) { + transaction = null; + throw e; + } + if (transaction != null && useTransaction) { + transaction.finish(); + transaction = null; + } + return ret; + } + + @Override + public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + boolean useTransaction = false; + if (transaction == null) { + transaction = factory.getModel().groupUpdate(); + useTransaction = true; + } + int ret; + try { + ret = super.setBlocks(region, pattern); + } catch (MaxChangedBlocksException e) { + transaction = null; + throw e; + } + if (transaction != null && useTransaction) { + transaction.finish(); + transaction = null; + } + return ret; + } + @Override public boolean rawSetBlock(Vector pt, BaseBlock block) { boolean success = super.rawSetBlock(pt, block); - if (success) - factory.onBlockEdit(player, pt, block); + if (success) { + if (transaction != null) { + factory.onTransactionBlockEdit(transaction, player, pt, block); + } else { + factory.onBlockEdit(player, pt, block); + } + } return success; } } diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSessionFactory.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSessionFactory.java index 6c5f69c..7eeef83 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSessionFactory.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSessionFactory.java @@ -18,6 +18,8 @@ import com.sk89q.worldedit.bukkit.BukkitWorld; import de.jaschastarke.minecraft.limitedcreative.ModBlockStates; import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState; import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source; +import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel; +import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction; public class LCEditSessionFactory extends EditSessionFactory { private ModBlockStates mod; @@ -154,22 +156,57 @@ public class LCEditSessionFactory extends EditSessionFactory { /*public void onBlockEdit(Vector pt, BaseBlock block) { this.onBlockEdit(null, pt, block); }*/ + + public DBModel getModel() { + return mod.getModel(); + } + public boolean onBlockEdit(LocalPlayer player, Vector pt, BaseBlock block) { if (player != null) { Location loc = new Location(((BukkitWorld) player.getWorld()).getWorld(), pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - BlockState s = mod.getModel().getState(loc.getBlock()); - if (s == null) { - s = new BlockState(); - s.setLocation(loc); + if (block.getType() == 0) { + mod.getModel().removeState(loc.getBlock()); + } else { + BlockState s = mod.getModel().getState(loc.getBlock()); + if (s == null) { + s = new BlockState(); + s.setLocation(loc); + } + s.setGameMode(null); + s.setPlayerName(player.getName()); + s.setDate(new Date()); + s.setSource(Source.EDIT); + if (mod.isDebug()) + mod.getLog().debug("Saving BlockState: " + s.toString()); + + mod.getModel().setState(s); + } + return true; + } else { + return false; + } + } + + public boolean onTransactionBlockEdit(DBTransaction transaction, LocalPlayer player, Vector pt, BaseBlock block) { + if (player != null) { + Location loc = new Location(((BukkitWorld) player.getWorld()).getWorld(), pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block.getType() == 0) { + transaction.removeState(loc.getBlock()); + } else { + BlockState s = mod.getModel().getState(loc.getBlock()); + if (s == null) { + s = new BlockState(); + s.setLocation(loc); + } + s.setGameMode(null); + s.setPlayerName(player.getName()); + s.setDate(new Date()); + s.setSource(Source.EDIT); + if (mod.isDebug()) + mod.getLog().debug("Saving BlockState: " + s.toString()); + + transaction.setState(s); } - s.setGameMode(null); - s.setPlayerName(player.getName()); - s.setDate(new Date()); - s.setSource(Source.EDIT); - if (mod.isDebug()) - mod.getLog().debug("Saving BlockState: " + s.toString()); - - mod.getModel().setState(s); return true; } else { return false; diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_CoreProtect.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_CoreProtect.java index ff8f945..e2ec4ff 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_CoreProtect.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_CoreProtect.java @@ -5,9 +5,14 @@ import net.coreprotect.worldedit.CoreProtectEditSession; import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.patterns.Pattern; +import com.sk89q.worldedit.regions.Region; + +import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction; public class LCEditSession_CoreProtect extends CoreProtectEditSession { private LCEditSessionFactory factory; @@ -25,11 +30,70 @@ public class LCEditSession_CoreProtect extends CoreProtectEditSession { this.player = player; } + private DBTransaction transaction; + + @Override + public void flushQueue() { + transaction = factory.getModel().groupUpdate(); + super.flushQueue(); + if (transaction != null) { + transaction.finish(); + transaction = null; + } + } + + @Override + public int setBlocks(Region region, BaseBlock block) throws MaxChangedBlocksException { + boolean useTransaction = false; + if (transaction == null) { + transaction = factory.getModel().groupUpdate(); + useTransaction = true; + } + int ret; + try { + ret = super.setBlocks(region, block); + } catch (MaxChangedBlocksException e) { + transaction = null; + throw e; + } + if (transaction != null && useTransaction) { + transaction.finish(); + transaction = null; + } + return ret; + } + + @Override + public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + boolean useTransaction = false; + if (transaction == null) { + transaction = factory.getModel().groupUpdate(); + useTransaction = true; + } + int ret; + try { + ret = super.setBlocks(region, pattern); + } catch (MaxChangedBlocksException e) { + transaction = null; + throw e; + } + if (transaction != null && useTransaction) { + transaction.finish(); + transaction = null; + } + return ret; + } + @Override public boolean rawSetBlock(Vector pt, BaseBlock block) { boolean success = super.rawSetBlock(pt, block); - if (success) - factory.onBlockEdit(player, pt, block); + if (success) { + if (transaction != null) { + factory.onTransactionBlockEdit(transaction, player, pt, block); + } else { + factory.onBlockEdit(player, pt, block); + } + } return success; } } diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_LogBlock.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_LogBlock.java index d5f0d39..00b90b4 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_LogBlock.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_LogBlock.java @@ -2,12 +2,16 @@ package de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit; import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.patterns.Pattern; +import com.sk89q.worldedit.regions.Region; import de.diddiz.LogBlock.LogBlock; import de.diddiz.worldedit.LogBlockEditSession; +import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction; public class LCEditSession_LogBlock extends LogBlockEditSession { private LCEditSessionFactory factory; @@ -25,11 +29,70 @@ public class LCEditSession_LogBlock extends LogBlockEditSession { this.player = player; } + private DBTransaction transaction; + + @Override + public void flushQueue() { + transaction = factory.getModel().groupUpdate(); + super.flushQueue(); + if (transaction != null) { + transaction.finish(); + transaction = null; + } + } + + @Override + public int setBlocks(Region region, BaseBlock block) throws MaxChangedBlocksException { + boolean useTransaction = false; + if (transaction == null) { + transaction = factory.getModel().groupUpdate(); + useTransaction = true; + } + int ret; + try { + ret = super.setBlocks(region, block); + } catch (MaxChangedBlocksException e) { + transaction = null; + throw e; + } + if (transaction != null && useTransaction) { + transaction.finish(); + transaction = null; + } + return ret; + } + + @Override + public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + boolean useTransaction = false; + if (transaction == null) { + transaction = factory.getModel().groupUpdate(); + useTransaction = true; + } + int ret; + try { + ret = super.setBlocks(region, pattern); + } catch (MaxChangedBlocksException e) { + transaction = null; + throw e; + } + if (transaction != null && useTransaction) { + transaction.finish(); + transaction = null; + } + return ret; + } + @Override public boolean rawSetBlock(Vector pt, BaseBlock block) { boolean success = super.rawSetBlock(pt, block); - if (success) - factory.onBlockEdit(player, pt, block); + if (success) { + if (transaction != null) { + factory.onTransactionBlockEdit(transaction, player, pt, block); + } else { + factory.onBlockEdit(player, pt, block); + } + } return success; } }