generated from Nexus-Mods/NexusMods.App.Template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Can join into child entities and link entities via reverse lookups
- Loading branch information
Showing
21 changed files
with
503 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
src/NexusMods.EventSourcing.Abstractions/Models/ReverseLookupAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System; | ||
|
||
namespace NexusMods.EventSourcing.Abstractions.Models; | ||
|
||
/// <summary> | ||
/// Defines a backwards lookup attribute | ||
/// </summary> | ||
public class ReverseLookupAttribute<TAttribute> : Attribute | ||
where TAttribute : ScalarAttribute<TAttribute, EntityId> | ||
{ | ||
|
||
} |
31 changes: 31 additions & 0 deletions
31
src/NexusMods.EventSourcing.DatomStore/BuiltInSerializers/EntityIdSerializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Buffers.Binary; | ||
using NexusMods.EventSourcing.Abstractions; | ||
|
||
namespace NexusMods.EventSourcing.DatomStore.BuiltInSerializers; | ||
|
||
public class EntityIdSerialzer : IValueSerializer<EntityId> | ||
{ | ||
public Type NativeType => typeof(EntityId); | ||
|
||
public static readonly UInt128 Id = "E2C3185E-C082-4641-B25E-7CEC803A2F48".ToUInt128Guid(); | ||
public UInt128 UniqueId => Id; | ||
public int Compare(ReadOnlySpan<byte> a, ReadOnlySpan<byte> b) | ||
{ | ||
return BinaryPrimitives.ReadUInt64LittleEndian(a).CompareTo(BinaryPrimitives.ReadUInt64LittleEndian(b)); | ||
} | ||
|
||
public void Write<TWriter>(EntityId value, TWriter buffer) where TWriter : IBufferWriter<byte> | ||
{ | ||
var span = buffer.GetSpan(8); | ||
BinaryPrimitives.WriteUInt64LittleEndian(span, value.Value); | ||
buffer.Advance(8); | ||
} | ||
|
||
public int Read(ReadOnlySpan<byte> buffer, out EntityId val) | ||
{ | ||
val = EntityId.From(BinaryPrimitives.ReadUInt64LittleEndian(buffer)); | ||
return 8; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/NexusMods.EventSourcing.DatomStore/BuiltInSerializers/TxIdSerializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Buffers.Binary; | ||
using NexusMods.EventSourcing.Abstractions; | ||
namespace NexusMods.EventSourcing.DatomStore.BuiltInSerializers; | ||
|
||
public class TxIdSerializer : IValueSerializer<TxId> | ||
{ | ||
public Type NativeType => typeof(TxId); | ||
|
||
public static readonly UInt128 Id = "BB2B2BAF-9AA8-4DB0-8BFC-A0A853ED9BA0".ToUInt128Guid(); | ||
public UInt128 UniqueId => Id; | ||
public int Compare(ReadOnlySpan<byte> a, ReadOnlySpan<byte> b) | ||
{ | ||
return BinaryPrimitives.ReadUInt64LittleEndian(a).CompareTo(BinaryPrimitives.ReadUInt64LittleEndian(b)); | ||
} | ||
|
||
public void Write<TWriter>(TxId value, TWriter buffer) where TWriter : IBufferWriter<byte> | ||
{ | ||
var span = buffer.GetSpan(8); | ||
BinaryPrimitives.WriteUInt64LittleEndian(span, value.Value); | ||
buffer.Advance(8); | ||
} | ||
|
||
public int Read(ReadOnlySpan<byte> buffer, out TxId val) | ||
{ | ||
val = TxId.From(BinaryPrimitives.ReadUInt64LittleEndian(buffer)); | ||
return 8; | ||
} | ||
} |
135 changes: 135 additions & 0 deletions
135
src/NexusMods.EventSourcing.DatomStore/Indexes/AVTEIndex.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
using NexusMods.EventSourcing.Abstractions; | ||
using Reloaded.Memory.Extensions; | ||
using RocksDbSharp; | ||
|
||
namespace NexusMods.EventSourcing.DatomStore.Indexes; | ||
|
||
public class AVTEIndex(AttributeRegistry registry) : | ||
AIndexDefinition<AVTEIndex>(registry, "avte"), IComparatorIndex<AVTEIndex> | ||
{ | ||
public static unsafe int Compare(AIndexDefinition<AVTEIndex> idx, KeyHeader* a, uint aLength, KeyHeader* b, uint bLength) | ||
{ | ||
// Attribute, Value, TX, Entity | ||
var cmp = KeyHeader.CompareAttribute(a, b); | ||
if (cmp != 0) return cmp; | ||
cmp = KeyHeader.CompareValues(idx.Registry, a, aLength, b, bLength); | ||
if (cmp != 0) return cmp; | ||
cmp = KeyHeader.CompareTx(a, b); | ||
if (cmp != 0) return cmp; | ||
cmp = KeyHeader.CompareEntity(a, b); | ||
if (cmp != 0) return cmp; | ||
return KeyHeader.CompareIsAssert(a, b); | ||
} | ||
|
||
public unsafe struct AVTEIterator : IDisposable | ||
{ | ||
private readonly KeyHeader* _key; | ||
private KeyHeader* _current; | ||
private UIntPtr _currentLength; | ||
private readonly Iterator _iterator; | ||
private readonly AttributeRegistry _registry; | ||
private bool _needsSeek; | ||
|
||
public AVTEIterator(ulong txId, AttributeRegistry registry, AVTEIndex idx) | ||
{ | ||
_registry = registry; | ||
_iterator = idx.Db.NewIterator(idx.ColumnFamilyHandle); | ||
_key = (KeyHeader*)Marshal.AllocHGlobal(KeyHeader.Size); | ||
_key->Entity = ulong.MaxValue; | ||
_key->AttributeId = ulong.MaxValue; | ||
_key->Tx = txId; | ||
_key->IsAssert = true; | ||
_needsSeek = true; | ||
} | ||
|
||
|
||
public void Set<TAttribute>() where TAttribute : IAttribute | ||
{ | ||
_key->Entity = ulong.MaxValue; | ||
_key->AttributeId = _registry.GetAttributeId<TAttribute>(); | ||
_needsSeek = true; | ||
} | ||
|
||
public IDatom Current | ||
{ | ||
get | ||
{ | ||
Debug.Assert(!_needsSeek, "Must call Next() before accessing Current"); | ||
var currentValue = new ReadOnlySpan<byte>((byte*)_current + KeyHeader.Size, (int)_currentLength - KeyHeader.Size); | ||
return _registry.ReadDatom(ref *_current, currentValue); | ||
} | ||
} | ||
|
||
public EntityId EntityId => EntityId.From(_current->Entity); | ||
|
||
public TValue GetValue<TAttribute, TValue>() | ||
where TAttribute : IAttribute<TValue> | ||
{ | ||
Debug.Assert(!_needsSeek, "Must call Next() before accessing GetValue"); | ||
var currentValue = new ReadOnlySpan<byte>((byte*)_current + KeyHeader.Size, (int)_currentLength - KeyHeader.Size); | ||
return _registry.ReadValue<TAttribute, TValue>(ref *_current, currentValue); | ||
|
||
} | ||
|
||
public ulong AttributeId | ||
{ | ||
get | ||
{ | ||
Debug.Assert(!_needsSeek, "Must call Next() before accessing AttributeId"); | ||
return _current->AttributeId; | ||
} | ||
} | ||
|
||
public ReadOnlySpan<byte> ValueSpan => _iterator.GetKeySpan().SliceFast(KeyHeader.Size); | ||
|
||
public bool Next() | ||
{ | ||
if (_needsSeek) | ||
{ | ||
_iterator.SeekForPrev((byte*)_key, KeyHeader.Size); | ||
_needsSeek = false; | ||
} | ||
else | ||
{ | ||
_key->Entity = _current->Entity - 1; | ||
_iterator.Prev(); | ||
} | ||
|
||
while (true) | ||
{ | ||
|
||
if (!_iterator.Valid()) return false; | ||
|
||
_current = (KeyHeader*)Native.Instance.rocksdb_iter_key(_iterator.Handle, out _currentLength); | ||
|
||
Debug.Assert(_currentLength < KeyHeader.Size, "Key length is less than KeyHeader.Size"); | ||
|
||
if (_current->AttributeId != _key->AttributeId) | ||
return false; | ||
|
||
if (_current->Tx > _key->Tx) | ||
{ | ||
_iterator.Prev(); | ||
continue; | ||
} | ||
|
||
if (_current->Entity > _key->Entity) | ||
{ | ||
_iterator.Prev(); | ||
continue; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
public void Dispose() | ||
{ | ||
_iterator.Dispose(); | ||
Marshal.FreeHGlobal((IntPtr)_key); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.