diff --git a/MCGalaxy/Commands/Information/CmdRankInfo.cs b/MCGalaxy/Commands/Information/CmdRankInfo.cs index c8194e733..f589c7245 100644 --- a/MCGalaxy/Commands/Information/CmdRankInfo.cs +++ b/MCGalaxy/Commands/Information/CmdRankInfo.cs @@ -18,7 +18,7 @@ using System; using System.Collections.Generic; -namespace MCGalaxy.Commands.Info +namespace MCGalaxy.Commands.Info { public sealed class CmdRankInfo : Command2 { diff --git a/MCGalaxy/Database/BlockDB/BlockDB.cs b/MCGalaxy/Database/BlockDB/BlockDB.cs index c84a95d03..0ccff3b79 100644 --- a/MCGalaxy/Database/BlockDB/BlockDB.cs +++ b/MCGalaxy/Database/BlockDB/BlockDB.cs @@ -17,6 +17,7 @@ */ using System; using System.IO; +using MCGalaxy.Events.BlockDBEvents; using MCGalaxy.Util; using MCGalaxy.Maths; @@ -56,8 +57,10 @@ namespace MCGalaxy.DB } void ReadDimensions() { - if (!File.Exists(FilePath)) return; - using (Stream s = OpenRead()) + string path = FilePath; + if (!File.Exists(path)) return; + + using (Stream s = OpenRead(path)) BlockDBFile.ReadHeader(s, out Dims); } @@ -66,8 +69,13 @@ namespace MCGalaxy.DB public void FlushCache() { if (Cache.Head == null) return; - BlockDBFile format = ValidateBackingFile(); - using (Stream s = OpenWrite()) { + string path = FilePath; + bool cancel = false; + OnBlockDBSaveEvent.Call(this, ref path, ref cancel); + if (cancel) return; + + BlockDBFile format = ValidateBackingFile(path); + using (Stream s = OpenWrite(path)) { // This truncates the lower 4 bits off - so e.g. if a power off occurred // and 21 bytes were in the file, this sets the position to byte 16 s.Position = s.Length & ~0x0F; @@ -90,10 +98,11 @@ namespace MCGalaxy.DB /// Outputs all block changes which affect the given coordinates. /// You must lock using Locker.AccquireRead() **before** entering this method. public void FindChangesAt(ushort x, ushort y, ushort z, Action output) { - if (!File.Exists(FilePath)) { FindInMemoryAt(x, y, z, output); return; } + string path = FilePath; + if (!File.Exists(path)) { FindInMemoryAt(x, y, z, output); return; } Vec3U16 dims; - using (Stream s = OpenRead()) { + using (Stream s = OpenRead(path)) { BlockDBFile format = BlockDBFile.ReadHeader(s, out dims); if (x >= dims.X || y >= dims.Y || z >= dims.Z) return; @@ -110,7 +119,8 @@ namespace MCGalaxy.DB BlockDBCacheEntry[] entries = node.Entries; int count = node.Count; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { if (entries[i].Index != index) continue; BlockDBEntry entry = node.Unpack(entries[i]); output(entry); @@ -125,13 +135,14 @@ namespace MCGalaxy.DB public bool FindChangesBy(int[] ids, DateTime start, DateTime end, out Vec3U16 dims, Action output) { int startDelta = ClampDelta(start.Subtract(Epoch)); - int endDelta = ClampDelta(end.Subtract(Epoch)); + int endDelta = ClampDelta(end.Subtract(Epoch)); dims = Dims; if (FindInMemoryBy(ids, startDelta, endDelta, output)) return true; + string path = FilePath; - if (!File.Exists(FilePath)) return false; - using (Stream s = OpenRead()) { + if (!File.Exists(path)) return false; + using (Stream s = OpenRead(path)) { BlockDBFile format = BlockDBFile.ReadHeader(s, out dims); return format.FindChangesBy(s, ids, startDelta, endDelta, output); } @@ -143,12 +154,14 @@ namespace MCGalaxy.DB int count = node.Count; BlockDBCacheEntry[] entries = node.Entries; - for (int i = count - 1; i >= 0; i--) { + for (int i = count - 1; i >= 0; i--) + { BlockDBEntry entry = node.Unpack(entries[i]); if (entry.TimeDelta < startDelta) return true; if (entry.TimeDelta > endDelta) continue; - for (int j = 0; j < ids.Length; j++) { + for (int j = 0; j < ids.Length; j++) + { if (entry.PlayerID != ids[j]) continue; output(entry); break; } @@ -168,41 +181,43 @@ namespace MCGalaxy.DB /// Deletes the backing file on disc if it exists. public void DeleteBackingFile() { + string path = FilePath; + using (IDisposable writeLock = Locker.AccquireWrite()) { - if (!File.Exists(FilePath)) return; - File.Delete(FilePath); + if (!File.Exists(path)) return; + File.Delete(path); } } /// 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. - BlockDBFile ValidateBackingFile() { + BlockDBFile ValidateBackingFile(string path) { + BlockDBFile format = BlockDBFile.V1; Vec3U16 fileDims; - BlockDBFile format = BlockDBFile.V1; - if (!File.Exists(FilePath)) { - using (Stream s = OpenWrite()) { + if (!File.Exists(path)) { + using (Stream s = OpenWrite(path)) { fileDims = Dims; BlockDBFile.WriteHeader(s, fileDims); } } else { - using (Stream s = OpenRead()) { + using (Stream s = OpenRead(path)) { format = BlockDBFile.ReadHeader(s, out fileDims); } if (fileDims.X < Dims.X || fileDims.Y < Dims.Y || fileDims.Z < Dims.Z) { - BlockDBFile.ResizeBackingFile(this); + BlockDBFile.ResizeBackingFile(this, path); } } return format; } - FileStream OpenWrite() { - return new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); + static FileStream OpenWrite(string path) { + return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); } - FileStream OpenRead() { - return new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite); + static FileStream OpenRead(string path) { + return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite); } } } diff --git a/MCGalaxy/Database/BlockDB/BlockDBFile.cs b/MCGalaxy/Database/BlockDB/BlockDBFile.cs index 345fd486a..f9ea89005 100644 --- a/MCGalaxy/Database/BlockDB/BlockDBFile.cs +++ b/MCGalaxy/Database/BlockDB/BlockDBFile.cs @@ -93,12 +93,11 @@ namespace MCGalaxy.DB File.Move(srcPath, dstPath); } - public static void ResizeBackingFile(BlockDB db) { + public static void ResizeBackingFile(BlockDB db, string path) { Logger.Log(LogType.BackgroundActivity, "Resizing BlockDB for " + db.MapName); - string filePath = FilePath(db.MapName); string tempPath = TempPath(db.MapName); - using (Stream src = File.OpenRead(filePath), dst = File.Create(tempPath)) { + using (Stream src = File.OpenRead(path), dst = File.Create(tempPath)) { Vec3U16 dims; ReadHeader(src, out dims); WriteHeader(dst, db.Dims); @@ -123,8 +122,8 @@ namespace MCGalaxy.DB } } - File.Delete(filePath); - File.Move(tempPath, filePath); + File.Delete(path); + File.Move(tempPath, path); } diff --git a/MCGalaxy/Events/BlockDBEvents.cs b/MCGalaxy/Events/BlockDBEvents.cs new file mode 100644 index 000000000..0d70498f9 --- /dev/null +++ b/MCGalaxy/Events/BlockDBEvents.cs @@ -0,0 +1,36 @@ +/* + Copyright 2011 MCForge + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + https://opensource.org/license/ecl-2-0/ + https://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using MCGalaxy.DB; + +namespace MCGalaxy.Events.BlockDBEvents +{ + public delegate void OnBlockDBSave(BlockDB db, ref string path, ref bool cancel); + /// Called whenever a BlockDB is being flushed from memory to disc + public sealed class OnBlockDBSaveEvent : IEvent + { + public static void Call(BlockDB db, ref string path, ref bool cancel) { + IEvent[] items = handlers.Items; + for (int i = 0; i < items.Length; i++) + { + try { items[i].method(db, ref path, ref cancel); } + catch (Exception ex) { LogHandlerException(ex, items[i]); } + } + } + } +} diff --git a/MCGalaxy/MCGalaxy_.csproj b/MCGalaxy/MCGalaxy_.csproj index 81abcba73..0c360a9f5 100644 --- a/MCGalaxy/MCGalaxy_.csproj +++ b/MCGalaxy/MCGalaxy_.csproj @@ -432,6 +432,7 @@ +