WorldEdit in transaction. (Better WE Performance with BlockState)

A special cookie for LordSaad, yummi.
This commit is contained in:
Jascha Starke 2013-11-08 11:57:36 +01:00
parent aba6bf354d
commit 8c9be4f1f4
7 changed files with 258 additions and 23 deletions

View file

@ -87,8 +87,10 @@ public class BlockStateConfig extends Configuration implements IConfigurationSub
* BlockStateThreading * BlockStateThreading
* *
* Uses Threading to minimize lag. This fully relies on Bukkit metadata implementation. You only should need this, * 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, * if there are often plays more then 10 players at once on your server, or you're about to use huge WorldEdits often.
* to increase the performance * Be aware that this requires more memory, to increase the performance
*
* Without threading, huge WorldEdits becomes much noticeable slower.
* *
* default: false * default: false
*/ */

View file

@ -133,7 +133,7 @@ public class DBQueries {
"WHERE x = ? AND y = ? AND z = ? AND world = ? "); "WHERE x = ? AND y = ? AND z = ? AND world = ? ");
} }
if (s.getGameMode() == null) if (s.getGameMode() == null)
update.setNull(5, Types.INTEGER); update.setNull(1, Types.INTEGER);
else if (db.getType() == Type.MySQL) else if (db.getType() == Type.MySQL)
update.setString(1, s.getGameMode().name()); update.setString(1, s.getGameMode().name());
else else

View file

@ -18,7 +18,7 @@ import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
import de.jaschastarke.minecraft.limitedcreative.blockstate.ThreadedModel; import de.jaschastarke.minecraft.limitedcreative.blockstate.ThreadedModel;
public class ThreadLink { 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 QUEUE_ACCESS_WARNING_DURATION = 5; // ms
private static final int COUNT_WARNING_QUEUE = 5; private static final int COUNT_WARNING_QUEUE = 5;
private static final int COUNT_ERROR_QUEUE = 20; private static final int COUNT_ERROR_QUEUE = 20;
@ -83,8 +83,11 @@ public class ThreadLink {
acts.add(updateQueue.pop()); 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()); log.debug("DB-Thread '" + Thread.currentThread().getName() + "' run: " + acts.size());
}
for (Action act : acts) { for (Action act : acts) {
if (!shutdown || !(act instanceof CacheChunkAction)) { if (!shutdown || !(act instanceof CacheChunkAction)) {
if (act instanceof CallableAction) { 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) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
log.severe("DB-Thread '" + Thread.currentThread().getName() + "' was harmfull interupted"); log.severe("DB-Thread '" + Thread.currentThread().getName() + "' was harmfull interupted");

View file

@ -3,9 +3,14 @@ package de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.bags.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock; 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 { public class LCEditSession extends EditSession {
private LCEditSessionFactory factory; private LCEditSessionFactory factory;
@ -23,11 +28,70 @@ public class LCEditSession extends EditSession {
this.player = player; 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 @Override
public boolean rawSetBlock(Vector pt, BaseBlock block) { public boolean rawSetBlock(Vector pt, BaseBlock block) {
boolean success = super.rawSetBlock(pt, block); boolean success = super.rawSetBlock(pt, block);
if (success) if (success) {
if (transaction != null) {
factory.onTransactionBlockEdit(transaction, player, pt, block);
} else {
factory.onBlockEdit(player, pt, block); factory.onBlockEdit(player, pt, block);
}
}
return success; return success;
} }
} }

View file

@ -18,6 +18,8 @@ import com.sk89q.worldedit.bukkit.BukkitWorld;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates; import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState; import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source; 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 { public class LCEditSessionFactory extends EditSessionFactory {
private ModBlockStates mod; private ModBlockStates mod;
@ -154,9 +156,17 @@ public class LCEditSessionFactory extends EditSessionFactory {
/*public void onBlockEdit(Vector pt, BaseBlock block) { /*public void onBlockEdit(Vector pt, BaseBlock block) {
this.onBlockEdit(null, pt, block); this.onBlockEdit(null, pt, block);
}*/ }*/
public DBModel getModel() {
return mod.getModel();
}
public boolean onBlockEdit(LocalPlayer player, Vector pt, BaseBlock block) { public boolean onBlockEdit(LocalPlayer player, Vector pt, BaseBlock block) {
if (player != null) { if (player != null) {
Location loc = new Location(((BukkitWorld) player.getWorld()).getWorld(), pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); Location loc = new Location(((BukkitWorld) player.getWorld()).getWorld(), pt.getBlockX(), pt.getBlockY(), pt.getBlockZ());
if (block.getType() == 0) {
mod.getModel().removeState(loc.getBlock());
} else {
BlockState s = mod.getModel().getState(loc.getBlock()); BlockState s = mod.getModel().getState(loc.getBlock());
if (s == null) { if (s == null) {
s = new BlockState(); s = new BlockState();
@ -170,6 +180,33 @@ public class LCEditSessionFactory extends EditSessionFactory {
mod.getLog().debug("Saving BlockState: " + s.toString()); mod.getLog().debug("Saving BlockState: " + s.toString());
mod.getModel().setState(s); 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);
}
return true; return true;
} else { } else {
return false; return false;

View file

@ -5,9 +5,14 @@ import net.coreprotect.worldedit.CoreProtectEditSession;
import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.bags.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock; 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 { public class LCEditSession_CoreProtect extends CoreProtectEditSession {
private LCEditSessionFactory factory; private LCEditSessionFactory factory;
@ -25,11 +30,70 @@ public class LCEditSession_CoreProtect extends CoreProtectEditSession {
this.player = player; 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 @Override
public boolean rawSetBlock(Vector pt, BaseBlock block) { public boolean rawSetBlock(Vector pt, BaseBlock block) {
boolean success = super.rawSetBlock(pt, block); boolean success = super.rawSetBlock(pt, block);
if (success) if (success) {
if (transaction != null) {
factory.onTransactionBlockEdit(transaction, player, pt, block);
} else {
factory.onBlockEdit(player, pt, block); factory.onBlockEdit(player, pt, block);
}
}
return success; return success;
} }
} }

View file

@ -2,12 +2,16 @@ package de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit;
import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.bags.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock; 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.LogBlock.LogBlock;
import de.diddiz.worldedit.LogBlockEditSession; import de.diddiz.worldedit.LogBlockEditSession;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction;
public class LCEditSession_LogBlock extends LogBlockEditSession { public class LCEditSession_LogBlock extends LogBlockEditSession {
private LCEditSessionFactory factory; private LCEditSessionFactory factory;
@ -25,11 +29,70 @@ public class LCEditSession_LogBlock extends LogBlockEditSession {
this.player = player; 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 @Override
public boolean rawSetBlock(Vector pt, BaseBlock block) { public boolean rawSetBlock(Vector pt, BaseBlock block) {
boolean success = super.rawSetBlock(pt, block); boolean success = super.rawSetBlock(pt, block);
if (success) if (success) {
if (transaction != null) {
factory.onTransactionBlockEdit(transaction, player, pt, block);
} else {
factory.onBlockEdit(player, pt, block); factory.onBlockEdit(player, pt, block);
}
}
return success; return success;
} }
} }