feat: Implement binary serialization for RAM database and mission end save
All checks were successful
Build / Build (push) Successful in 29s
All checks were successful
Build / Build (push) Successful in 29s
This commit introduces binary serialization for the RAM database to improve performance and adds a mission end event handler to ensure data is saved with a backup when the mission ends. - Implemented binary serialization and deserialization for key-values, hash tables, and lists in `Utils.cs`. This replaces the previous text-based serialization, resulting in faster save and load times. - Moved data writing and reading logic from `RAMDb.cs` to `Utils.cs` for better code organization and reusability. - Modified `RAMDb.cs` to use the new binary serialization methods (`ExportToBinary` and `ImportFromBinary`). - Added a mission end event handler in `XEH_preInit_server.sqf` to trigger a forced save with backup when the mission ends. This ensures that data is not lost in case of unexpected server shutdowns. - Updated the extension binaries (`ArmaRAMDb_x64.dll` and `ArmaRAMDb_x64.so`) with the new serialization logic. - Added a static `db` property to the `Main` class to allow access to the `RAMDb` instance from anywhere in the extension. - Modified the `Save` and `Load` methods in `Main.cs` to use the new binary serialization methods. - Updated the `Dispose` method in `RAMDb.cs` to ensure a final save and backup is performed when the object is disposed.
This commit is contained in:
parent
5ed8f74c71
commit
1d5225f279
Binary file not shown.
BIN
ArmaRAMDb_x64.so
BIN
ArmaRAMDb_x64.so
Binary file not shown.
@ -1 +1,6 @@
|
|||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
|
addMissionEventHandler ["Ended", {
|
||||||
|
"ArmaRAMDb" callExtension ["save", [true]];
|
||||||
|
INFO("Mission ended - forced save with backup");
|
||||||
|
}];
|
Binary file not shown.
Binary file not shown.
@ -19,6 +19,9 @@ namespace ArmaRAMDb
|
|||||||
{
|
{
|
||||||
private const string ARDB_VERSION = "1.0.0";
|
private const string ARDB_VERSION = "1.0.0";
|
||||||
public const int ARDB_BUFFERSIZE = 10240;
|
public const int ARDB_BUFFERSIZE = 10240;
|
||||||
|
#pragma warning disable CA2211 // Non-constant fields should not be visible
|
||||||
|
public static RAMDb db;
|
||||||
|
#pragma warning restore CA2211 // Non-constant fields should not be visible
|
||||||
public static readonly string DEFAULT_ARDB_PATH = $"@ramdb{Path.DirectorySeparatorChar}ArmaRAMDb.ardb";
|
public static readonly string DEFAULT_ARDB_PATH = $"@ramdb{Path.DirectorySeparatorChar}ArmaRAMDb.ardb";
|
||||||
public static string ARDB_LOGFOLDER { get; private set; } = $"{Path.DirectorySeparatorChar}@ramdb{Path.DirectorySeparatorChar}logs";
|
public static string ARDB_LOGFOLDER { get; private set; } = $"{Path.DirectorySeparatorChar}@ramdb{Path.DirectorySeparatorChar}logs";
|
||||||
public static bool ARDB_DEBUG {get; private set; } = false;
|
public static bool ARDB_DEBUG {get; private set; } = false;
|
||||||
@ -82,11 +85,12 @@ namespace ArmaRAMDb
|
|||||||
Log($"Config file found! Context Mode: {ARDB_CONTEXTLOG}! Debug Mode: {ARDB_DEBUG}! " +
|
Log($"Config file found! Context Mode: {ARDB_CONTEXTLOG}! Debug Mode: {ARDB_DEBUG}! " +
|
||||||
$"Auto Backup: {RAMDb.AutoBackupEnabled} (every {RAMDb.BackupFrequencyMinutes} min, keep {RAMDb.MaxBackupsToKeep})", "action");
|
$"Auto Backup: {RAMDb.AutoBackupEnabled} (every {RAMDb.BackupFrequencyMinutes} min, keep {RAMDb.MaxBackupsToKeep})", "action");
|
||||||
|
|
||||||
|
db ??= new RAMDb();
|
||||||
|
|
||||||
// First, load any existing RDB file
|
// First, load any existing RDB file
|
||||||
var db = new RAMDb();
|
|
||||||
if (File.Exists(Path.Combine(Environment.CurrentDirectory, DEFAULT_ARDB_PATH)))
|
if (File.Exists(Path.Combine(Environment.CurrentDirectory, DEFAULT_ARDB_PATH)))
|
||||||
{
|
{
|
||||||
db.ImportFromArdb();
|
db.ImportFromBinary();
|
||||||
ARDB_ISLOADED = true;
|
ARDB_ISLOADED = true;
|
||||||
Log("Existing ARDB data loaded during initialization", "action");
|
Log("Existing ARDB data loaded during initialization", "action");
|
||||||
}
|
}
|
||||||
@ -321,7 +325,7 @@ namespace ArmaRAMDb
|
|||||||
WriteOutput(output, "Data loaded");
|
WriteOutput(output, "Data loaded");
|
||||||
return 100;
|
return 100;
|
||||||
case "save":
|
case "save":
|
||||||
Save(args);
|
Save(args, argc);
|
||||||
WriteOutput(output, "Data saved");
|
WriteOutput(output, "Data saved");
|
||||||
return 100;
|
return 100;
|
||||||
case "set":
|
case "set":
|
||||||
@ -384,23 +388,23 @@ namespace ArmaRAMDb
|
|||||||
Marshal.Copy(bytes, 0, (nint)output, bytes.Length);
|
Marshal.Copy(bytes, 0, (nint)output, bytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Save(List<string> args)
|
private static void Save(List<string> args, int argc)
|
||||||
{
|
{
|
||||||
var db = new RAMDb();
|
db ??= new RAMDb();
|
||||||
|
|
||||||
// Convert string to boolean properly
|
// Convert string to boolean properly
|
||||||
bool createBackup = args.Count > 0 &&
|
bool createBackup = argc > 0 &&
|
||||||
(args[0].Trim('"').Equals("true", StringComparison.CurrentCultureIgnoreCase) || args[0].Trim('"') == "1");
|
(args[0].Trim('"').Equals("true", StringComparison.CurrentCultureIgnoreCase) || args[0].Trim('"') == "1");
|
||||||
|
|
||||||
db.ExportToArdb(createBackup);
|
db.ExportToBinary(createBackup);
|
||||||
Log($"Data saved to ARDB{(createBackup ? " with backup" : "")}", "action");
|
Log($"Data saved to ARDB{(createBackup ? " with backup" : "")}", "action");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Load()
|
private static void Load()
|
||||||
{
|
{
|
||||||
var db = new RAMDb();
|
db ??= new RAMDb();
|
||||||
|
|
||||||
db.ImportFromArdb();
|
db.ImportFromBinary();
|
||||||
ARDB_ISLOADED = true;
|
ARDB_ISLOADED = true;
|
||||||
Log("Data loaded from ARDB", "action");
|
Log("Data loaded from ARDB", "action");
|
||||||
}
|
}
|
||||||
@ -442,7 +446,7 @@ namespace ArmaRAMDb
|
|||||||
await HashStore.HashGet(STEAMID, args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'), args[3].Trim('"'));
|
await HashStore.HashGet(STEAMID, args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'), args[3].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for HashGet operation", "warning");
|
Log($"Unexpected argument count: {argc} for HashGet operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -465,7 +469,7 @@ namespace ArmaRAMDb
|
|||||||
await HashStore.HashGet(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'), args[4].Trim('"'));
|
await HashStore.HashGet(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'), args[4].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for HashGetId operation", "warning");
|
Log($"Unexpected argument count: {argc} for HashGetId operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -488,7 +492,7 @@ namespace ArmaRAMDb
|
|||||||
await HashStore.HashGetAllAsync(STEAMID, args[0].Trim('"'), _uniqueID, args[1].Trim('"'), args[2].Trim('"'));
|
await HashStore.HashGetAllAsync(STEAMID, args[0].Trim('"'), _uniqueID, args[1].Trim('"'), args[2].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for HashGetAll operation", "warning");
|
Log($"Unexpected argument count: {argc} for HashGetAll operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -511,7 +515,7 @@ namespace ArmaRAMDb
|
|||||||
await HashStore.HashGetAllAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2], args[3].Trim('"'));
|
await HashStore.HashGetAllAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2], args[3].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for HashGetAllId operation", "warning");
|
Log($"Unexpected argument count: {argc} for HashGetAllId operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -555,7 +559,7 @@ namespace ArmaRAMDb
|
|||||||
await HashStore.HashSetAsync(STEAMID, args[0].Trim('"'), args[1].Trim('"'));
|
await HashStore.HashSetAsync(STEAMID, args[0].Trim('"'), args[1].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Invalid argument count: {argc} for HashSet operation", "warning");
|
Log($"Invalid argument count: {argc} for HashSet operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -579,7 +583,7 @@ namespace ArmaRAMDb
|
|||||||
await HashStore.HashSetAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'));
|
await HashStore.HashSetAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Invalid argument count: {argc} for HashSetId operation", "warning");
|
Log($"Invalid argument count: {argc} for HashSetId operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -601,7 +605,7 @@ namespace ArmaRAMDb
|
|||||||
await ListStore.ListAddAsync(args[0].Trim('"'), args[1].Trim('"'));
|
await ListStore.ListAddAsync(args[0].Trim('"'), args[1].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Invalid argument count: {argc} for ListAdd operation", "warning");
|
Log($"Invalid argument count: {argc} for ListAdd operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -643,7 +647,7 @@ namespace ArmaRAMDb
|
|||||||
await ListStore.ListIndexAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'), args[4].Trim('"'));
|
await ListStore.ListIndexAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'), args[4].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for ListIdx operation", "warning");
|
Log($"Unexpected argument count: {argc} for ListIdx operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -666,7 +670,7 @@ namespace ArmaRAMDb
|
|||||||
await ListStore.ListRangeAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), args[3].Trim('"'), _uniqueID, args[4].Trim('"'), args[5].Trim('"'));
|
await ListStore.ListRangeAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), args[3].Trim('"'), _uniqueID, args[4].Trim('"'), args[5].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for ListRng operation", "warning");
|
Log($"Unexpected argument count: {argc} for ListRng operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -709,7 +713,7 @@ namespace ArmaRAMDb
|
|||||||
await KeyValueStore.GetAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'), args[3].Trim('"'));
|
await KeyValueStore.GetAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'), args[3].Trim('"'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Main.Log($"Unexpected argument count: {argc} for Get operation", "warning");
|
Log($"Unexpected argument count: {argc} for Get operation", "warning");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -727,7 +731,7 @@ namespace ArmaRAMDb
|
|||||||
|
|
||||||
private static string HandleListBackupsOperation()
|
private static string HandleListBackupsOperation()
|
||||||
{
|
{
|
||||||
var db = new RAMDb();
|
db ??= new RAMDb();
|
||||||
var backups = db.ListBackups();
|
var backups = db.ListBackups();
|
||||||
|
|
||||||
if (backups.Count > 0)
|
if (backups.Count > 0)
|
||||||
@ -752,7 +756,7 @@ namespace ArmaRAMDb
|
|||||||
if (args.Count < 1) return false;
|
if (args.Count < 1) return false;
|
||||||
|
|
||||||
string backupFileName = args[0].Trim('"');
|
string backupFileName = args[0].Trim('"');
|
||||||
var db = new RAMDb();
|
db ??= new RAMDb();
|
||||||
var backups = db.ListBackups();
|
var backups = db.ListBackups();
|
||||||
|
|
||||||
// Find the full path based on filename
|
// Find the full path based on filename
|
||||||
@ -774,7 +778,7 @@ namespace ArmaRAMDb
|
|||||||
if (args.Count < 1) return false;
|
if (args.Count < 1) return false;
|
||||||
|
|
||||||
string backupFileName = args[0].Trim('"');
|
string backupFileName = args[0].Trim('"');
|
||||||
var db = new RAMDb();
|
db ??= new RAMDb();
|
||||||
var backups = db.ListBackups();
|
var backups = db.ListBackups();
|
||||||
|
|
||||||
// Find the full path based on filename
|
// Find the full path based on filename
|
||||||
|
@ -4,7 +4,7 @@ using System.Collections.Concurrent;
|
|||||||
namespace ArmaRAMDb
|
namespace ArmaRAMDb
|
||||||
#pragma warning restore IDE0130 // Namespace does not match folder structure
|
#pragma warning restore IDE0130 // Namespace does not match folder structure
|
||||||
{
|
{
|
||||||
internal class RAMDb(string ardbPath = null) : IDisposable
|
public class RAMDb(string ardbPath = null) : IDisposable
|
||||||
{
|
{
|
||||||
private readonly string _ardbPath = Path.Combine(Environment.CurrentDirectory, ardbPath ?? Main.DEFAULT_ARDB_PATH);
|
private readonly string _ardbPath = Path.Combine(Environment.CurrentDirectory, ardbPath ?? Main.DEFAULT_ARDB_PATH);
|
||||||
public static readonly ConcurrentDictionary<string, string> _keyValues = new();
|
public static readonly ConcurrentDictionary<string, string> _keyValues = new();
|
||||||
@ -16,7 +16,7 @@ namespace ArmaRAMDb
|
|||||||
public static int MaxBackupsToKeep { get; set; } = 10;
|
public static int MaxBackupsToKeep { get; set; } = 10;
|
||||||
private static Timer _backupTimer;
|
private static Timer _backupTimer;
|
||||||
|
|
||||||
public void ImportFromArdb()
|
public void ImportFromBinary()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ namespace ArmaRAMDb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExportToArdb(bool createBackup = false)
|
public void ExportToBinary(bool createBackup = false)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -111,7 +111,7 @@ namespace ArmaRAMDb
|
|||||||
{
|
{
|
||||||
writer.Write(1);
|
writer.Write(1);
|
||||||
|
|
||||||
WriteDataToBinaryWriter(writer);
|
Utils.WriteDataToBinaryWriter(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createBackup)
|
if (createBackup)
|
||||||
@ -126,7 +126,7 @@ namespace ArmaRAMDb
|
|||||||
using (var stream = new FileStream(backupPath, FileMode.Create))
|
using (var stream = new FileStream(backupPath, FileMode.Create))
|
||||||
using (var writer = new BinaryWriter(stream))
|
using (var writer = new BinaryWriter(stream))
|
||||||
{
|
{
|
||||||
WriteDataToBinaryWriter(writer);
|
Utils.WriteDataToBinaryWriter(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Main.Log($"Created backup at: {backupPath}", "debug");
|
Main.Log($"Created backup at: {backupPath}", "debug");
|
||||||
@ -140,44 +140,6 @@ namespace ArmaRAMDb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteDataToBinaryWriter(BinaryWriter writer)
|
|
||||||
{
|
|
||||||
// Write KeyValues
|
|
||||||
writer.Write(_keyValues.Count);
|
|
||||||
foreach (var pair in _keyValues)
|
|
||||||
{
|
|
||||||
writer.Write(pair.Key);
|
|
||||||
writer.Write(pair.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write HashTables
|
|
||||||
writer.Write(_hashTables.Count);
|
|
||||||
foreach (var table in _hashTables)
|
|
||||||
{
|
|
||||||
writer.Write(table.Key);
|
|
||||||
writer.Write(table.Value.Count);
|
|
||||||
|
|
||||||
foreach (var entry in table.Value)
|
|
||||||
{
|
|
||||||
writer.Write(entry.Key);
|
|
||||||
writer.Write(entry.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write Lists
|
|
||||||
writer.Write(_lists.Count);
|
|
||||||
foreach (var list in _lists)
|
|
||||||
{
|
|
||||||
writer.Write(list.Key);
|
|
||||||
writer.Write(list.Value.Count);
|
|
||||||
|
|
||||||
foreach (var item in list.Value)
|
|
||||||
{
|
|
||||||
writer.Write(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<string> ListBackups()
|
public List<string> ListBackups()
|
||||||
{
|
{
|
||||||
string backupDirectory = Path.Combine(Path.GetDirectoryName(_ardbPath), "backups");
|
string backupDirectory = Path.Combine(Path.GetDirectoryName(_ardbPath), "backups");
|
||||||
@ -211,7 +173,7 @@ namespace ArmaRAMDb
|
|||||||
_hashTables.Clear();
|
_hashTables.Clear();
|
||||||
_lists.Clear();
|
_lists.Clear();
|
||||||
|
|
||||||
ReadDataFromBinaryReader(reader);
|
Utils.ReadDataFromBinaryReader(reader);
|
||||||
|
|
||||||
Main.Log($"Restored from backup: {backupPath}", "info");
|
Main.Log($"Restored from backup: {backupPath}", "info");
|
||||||
return true;
|
return true;
|
||||||
@ -225,62 +187,6 @@ namespace ArmaRAMDb
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadDataFromBinaryReader(BinaryReader reader)
|
|
||||||
{
|
|
||||||
// Read KeyValues
|
|
||||||
int keyValueCount = reader.ReadInt32();
|
|
||||||
for (int i = 0; i < keyValueCount; i++)
|
|
||||||
{
|
|
||||||
string key = reader.ReadString();
|
|
||||||
string value = reader.ReadString();
|
|
||||||
_keyValues.TryAdd(key, value);
|
|
||||||
Main.Log($"Loaded key-value: {key} = {value[..Math.Min(50, value.Length)]}...", "debug");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read HashTables
|
|
||||||
int tableCount = reader.ReadInt32();
|
|
||||||
for (int i = 0; i < tableCount; i++)
|
|
||||||
{
|
|
||||||
string tableName = reader.ReadString();
|
|
||||||
Main.Log($"Loading table: {tableName}", "debug");
|
|
||||||
|
|
||||||
var concurrentDict = new ConcurrentDictionary<string, string>();
|
|
||||||
int entryCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int j = 0; j < entryCount; j++)
|
|
||||||
{
|
|
||||||
string key = reader.ReadString();
|
|
||||||
string value = reader.ReadString();
|
|
||||||
concurrentDict.TryAdd(key, value);
|
|
||||||
Main.Log($"Loaded entry: {key} = {value[..Math.Min(50, value.Length)]}...", "debug");
|
|
||||||
}
|
|
||||||
|
|
||||||
_hashTables.TryAdd(tableName, concurrentDict);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read Lists
|
|
||||||
int listCount = reader.ReadInt32();
|
|
||||||
for (int i = 0; i < listCount; i++)
|
|
||||||
{
|
|
||||||
string listName = reader.ReadString();
|
|
||||||
Main.Log($"Loading list: {listName}", "debug");
|
|
||||||
|
|
||||||
var items = new List<string>();
|
|
||||||
int itemCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int j = 0; j < itemCount; j++)
|
|
||||||
{
|
|
||||||
string value = reader.ReadString();
|
|
||||||
items.Add(value);
|
|
||||||
Main.Log($"Loaded item: {value[..Math.Min(50, value.Length)]}...", "debug");
|
|
||||||
}
|
|
||||||
|
|
||||||
_lists.TryAdd(listName, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
Main.Log("ARDB import complete", "debug");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InitializeAutoBackup()
|
public static void InitializeAutoBackup()
|
||||||
{
|
{
|
||||||
if (AutoBackupEnabled)
|
if (AutoBackupEnabled)
|
||||||
@ -299,8 +205,7 @@ namespace ArmaRAMDb
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var db = new RAMDb();
|
Main.db.ExportToBinary(true);
|
||||||
db.ExportToArdb(true);
|
|
||||||
|
|
||||||
ManageBackupRotation();
|
ManageBackupRotation();
|
||||||
|
|
||||||
@ -316,8 +221,7 @@ namespace ArmaRAMDb
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var db = new RAMDb();
|
var backups = Main.db.ListBackups();
|
||||||
var backups = db.ListBackups();
|
|
||||||
|
|
||||||
if (backups.Count > MaxBackupsToKeep)
|
if (backups.Count > MaxBackupsToKeep)
|
||||||
{
|
{
|
||||||
@ -336,8 +240,17 @@ namespace ArmaRAMDb
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_backupTimer?.Dispose();
|
try
|
||||||
ExportToArdb(createBackup: true);
|
{
|
||||||
|
ExportToBinary(true);
|
||||||
|
_backupTimer?.Dispose();
|
||||||
|
Main.Log("RAMDb disposed with final save and backup", "action");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Main.Log($"Error during final save on disposal: {ex.Message}", "error");
|
||||||
|
}
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
#pragma warning disable IDE0130 // Namespace does not match folder structure
|
#pragma warning disable IDE0130 // Namespace does not match folder structure
|
||||||
namespace ArmaRAMDb
|
namespace ArmaRAMDb
|
||||||
@ -44,6 +45,100 @@ namespace ArmaRAMDb
|
|||||||
return DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
return DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void WriteDataToBinaryWriter(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
// Write KeyValues
|
||||||
|
writer.Write(RAMDb._keyValues.Count);
|
||||||
|
foreach (var pair in RAMDb._keyValues)
|
||||||
|
{
|
||||||
|
writer.Write(pair.Key);
|
||||||
|
writer.Write(pair.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write HashTables
|
||||||
|
writer.Write(RAMDb._hashTables.Count);
|
||||||
|
foreach (var table in RAMDb._hashTables)
|
||||||
|
{
|
||||||
|
writer.Write(table.Key);
|
||||||
|
writer.Write(table.Value.Count);
|
||||||
|
|
||||||
|
foreach (var entry in table.Value)
|
||||||
|
{
|
||||||
|
writer.Write(entry.Key);
|
||||||
|
writer.Write(entry.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write Lists
|
||||||
|
writer.Write(RAMDb._lists.Count);
|
||||||
|
foreach (var list in RAMDb._lists)
|
||||||
|
{
|
||||||
|
writer.Write(list.Key);
|
||||||
|
writer.Write(list.Value.Count);
|
||||||
|
|
||||||
|
foreach (var item in list.Value)
|
||||||
|
{
|
||||||
|
writer.Write(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ReadDataFromBinaryReader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
// Read KeyValues
|
||||||
|
int keyValueCount = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < keyValueCount; i++)
|
||||||
|
{
|
||||||
|
string key = reader.ReadString();
|
||||||
|
string value = reader.ReadString();
|
||||||
|
RAMDb._keyValues.TryAdd(key, value);
|
||||||
|
Main.Log($"Loaded key-value: {key} = {value[..Math.Min(50, value.Length)]}...", "debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read HashTables
|
||||||
|
int tableCount = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < tableCount; i++)
|
||||||
|
{
|
||||||
|
string tableName = reader.ReadString();
|
||||||
|
Main.Log($"Loading table: {tableName}", "debug");
|
||||||
|
|
||||||
|
var concurrentDict = new ConcurrentDictionary<string, string>();
|
||||||
|
int entryCount = reader.ReadInt32();
|
||||||
|
|
||||||
|
for (int j = 0; j < entryCount; j++)
|
||||||
|
{
|
||||||
|
string key = reader.ReadString();
|
||||||
|
string value = reader.ReadString();
|
||||||
|
concurrentDict.TryAdd(key, value);
|
||||||
|
Main.Log($"Loaded entry: {key} = {value[..Math.Min(50, value.Length)]}...", "debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
RAMDb._hashTables.TryAdd(tableName, concurrentDict);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Lists
|
||||||
|
int listCount = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < listCount; i++)
|
||||||
|
{
|
||||||
|
string listName = reader.ReadString();
|
||||||
|
Main.Log($"Loading list: {listName}", "debug");
|
||||||
|
|
||||||
|
var items = new List<string>();
|
||||||
|
int itemCount = reader.ReadInt32();
|
||||||
|
|
||||||
|
for (int j = 0; j < itemCount; j++)
|
||||||
|
{
|
||||||
|
string value = reader.ReadString();
|
||||||
|
items.Add(value);
|
||||||
|
Main.Log($"Loaded item: {value[..Math.Min(50, value.Length)]}...", "debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
RAMDb._lists.TryAdd(listName, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main.Log("ARDB import complete", "debug");
|
||||||
|
}
|
||||||
|
|
||||||
public static void CheckByteCount(string uniqueId, string data, string function, string entity, bool call, int bufferSize)
|
public static void CheckByteCount(string uniqueId, string data, string function, string entity, bool call, int bufferSize)
|
||||||
{
|
{
|
||||||
if (Encoding.UTF8.GetByteCount(data) <= bufferSize)
|
if (Encoding.UTF8.GetByteCount(data) <= bufferSize)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user