DB: Fix BlockDB with /resizelvl

This commit is contained in:
UnknownShadow200 2016-12-24 07:31:37 +11:00
parent 88bfba87c2
commit 62410fc34a
9 changed files with 89 additions and 59 deletions

View File

@ -114,8 +114,9 @@ namespace MCGalaxy.Commands {
static void ListInMemory(Player p, ref bool foundAny, Dictionary<int, string> names,
ushort x, ushort y, ushort z) {
int index = p.level.PosToInt(x, y, z);
FastList<BlockDBEntry> entries = p.level.blockCache;
BlockDB blockDB = p.level.BlockDB;
int index = x + blockDB.Dims.X * (z + blockDB.Dims.Z * y);
FastList<BlockDBEntry> entries = blockDB.Cache;
for (int i = 0; i < entries.Count; i++) {
if (entries.Items[i].Index != index) continue;

View File

@ -24,7 +24,9 @@ namespace MCGalaxy.DB {
public unsafe sealed class BlockDB {
public ushort Width, Height, Length;
/// <summary> Dimensions used to pack coordinates into an index. </summary>
/// <remarks> May be different from actual level's dimensions, such as when the level has been resized. </remarks>
public Vec3U16 Dims;
/// <summary> The map/level name associated with this BlockDB. </summary>
public string MapName;
@ -38,25 +40,69 @@ namespace MCGalaxy.DB {
/// <summary> The path of this BlockDB's temp backing file on disc for resizing. </summary>
public string TempPath { get { return "blockdb/" + MapName + ".temp"; } }
/// <summary> Used to synchronise adding to Cache by multiple threads. </summary>
internal readonly object CacheLock = new object();
/// <summary> In-memory list of recent BlockDB changes. </summary>
public FastList<BlockDBEntry> Cache = new FastList<BlockDBEntry>();
/// <summary> Whether changes are actually added to the BlockDB. </summary>
public bool Used;
readonly ReaderWriterLockSlim locker;
public BlockDB(Level lvl) {
MapName = lvl.name;
Width = lvl.Width; Height = lvl.Height; Length = lvl.Length;
ReadDimensions();
locker = new ReaderWriterLockSlim();
if (Dims.X < lvl.Width) Dims.X = lvl.Width;
if (Dims.Y < lvl.Height) Dims.Y = lvl.Height;
if (Dims.Z < lvl.Length) Dims.Z = lvl.Length;
}
void ReadDimensions() {
if (!File.Exists(FilePath)) return;
using (Stream s = File.OpenRead(FilePath))
BlockDBFile.ReadHeader(s, out Dims);
}
public void AppendEntries(ref FastList<BlockDBEntry> entries, object lockObj) {
public void Add(Player p, ushort x, ushort y, ushort z, ushort flags,
byte oldBlock, byte oldExt, byte block, byte ext) {
if (!Used) return;
BlockDBEntry entry;
entry.PlayerID = p.UserID;
entry.TimeDelta = (int)DateTime.UtcNow.Subtract(BlockDB.Epoch).TotalSeconds;
entry.Index = x + Dims.X * (z + Dims.Z * y);
entry.OldRaw = oldBlock; entry.NewRaw = block;
entry.Flags = flags;
if (block == Block.custom_block) {
entry.Flags |= BlockDBFlags.NewCustom;
entry.NewRaw = ext;
}
if (oldBlock == Block.custom_block) {
entry.Flags |= BlockDBFlags.OldCustom;
entry.OldRaw = oldExt;
}
lock (CacheLock)
Cache.Add(entry);
}
public void WriteEntries() {
using (IDisposable writeLock = locker.AccquireWriteLock()) {
if (entries.Count == 0) return;
if (Cache.Count == 0) return;
ValidateBackingFile();
using (Stream s = File.OpenWrite(FilePath)) {
s.Position = s.Length;
BlockDBFile.WriteEntries(s, entries);
BlockDBFile.WriteEntries(s, Cache);
lock (lockObj)
entries = new FastList<BlockDBEntry>();
lock (CacheLock)
Cache = new FastList<BlockDBEntry>();
}
}
}
@ -115,18 +161,18 @@ namespace MCGalaxy.DB {
/// <summary> Checks if the backing file exists on disc, and if not, creates it.
/// Also recreates the backing file if dimensions on disc are less than those in memory. </summary>
void ValidateBackingFile() {
Vec3U16 dims;
Vec3U16 fileDims;
if (!File.Exists(FilePath)) {
using (Stream s = File.OpenWrite(FilePath)) {
dims = new Vec3U16(Width, Height, Length);
BlockDBFile.WriteHeader(s, dims);
fileDims = Dims;
BlockDBFile.WriteHeader(s, fileDims);
}
} else {
using (Stream s = File.OpenRead(FilePath)) {
BlockDBFile.ReadHeader(s, out dims);
BlockDBFile.ReadHeader(s, out fileDims);
}
if (dims.X < Width || dims.Y < Height || dims.Z < Length) {
if (fileDims.X < Dims.X || fileDims.Y < Dims.Y || fileDims.Z < Dims.Z) {
BlockDBFile.ResizeBackingFile(this);
}
}

View File

@ -142,8 +142,8 @@ namespace MCGalaxy.DB {
using (Stream src = File.OpenRead(db.FilePath), dst = File.Create(db.TempPath)) {
Vec3U16 dims;
ReadHeader(src, out dims);
WriteHeader(dst, new Vec3U16(db.Width, db.Height, db.Length));
int width = db.Width, length = db.Length;
WriteHeader(dst, db.Dims);
int width = db.Dims.X, length = db.Dims.Z;
byte[] bulk = new byte[bulkEntries * entrySize];
fixed (byte* ptr = bulk) {

View File

@ -176,8 +176,9 @@ namespace MCGalaxy.Drawing.Ops {
} else {
if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true)) return;
lvl.BlockDB.Add(p, b.X, b.Y, b.Z, op.Flags,
old, oldExt, b.Block, b.ExtBlock);
int index = lvl.PosToInt(b.X, b.Y, b.Z);
lvl.AddToBlockDB(p, index, old, oldExt, b.Block, b.ExtBlock, op.Flags);
BlockQueue.Addblock(p, index, b.Block, b.ExtBlock);
}
op.TotalModified++;

View File

@ -146,7 +146,8 @@ namespace MCGalaxy {
SetExtTileNoCheck(x, y, z, ext);
if (p == null) return;
AddToBlockDB(p, index, oldBlock, oldExtBlock, block, ext, flags);
BlockDB.Add(p, x, y, z, flags,
oldBlock, oldExtBlock, block, ext);
Player.UndoPos Pos;
Pos.x = x; Pos.y = y; Pos.z = z;
Pos.mapName = this.name;
@ -429,30 +430,6 @@ namespace MCGalaxy {
return x >= 0 && y >= 0 && z >= 0 && x < Width && y < Height && z < Length;
}
public void AddToBlockDB(Player p, int index, byte oldBlock, byte oldExt,
byte block, byte ext, ushort flags) {
if (!UseBlockDB) return;
BlockDBEntry entry;
entry.PlayerID = p.UserID;
entry.TimeDelta = (int)DateTime.UtcNow.Subtract(BlockDB.Epoch).TotalSeconds;
entry.Index = index; // TODO: WRONG WRONG WRONG, use blockdb file's dimensions
entry.OldRaw = oldBlock; entry.NewRaw = block;
entry.Flags = flags;
if (block == Block.custom_block) {
entry.Flags |= BlockDBFlags.NewCustom;
entry.NewRaw = ext;
}
if (oldBlock == Block.custom_block) {
entry.Flags |= BlockDBFlags.OldCustom;
entry.OldRaw = oldExt;
}
lock (blockCacheLock)
blockCache.Add(entry);
}
public void UpdateBlock(Player p, ushort x, ushort y, ushort z,
byte block, byte extBlock, ushort flags) {
byte old = GetTile(x, y, z), oldExt = 0;
@ -460,9 +437,10 @@ namespace MCGalaxy {
bool drawn = (flags & BlockDBFlags.ManualPlace) != 0;
if (!DoBlockchange(p, x, y, z, block, extBlock, drawn)) return;
int index = PosToInt(x, y, z);
AddToBlockDB(p, index, old, oldExt, block, extBlock, flags);
BlockDB.Add(p, x, y, z, flags,
old, oldExt, block, extBlock);
int index = PosToInt(x, y, z);
if (bufferblocks)
BlockQueue.Addblock(p, index, block, extBlock);
else

View File

@ -87,8 +87,7 @@ namespace MCGalaxy {
public List<UndoPos> UndoBuffer = new List<UndoPos>();
public List<Zone> ZoneList;
public bool backedup;
internal readonly object blockCacheLock = new object();
public FastList<BlockDBEntry> blockCache = new FastList<BlockDBEntry>();
[ConfigBool("UseBlockDB", "Other", null, true)]
public bool UseBlockDB = true;
public BlockDB BlockDB;

View File

@ -108,7 +108,7 @@ namespace MCGalaxy {
ListCheck.Clear(); listCheckExists.Clear();
ListUpdate.Clear(); listUpdateExists.Clear();
UndoBuffer.Clear();
blockCache.Clear();
BlockDB.Cache.Clear();
ZoneList.Clear();
lock (queueLock)
@ -374,6 +374,7 @@ namespace MCGalaxy {
} catch (Exception e) {
Server.ErrorLog(e);
}
level.BlockDB.Used = level.UseBlockDB;
BlockDefinition[] defs = BlockDefinition.Load(false, level);
for (int i = 0; i < defs.Length; i++) {

View File

@ -25,10 +25,10 @@ namespace MCGalaxy {
public static class LevelDB {
public unsafe static void SaveBlockDB(Level lvl) {
if (lvl.blockCache.Count == 0) return;
if (!lvl.UseBlockDB) { lvl.blockCache.Clear(); return; }
if (lvl.BlockDB.Cache.Count == 0) return;
if (!lvl.UseBlockDB) { lvl.BlockDB.Cache.Clear(); return; }
lvl.BlockDB.AppendEntries(ref lvl.blockCache, lvl.blockCacheLock);
lvl.BlockDB.WriteEntries();
Server.s.Log("Saved BlockDB changes for:" + lvl.name, true);
}

View File

@ -125,11 +125,15 @@ namespace MCGalaxy {
byte heldBlock = GetActualHeldBlock(out heldExt);
int index = level.PosToInt(x, y, z);
if (doDelete) {
if (DeleteBlock(old, x, y, z, block, extBlock))
level.AddToBlockDB(this, index, old, oldExt, 0, 0, flags);
if (DeleteBlock(old, x, y, z, block, extBlock)) {
level.BlockDB.Add(this, x, y, z, flags,
old, oldExt, 0, 0);
}
} else {
if (PlaceBlock(old, x, y, z, block, extBlock))
level.AddToBlockDB(this, index, old, oldExt, heldBlock, heldExt, flags);
if (PlaceBlock(old, x, y, z, block, extBlock)) {
level.BlockDB.Add(this, x, y, z, flags,
old, oldExt, heldBlock, heldExt);
}
}
}