Skip to content

Commit

Permalink
Add cancellable event for when BlockDB is being flushed to disc
Browse files Browse the repository at this point in the history
  • Loading branch information
UnknownShadow200 committed Feb 18, 2024
1 parent ffe4707 commit 3a7390d
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 30 deletions.
2 changes: 1 addition & 1 deletion MCGalaxy/Commands/Information/CmdRankInfo.cs
Expand Up @@ -18,7 +18,7 @@
using System;
using System.Collections.Generic;

namespace MCGalaxy.Commands.Info
namespace MCGalaxy.Commands.Info
{
public sealed class CmdRankInfo : Command2
{
Expand Down
63 changes: 39 additions & 24 deletions MCGalaxy/Database/BlockDB/BlockDB.cs
Expand Up @@ -17,6 +17,7 @@
*/
using System;
using System.IO;
using MCGalaxy.Events.BlockDBEvents;
using MCGalaxy.Util;
using MCGalaxy.Maths;

Expand Down Expand Up @@ -56,8 +57,10 @@ public unsafe sealed class BlockDB
}

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);
}

Expand All @@ -66,8 +69,13 @@ public unsafe sealed class BlockDB
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;
Expand All @@ -90,10 +98,11 @@ public unsafe sealed class BlockDB
/// <summary> Outputs all block changes which affect the given coordinates. </summary>
/// <remarks> You must lock using Locker.AccquireRead() **before** entering this method. </remarks>
public void FindChangesAt(ushort x, ushort y, ushort z, Action<BlockDBEntry> 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;

Expand All @@ -110,7 +119,8 @@ public unsafe sealed class BlockDB
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);
Expand All @@ -125,13 +135,14 @@ public unsafe sealed class BlockDB
public bool FindChangesBy(int[] ids, DateTime start, DateTime end,
out Vec3U16 dims, Action<BlockDBEntry> 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);
}
Expand All @@ -143,12 +154,14 @@ public unsafe sealed class BlockDB
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;
}
Expand All @@ -168,41 +181,43 @@ public unsafe sealed class BlockDB

/// <summary> Deletes the backing file on disc if it exists. </summary>
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);
}
}

/// <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>
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);
}
}
}
9 changes: 4 additions & 5 deletions MCGalaxy/Database/BlockDB/BlockDBFile.cs
Expand Up @@ -93,12 +93,11 @@ public unsafe abstract class BlockDBFile
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);
Expand All @@ -123,8 +122,8 @@ public unsafe abstract class BlockDBFile
}
}

File.Delete(filePath);
File.Move(tempPath, filePath);
File.Delete(path);
File.Move(tempPath, path);
}


Expand Down
36 changes: 36 additions & 0 deletions 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);
/// <summary> Called whenever a BlockDB is being flushed from memory to disc </summary>
public sealed class OnBlockDBSaveEvent : IEvent<OnBlockDBSave>
{
public static void Call(BlockDB db, ref string path, ref bool cancel) {
IEvent<OnBlockDBSave>[] 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]); }
}
}
}
}
1 change: 1 addition & 0 deletions MCGalaxy/MCGalaxy_.csproj
Expand Up @@ -432,6 +432,7 @@
<Compile Include="Entity\ModelInfo.cs" />
<Compile Include="Entity\Structs.cs" />
<Compile Include="Entity\TabList.cs" />
<Compile Include="Events\BlockDBEvents.cs" />
<Compile Include="Events\PlayerDBEvents.cs" />
<Compile Include="Events\EconomyEvents.cs" />
<Compile Include="Events\EntityEvents.cs" />
Expand Down

0 comments on commit 3a7390d

Please sign in to comment.