Per player history size (in MB)

This commit is contained in:
Jesse Boyd 2016-06-28 20:22:31 +10:00
parent e8ae5ca119
commit 478cbbf393
11 changed files with 65 additions and 46 deletions

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.config;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.LocalSession;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
@ -63,6 +64,8 @@ public class Settings extends Config {
"NoteBlock, Sign, Skull, Structure"
})
public int MAX_BLOCKSTATES = 1337;
@Comment("Maximum size of the player's history in Megabytes")
public int MAX_HISTORY_MB = 20;
}
public static class HISTORY {
@ -211,13 +214,18 @@ public class Settings extends Config {
public static void load(File file) {
load(file, Settings.class);
if (HISTORY.USE_DISK) {
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
}
}
public static FaweLimit getLimit(FawePlayer player) {
FaweLimit limit;
if (player.hasWorldEditBypass()) {
return FaweLimit.MAX.copy();
limit = FaweLimit.MAX.copy();
} else {
limit = new FaweLimit();
}
FaweLimit limit = new FaweLimit();
Collection<String> keys = LIMITS.getSections();
for (String key : keys) {
if (key.equals("default") || (player != null && player.hasPermission("fawe.limit." + key))) {
@ -228,6 +236,7 @@ public class Settings extends Config {
limit.MAX_ENTITIES = Math.max(limit.MAX_ENTITIES, newLimit.MAX_ENTITIES != -1 ? newLimit.MAX_ENTITIES : Integer.MAX_VALUE);
limit.MAX_FAILS = Math.max(limit.MAX_FAILS, newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE);
limit.MAX_ITERATIONS = Math.max(limit.MAX_ITERATIONS, newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE);
limit.MAX_HISTORY = HISTORY.USE_DISK ? Integer.MAX_VALUE : Math.max(limit.MAX_HISTORY, newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE);
}
}
return limit;

View File

@ -1,9 +1,5 @@
package com.boydti.fawe.object;
import com.boydti.fawe.configuration.ConfigurationSection;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Jesse on 4/5/2016.
*/
@ -14,6 +10,8 @@ public class FaweLimit {
public int MAX_ITERATIONS = 0;
public int MAX_BLOCKSTATES = 0;
public int MAX_ENTITIES = 0;
public int MAX_HISTORY = 0;
public static FaweLimit MAX;
static {
@ -49,6 +47,7 @@ public class FaweLimit {
MAX.MAX_ITERATIONS = Integer.MAX_VALUE;
MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE;
MAX.MAX_ENTITIES = Integer.MAX_VALUE;
MAX.MAX_HISTORY = 15;
}
public boolean MAX_CHANGES() {
@ -75,31 +74,6 @@ public class FaweLimit {
return MAX_ENTITIES-- > 0;
}
public boolean load(ConfigurationSection section, FaweLimit defaultLimit, boolean save) {
this.MAX_CHANGES = section.getInt("max-changes", defaultLimit == null ? MAX_CHANGES : defaultLimit.MAX_CHANGES);
this.MAX_FAILS = section.getInt("max-fails", defaultLimit == null ? MAX_FAILS : defaultLimit.MAX_FAILS);
this.MAX_CHECKS = section.getInt("max-checks", defaultLimit == null ? MAX_CHECKS : defaultLimit.MAX_CHECKS);
this.MAX_ITERATIONS = section.getInt("max-iterations", defaultLimit == null ? MAX_ITERATIONS : defaultLimit.MAX_ITERATIONS);
this.MAX_BLOCKSTATES = section.getInt("max-blockstates", defaultLimit == null ? MAX_BLOCKSTATES : defaultLimit.MAX_BLOCKSTATES);
this.MAX_ENTITIES = section.getInt("max-entities", defaultLimit == null ? MAX_ENTITIES : defaultLimit.MAX_ENTITIES);
boolean changed = false;
if (save) {
HashMap<String, Object> options = new HashMap<>();
options.put("max-changes", MAX_CHANGES);
options.put("max-fails", MAX_FAILS);
options.put("max-checks", MAX_CHECKS);
options.put("max-iterations", MAX_ITERATIONS);
options.put("max-blockstates", MAX_BLOCKSTATES);
options.put("max-entities", MAX_ENTITIES);
for (Map.Entry<String, Object> entry : options.entrySet()) {
if (!section.contains(entry.getKey())) {
section.set(entry.getKey(), entry.getValue());
changed = true;
}
}
}
return changed;
}
public FaweLimit copy() {
FaweLimit limit = new FaweLimit();
@ -109,6 +83,7 @@ public class FaweLimit {
limit.MAX_ENTITIES = MAX_ENTITIES;
limit.MAX_FAILS = MAX_FAILS;
limit.MAX_ITERATIONS = MAX_ITERATIONS;
limit.MAX_HISTORY = MAX_HISTORY;
return limit;
}

View File

@ -180,7 +180,7 @@ public abstract class FawePlayer<T> {
FaweStreamChangeSet set = new DiskStorageHistory(world, uuid, index);
EditSession edit = set.toEditSession(FawePlayer.this);
if (world.equals(getWorld())) {
session.remember(edit, false, false);
session.remember(edit, false, false, Integer.MAX_VALUE);
} else {
return;
}

View File

@ -150,6 +150,11 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
return bdFile.exists() ? (int) bdFile.length() : 0;
}
@Override
public long getSizeInMemory() {
return 80;
}
@Override
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
if (osBD != null) {

View File

@ -46,6 +46,8 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
public abstract int getCompressedSize();
public abstract long getSizeInMemory();
public abstract OutputStream getBlockOS(int x, int y, int z) throws IOException;
public abstract NBTOutputStream getEntityCreateOS() throws IOException;
public abstract NBTOutputStream getEntityRemoveOS() throws IOException;

View File

@ -91,6 +91,11 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
return ids == null ? 0 : ids.length;
}
@Override
public long getSizeInMemory() {
return 92 + getCompressedSize();
}
@Override
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
if (idsStreamZip != null) {

View File

@ -107,7 +107,9 @@ public class Schematic {
extent = new BlockTransformExtent(clipboard, transform, world.getWorldData().getBlockRegistry());
}
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), editSession, to);
if (transform != null) {
copy.setTransform(transform);
}
if (!pasteAir) {
copy.setSourceMask(new ExistingBlockMask(clipboard));
}

View File

@ -8,6 +8,7 @@ import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
@ -17,6 +18,7 @@ import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.util.Location;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@ -87,6 +89,18 @@ public class MainUtil {
return getCompressedOS(os, Settings.HISTORY.COMPRESSION_LEVEL);
}
public static long getSizeInMemory(ChangeSet changeSet) {
if (changeSet instanceof FaweStreamChangeSet){
return 92 + ((FaweStreamChangeSet) changeSet).getSizeInMemory();
} else if (changeSet instanceof CPUOptimizedChangeSet) {
return changeSet.size() + 32;
} else if (changeSet != null) {
return changeSet.size() * 128;
} else {
return 0;
}
}
public static FaweOutputStream getCompressedOS(OutputStream os, int amount) throws IOException {
os.write((byte) amount);
os = new BufferedOutputStream(os, Settings.HISTORY.BUFFER_SIZE);

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.wrappers;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager;
@ -205,7 +206,7 @@ public class PlayerWrapper implements Player {
edit.setBlock(new Vector(x, y - 1, z), new BaseBlock( BlockType.GLASS.getID()));
LocalSession session = Fawe.get().getWorldEdit().getSession(this);
if (session != null) {
session.remember(edit);
session.remember(edit, true, false, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
}
} catch (MaxChangedBlocksException e) {
MainUtil.handleError(e);

View File

@ -19,8 +19,9 @@
package com.sk89q.worldedit;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.util.MainUtil;
import com.sk89q.jchronic.Chronic;
import com.sk89q.jchronic.Options;
import com.sk89q.jchronic.utils.Span;
@ -66,6 +67,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class LocalSession {
@Deprecated
public transient static int MAX_HISTORY_SIZE = 15;
// Non-session related fields
@ -77,6 +79,7 @@ public class LocalSession {
private transient boolean placeAtPos1 = false;
private transient List<EditSession> history = Collections.synchronizedList(new LinkedList<EditSession>());
private transient volatile int historyPointer = 0;
private transient volatile long historySize = 0;
private transient ClipboardHolder clipboard;
private transient boolean toolControl = true;
private transient boolean superPickaxe = false;
@ -184,6 +187,7 @@ public class LocalSession {
public void clearHistory() {
history.clear();
historyPointer = 0;
historySize = 0;
}
/**
@ -193,31 +197,31 @@ public class LocalSession {
* @param editSession the edit session
*/
public void remember(EditSession editSession) {
remember(editSession, true, false);
FawePlayer fp = editSession.getPlayer();
int limit = fp == null ? Integer.MAX_VALUE : fp.getLimit().MAX_HISTORY;
remember(editSession, true, false, limit);
}
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage) {
if (editSession == null || editSession.getChangeSet() == null) {
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) {
if (editSession == null || editSession.getChangeSet() == null || limitMb == 0) {
return;
}
// It should have already been flushed, but just in case!
editSession.flushQueue();
if (Settings.HISTORY.USE_DISK) {
MAX_HISTORY_SIZE = Integer.MAX_VALUE;
} else if (MAX_HISTORY_SIZE == Integer.MAX_VALUE) {
MAX_HISTORY_SIZE = 15;
}
// Don't store anything if no changes were made
if (editSession.size() == 0 || editSession.hasFastMode()) {
return;
}
System.out.println("SIZE: " + historySize + " | " + history.size());
// Destroy any sessions after this undo point
if (append) {
while (historyPointer < history.size()) {
EditSession item = history.get(historyPointer);
historySize -= MainUtil.getSizeInMemory(item.getChangeSet());
history.remove(historyPointer);
}
}
historySize += MainUtil.getSizeInMemory(editSession.getChangeSet());
if (append) {
history.add(editSession);
historyPointer = history.size();
@ -225,7 +229,9 @@ public class LocalSession {
history.add(0, editSession);
historyPointer++;
}
while (history.size() > MAX_HISTORY_SIZE) {
while ((history.size() > MAX_HISTORY_SIZE || historySize > limitMb) && history.size() > 0) {
EditSession item = history.get(0);
historySize -= MainUtil.getSizeInMemory(item.getChangeSet());
history.remove(0);
historyPointer--;
}

View File

@ -299,7 +299,7 @@ public final class CommandManager {
if (editSession != null) {
editSession.flushQueue();
worldEdit.flushBlockBag(actor, editSession);
session.remember(editSession, true, true);
session.remember(editSession);
hasSession = editSession.size() > 0;
}
if (fp != null) {