Skip to content
69 changes: 46 additions & 23 deletions Basis Server/BasisNetworkServer/BasisNetworking/BasisDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ public BasisData(string name, ConcurrentDictionary<string, object> jsonPayload)
public static class BasisPersistentDatabase
{
private static readonly ConcurrentDictionary<string, BasisData> _dataByName = new();
#if NET9_0_OR_GREATER
private static readonly Lock _dataLock = new();
private static readonly Lock _fileLock = new();
#else
private static readonly object _dataLock = new();
private static readonly object _fileLock = new();
#endif

private static string _filePath = "basis_data.json";
private static volatile bool _isDirty = false;
Expand Down Expand Up @@ -72,18 +78,24 @@ public static bool AddOrUpdate(BasisData item)
BNL.LogError("Payload exceeds maximum entry count. (basis database)");
return false;
}
if (!_dataByName.ContainsKey(item.Name) && _dataByName.Count >= BasisNetworkServer.Security.BasisResourceLimitManager.MaxDatabaseEntries)
lock (_dataLock)
{
BNL.LogError("Database entry limit reached; rejecting new entry. (basis database)");
return false;
}
_dataByName.AddOrUpdate(item.Name,
addValueFactory: _ => item,
updateValueFactory: (_, existing) =>
if (_dataByName.TryGetValue(item.Name, out BasisData existing))
{
existing.JsonPayload = new ConcurrentDictionary<string, object>(item.JsonPayload);
return existing;
});
existing.JsonPayload = item.JsonPayload != null
? new ConcurrentDictionary<string, object>(item.JsonPayload)
: new ConcurrentDictionary<string, object>();
}
else
{
if (_dataByName.Count >= BasisNetworkServer.Security.BasisResourceLimitManager.MaxDatabaseEntries)
{
BNL.LogError("Database entry limit reached; rejecting new entry. (basis database)");
return false;
}
_dataByName[item.Name] = item;
}
}

MarkDirty();
return true;
Expand All @@ -103,7 +115,11 @@ public static bool GetByName(string name, out BasisData BasisData)
public static bool Remove(string name)
{
if (string.IsNullOrWhiteSpace(name)) return false;
var result = _dataByName.TryRemove(name, out _);
bool result;
lock (_dataLock)
{
result = _dataByName.TryRemove(name, out _);
}
if (result) MarkDirty();
return result;
}
Expand All @@ -120,16 +136,19 @@ public static void Save()
{
try
{
var list = GetAll().ToList();

using var stream = new FileStream(_filePath, FileMode.Create, FileAccess.Write, FileShare.None);
var serializer = new DataContractJsonSerializer(typeof(List<BasisData>), new DataContractJsonSerializerSettings
lock (_dataLock)
{
UseSimpleDictionaryFormat = true
});
var list = _dataByName.Values.ToList();

using var stream = new FileStream(_filePath, FileMode.Create, FileAccess.Write, FileShare.None);
var serializer = new DataContractJsonSerializer(typeof(List<BasisData>), new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
});

serializer.WriteObject(stream, list);
_isDirty = false;
serializer.WriteObject(stream, list);
_isDirty = false;
}
}
catch (IOException ex)
{
Expand All @@ -155,11 +174,15 @@ public static void Load()

if (serializer.ReadObject(stream) is List<BasisData> loadedData)
{
_dataByName.Clear();
foreach (var item in loadedData)
lock (_dataLock)
{
if (!string.IsNullOrWhiteSpace(item.Name))
_dataByName[item.Name] = item;
_dataByName.Clear();
foreach (var item in loadedData)
{
if (!string.IsNullOrWhiteSpace(item.Name))
_dataByName[item.Name] = item;
}
_isDirty = false;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public static void Simulate()
}

bool hmdGaze = hmdHas && (hmdData.HasWorldRay || hmdData.HasPerEyeAngles);
if (hmdGaze) _lastHmdActiveTime = Time.unscaledTime;
bool oscGaze = oscHas && (oscData.HasWorldRay || oscData.HasPerEyeAngles);

BasisEyeTrackingData merged = default;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading