From 4fc6670f803d3afec632c8a90ff82f1ecbfa9622 Mon Sep 17 00:00:00 2001 From: halgari Date: Mon, 11 Nov 2024 10:57:43 -0700 Subject: [PATCH 1/4] Work on removing the insane amout of compile time warnings in this project --- NexusMods.MnemonicDB.sln.DotSettings | 1 + .../NexusMods.MnemonicDB.Benchmarks.csproj | 6 +- .../OneBillionDatomsTest.csproj | 2 +- .../Attribute.cs | 5 ++ .../AttributeCache.cs | 3 + .../Attributes/BackReferenceAttribute.cs | 2 + .../DatomComparators/AEVTComparator.cs | 1 - .../DatomComparators/EAVTComparator.cs | 2 - .../DatomKey.cs | 1 + .../DatomStoreSettings.cs | 3 + .../DependencyInjectionExtensions.cs | 4 - .../EnumerableExtensions.cs | 3 + .../Exceptions/UnsupportedLowLevelReadType.cs | 9 --- .../UnsupportedLowLevelTypeException.cs | 12 --- .../GlobalComparer.cs | 3 + .../IndexSegments/IndexSegmentBuilder.cs | 4 + .../IndexType.cs | 45 +++++++++-- .../Internals/KeyPrefix.cs | 23 +++--- .../NexusMods.MnemonicDB.Abstractions.csproj | 10 +-- .../Query/ObservableDatoms.cs | 6 +- .../ValueSerializers/NullSerializer.cs | 7 +- .../AnalyzedAttribute.cs | 2 +- .../AnalyzedBackReferenceAttribute.cs | 2 +- .../Analyzer.cs | 2 +- .../AttributeFlags.cs | 2 +- .../Consts.cs | 2 +- .../ModelAnalyzer.cs | 6 +- ...exusMods.MnemonicDB.SourceGenerator.csproj | 3 +- .../SyntaxReceiver.cs | 2 +- .../Template.weave | 74 +++++++++++++++++-- .../NexusMods.MnemonicDB.csproj | 12 +-- ...ds.MnemonicDB.SourceGenerator.Tests.csproj | 25 ++++++- .../NexusMods.MnemonicDB.Storage.Tests.csproj | 14 ++-- .../NexusMods.MnemonicDB.TestModel.csproj | 18 ++--- .../NexusMods.MnemonicDB.Tests.csproj | 14 ++-- 35 files changed, 218 insertions(+), 112 deletions(-) delete mode 100644 src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelReadType.cs delete mode 100644 src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelTypeException.cs diff --git a/NexusMods.MnemonicDB.sln.DotSettings b/NexusMods.MnemonicDB.sln.DotSettings index a8efa4ec..ce614274 100644 --- a/NexusMods.MnemonicDB.sln.DotSettings +++ b/NexusMods.MnemonicDB.sln.DotSettings @@ -1,3 +1,4 @@  + EAVT True True \ No newline at end of file diff --git a/benchmarks/NexusMods.MnemonicDB.Benchmarks/NexusMods.MnemonicDB.Benchmarks.csproj b/benchmarks/NexusMods.MnemonicDB.Benchmarks/NexusMods.MnemonicDB.Benchmarks.csproj index 2231a4a0..9812dd54 100644 --- a/benchmarks/NexusMods.MnemonicDB.Benchmarks/NexusMods.MnemonicDB.Benchmarks.csproj +++ b/benchmarks/NexusMods.MnemonicDB.Benchmarks/NexusMods.MnemonicDB.Benchmarks.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/benchmarks/OneBillionDatomsTest/OneBillionDatomsTest.csproj b/benchmarks/OneBillionDatomsTest/OneBillionDatomsTest.csproj index 50f585ce..8bca1457 100644 --- a/benchmarks/OneBillionDatomsTest/OneBillionDatomsTest.csproj +++ b/benchmarks/OneBillionDatomsTest/OneBillionDatomsTest.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/NexusMods.MnemonicDB.Abstractions/Attribute.cs b/src/NexusMods.MnemonicDB.Abstractions/Attribute.cs index 3ab95fd8..54868d8b 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Attribute.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Attribute.cs @@ -17,6 +17,11 @@ public abstract class Attribute : IReadableAttribute where TSerializer : IValueSerializer { + + /// + /// Constructor used when subclassing, provides a few of the important flags + /// and the name of the attribute + /// protected Attribute( string ns, string name, diff --git a/src/NexusMods.MnemonicDB.Abstractions/AttributeCache.cs b/src/NexusMods.MnemonicDB.Abstractions/AttributeCache.cs index 9b58e974..21f37e05 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/AttributeCache.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/AttributeCache.cs @@ -22,6 +22,9 @@ public sealed class AttributeCache private ValueTag[] _valueTags; private BitArray _isNoHistory; + /// + /// Constructs a new cache, populated with the hardcoded attribute definitions + /// public AttributeCache() { var maxId = AttributeDefinition.HardcodedIds.Values.Max() + 1; diff --git a/src/NexusMods.MnemonicDB.Abstractions/Attributes/BackReferenceAttribute.cs b/src/NexusMods.MnemonicDB.Abstractions/Attributes/BackReferenceAttribute.cs index f4c3730d..c33a5627 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Attributes/BackReferenceAttribute.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Attributes/BackReferenceAttribute.cs @@ -1,4 +1,6 @@ using NexusMods.MnemonicDB.Abstractions.Models; +// ReSharper disable UnusedTypeParameter +#pragma warning disable CS9113 // Parameter is unread. namespace NexusMods.MnemonicDB.Abstractions.Attributes; diff --git a/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/AEVTComparator.cs b/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/AEVTComparator.cs index dbed00ce..d5ea2683 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/AEVTComparator.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/AEVTComparator.cs @@ -7,7 +7,6 @@ namespace NexusMods.MnemonicDB.Abstractions.DatomComparators; /// /// The AEVT Comparator. /// -/// public sealed class AEVTComparator : ADatomComparator< AComparer, EComparer, diff --git a/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/EAVTComparator.cs b/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/EAVTComparator.cs index fb77afa6..3dbd2829 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/EAVTComparator.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/DatomComparators/EAVTComparator.cs @@ -1,5 +1,4 @@ using NexusMods.MnemonicDB.Abstractions.ElementComparers; -using NexusMods.MnemonicDB.Abstractions.Internals; using NexusMods.MnemonicDB.Storage.Abstractions.ElementComparers; namespace NexusMods.MnemonicDB.Abstractions.DatomComparators; @@ -7,7 +6,6 @@ namespace NexusMods.MnemonicDB.Abstractions.DatomComparators; /// /// The EAVT Comparator. /// -/// public sealed class EAVTComparator : ADatomComparator< EComparer, AComparer, diff --git a/src/NexusMods.MnemonicDB.Abstractions/DatomKey.cs b/src/NexusMods.MnemonicDB.Abstractions/DatomKey.cs index 6884c5e2..4dac9b02 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/DatomKey.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/DatomKey.cs @@ -60,6 +60,7 @@ public int GetHashCode(DatomKey obj) return hash.ToHashCode(); } + /// public override string ToString() { if (_valueMemory.IsEmpty) diff --git a/src/NexusMods.MnemonicDB.Abstractions/DatomStoreSettings.cs b/src/NexusMods.MnemonicDB.Abstractions/DatomStoreSettings.cs index 7c03a56c..4c3a5709 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/DatomStoreSettings.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/DatomStoreSettings.cs @@ -7,5 +7,8 @@ namespace NexusMods.MnemonicDB.Abstractions; /// public class DatomStoreSettings { + /// + /// The path to the datom store's storage + /// public AbsolutePath Path { get; init; } } diff --git a/src/NexusMods.MnemonicDB.Abstractions/DependencyInjectionExtensions.cs b/src/NexusMods.MnemonicDB.Abstractions/DependencyInjectionExtensions.cs index 6fa239e3..e76f4f6d 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/DependencyInjectionExtensions.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/DependencyInjectionExtensions.cs @@ -27,10 +27,6 @@ public static IServiceCollection AddAttribute(this IServiceCollectio /// Assumes that the specified type is a static class with nested attribute classes, it registers all the nested /// classes with the service collection. /// - /// - /// - /// - /// public static IServiceCollection AddAttributeCollection(this IServiceCollection services, Type type) { diff --git a/src/NexusMods.MnemonicDB.Abstractions/EnumerableExtensions.cs b/src/NexusMods.MnemonicDB.Abstractions/EnumerableExtensions.cs index 39bdcb48..571643ed 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/EnumerableExtensions.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/EnumerableExtensions.cs @@ -4,6 +4,9 @@ namespace NexusMods.MnemonicDB.Abstractions; +/// +/// Extensions for IEnumerable +/// public static class EnumerableExtensions { /// diff --git a/src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelReadType.cs b/src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelReadType.cs deleted file mode 100644 index 59265566..00000000 --- a/src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelReadType.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; -using NexusMods.MnemonicDB.Abstractions.ElementComparers; - -namespace NexusMods.MnemonicDB.Abstractions.Exceptions; - -public class UnsupportedLowLevelReadType(ValueTag tag) : Exception($"Unsupported low-level read type: {tag}") -{ - -} diff --git a/src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelTypeException.cs b/src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelTypeException.cs deleted file mode 100644 index ab0ddea4..00000000 --- a/src/NexusMods.MnemonicDB.Abstractions/Exceptions/UnsupportedLowLevelTypeException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace NexusMods.MnemonicDB.Abstractions.Exceptions; - -/// -/// Thrown when the low-level type of some attribute is not something the database can handle. -/// -public class UnsupportedLowLevelWriteType(TValue value) : - Exception($"Unsupported low-level write type: {value?.GetType().ToString() ?? "null"} for value: {value}") -{ - -} diff --git a/src/NexusMods.MnemonicDB.Abstractions/GlobalComparer.cs b/src/NexusMods.MnemonicDB.Abstractions/GlobalComparer.cs index 873d22e7..2d5a69d7 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/GlobalComparer.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/GlobalComparer.cs @@ -34,6 +34,9 @@ public static unsafe int Compare(byte* aPtr, int aLen, byte* bPtr, int bLen) }; } + /// + /// Compare two datoms + /// public static int Compare(in Datom a, in Datom b) { var cmp = ((byte)a.Prefix.Index).CompareTo((byte)b.Prefix.Index); diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentBuilder.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentBuilder.cs index f6be71e5..7bdbfafb 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentBuilder.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentBuilder.cs @@ -16,6 +16,10 @@ namespace NexusMods.MnemonicDB.Abstractions.IndexSegments; private readonly PooledMemoryBufferWriter _data; private readonly AttributeCache _attributeCache; + /// + /// Not supported, use the other constructor + /// + /// public IndexSegmentBuilder() { throw new NotSupportedException(); diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs index 6b696761..1b65a4a7 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs @@ -2,32 +2,63 @@ using NexusMods.MnemonicDB.Abstractions.DatomComparators; using NexusMods.MnemonicDB.Abstractions.DatomIterators; using NexusMods.MnemonicDB.Abstractions.Internals; +// ReSharper disable InconsistentNaming namespace NexusMods.MnemonicDB.Abstractions; +/// +/// The type of indexes in the database +/// public enum IndexType : byte { - // No specified index, default for datoms + /// + /// Default for datoms that are not part of an index + /// None = 0, - // Transaction log, the final source of truth, used - // for replaying the database + /// + /// Transaction log index + /// TxLog = 1, - // Primary index for looking up values on an entity + /// + /// Current row-level index + /// EAVTCurrent = 2, + + /// + /// History row-level index + /// EAVTHistory, - // Indexes for asking what entities have this attribute? + /// + /// Current column-level index + /// AEVTCurrent, + + /// + /// History column-level index + /// AEVTHistory, - // Backref index for asking "who references this entity?" + /// + /// Current reverse reference index + /// VAETCurrent, + + /// + /// History reverse reference index + /// VAETHistory, - // Secondary index for asking "who has this value on this attribute?" + /// + /// Current indexed value index + /// AVETCurrent, + + /// + /// History indexed value index + /// AVETHistory } diff --git a/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs b/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs index f030fc0b..6e5c4765 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs @@ -6,18 +6,17 @@ namespace NexusMods.MnemonicDB.Abstractions.Internals; /// -/// The system encodes keys as a 16 byte prefix followed by the actual key data, the format -/// of the value is defined by the IValueSerializer -/// and the length is maintained by the datastore. -/// This KeyPrefix then contains the other parts of the Datom: EntityId, AttributeId, TxId, and Flags. -/// Encodes and decodes the prefix of a key, the format is: -/// [AttributeId: 2bytes] -/// [TxId: 6bytes] -/// [EntityID + PartitionID: 7bytes] -/// [IsRetract: 1 bit] [ValueTag: 7 bits] -/// The Entity Id is created by taking the last 6 bytes of the id and combining it with -/// the partition id. So the encoding logic looks like this: -/// packed = (e & 0x00FFFFFFFFFFFFFF) >> 8 | (e & 0xFFFFFFFFFFFF) << 8 +/// Represents a key prefix used in the MnemonicDB system. +/// The KeyPrefix is a fixed-size structure (16 bytes) that encodes various parameters: +/// - Upper 8 bytes: +/// - Bits 48-63: AttributeId (16 bits) +/// - Bits 40-47: IndexType (8 bits) +/// - Bits 0-39: TxId (40 bits) +/// - Lower 8 bytes: +/// - Bits 56-63: EntityId (8 bits) +/// - Bits 8-55: EntityId (48 bits) +/// - Bit 0: IsRetract (1 bit) +/// - Bits 1-7: ValueTag (7 bits) /// [StructLayout(LayoutKind.Explicit, Size = Size)] public readonly record struct KeyPrefix diff --git a/src/NexusMods.MnemonicDB.Abstractions/NexusMods.MnemonicDB.Abstractions.csproj b/src/NexusMods.MnemonicDB.Abstractions/NexusMods.MnemonicDB.Abstractions.csproj index e1c817f0..7f0d6969 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/NexusMods.MnemonicDB.Abstractions.csproj +++ b/src/NexusMods.MnemonicDB.Abstractions/NexusMods.MnemonicDB.Abstractions.csproj @@ -5,13 +5,13 @@ - - - - + + + + - + diff --git a/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs b/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs index 36677c65..9b75cd61 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs @@ -112,13 +112,9 @@ public static IObservable> AsEntityIds(this IObserva private static IChangeSet Diff(AttributeCache cache, IndexSegment updates, SliceDescriptor descriptor) { var changes = new ChangeSet(); - - AttributeId previousAid = default; - var index = descriptor.Index; - - for (int i = 0; i < updates.Count; i++) + for (var i = 0; i < updates.Count; i++) { var datom = updates[i].WithIndex(index); if (!descriptor.Includes(datom)) diff --git a/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/NullSerializer.cs b/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/NullSerializer.cs index 5d128636..44f4f663 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/NullSerializer.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/NullSerializer.cs @@ -9,15 +9,14 @@ namespace NexusMods.MnemonicDB.Abstractions.ValueSerializers; /// public class NullSerializer : IValueSerializer { + /// public static ValueTag ValueTag => ValueTag.Null; /// public static int Compare(ReadOnlySpan a, ReadOnlySpan b) => 0; - public static unsafe int Compare(byte* aPtr, int aLen, byte* bPtr, int bLen) - { - return 0; - } + /// + public static unsafe int Compare(byte* aPtr, int aLen, byte* bPtr, int bLen) => 0; /// public static Null Read(ReadOnlySpan span) diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedAttribute.cs b/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedAttribute.cs index dce4e635..5614ead6 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedAttribute.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedAttribute.cs @@ -3,7 +3,7 @@ namespace NexusMods.MnemonicDB.SourceGenerator; -public class AnalyzedAttribute +internal class AnalyzedAttribute { public string Name { get; set; } = ""; public string FieldName { get; set; } = ""; diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedBackReferenceAttribute.cs b/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedBackReferenceAttribute.cs index 9389d605..877f954b 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedBackReferenceAttribute.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/AnalyzedBackReferenceAttribute.cs @@ -3,7 +3,7 @@ namespace NexusMods.MnemonicDB.SourceGenerator; -public class AnalyzedBackReferenceAttribute +internal class AnalyzedBackReferenceAttribute { public string Name { get; set; } = ""; public INamedTypeSymbol OtherModel { get; set; } = null!; diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs b/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs index 7884fdf8..16319347 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs @@ -8,7 +8,7 @@ namespace NexusMods.MnemonicDB.SourceGenerator; [Generator] -public class ModelGenerator : ISourceGenerator +internal class ModelGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/AttributeFlags.cs b/src/NexusMods.MnemonicDB.SourceGenerator/AttributeFlags.cs index 05412063..5a6fee7c 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/AttributeFlags.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/AttributeFlags.cs @@ -3,7 +3,7 @@ namespace NexusMods.MnemonicDB.SourceGenerator; [Flags] -public enum AttributeFlags +internal enum AttributeFlags { Marker = 1, Scalar = 2, diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/Consts.cs b/src/NexusMods.MnemonicDB.SourceGenerator/Consts.cs index e98f692c..88699a16 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/Consts.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/Consts.cs @@ -1,6 +1,6 @@ namespace NexusMods.MnemonicDB.SourceGenerator; -public static class Consts +internal static class Consts { public const string IModelDefinitionFullName = "NexusMods.MnemonicDB.Abstractions.Models.IModelDefinition"; public const string IModelDefinitionName = "IModelDefinition"; diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/ModelAnalyzer.cs b/src/NexusMods.MnemonicDB.SourceGenerator/ModelAnalyzer.cs index 7f7c682e..04db6f21 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/ModelAnalyzer.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/ModelAnalyzer.cs @@ -9,7 +9,7 @@ namespace NexusMods.MnemonicDB.SourceGenerator; -public class ModelAnalyzer +internal class ModelAnalyzer { private readonly Compilation _compilation; private readonly GeneratorExecutionContext _context; @@ -31,9 +31,9 @@ public class ModelAnalyzer public string Name { get; set; } = ""; public INamespaceSymbol Namespace { get; set; } = null!; - public List Attributes { get; } = new(); + internal List Attributes { get; } = new(); - public List BackReferences { get; } = new(); + internal List BackReferences { get; } = new(); public List Includes { get; set; } = new(); public string Comments { get; set; } = ""; diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj b/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj index 7d76f4eb..05448d27 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj +++ b/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj @@ -7,12 +7,13 @@ false - + all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/SyntaxReceiver.cs b/src/NexusMods.MnemonicDB.SourceGenerator/SyntaxReceiver.cs index 574e6d35..689a08a1 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/SyntaxReceiver.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/SyntaxReceiver.cs @@ -5,7 +5,7 @@ namespace NexusMods.MnemonicDB.SourceGenerator; -public class SyntaxReceiver : ISyntaxReceiver +internal class SyntaxReceiver : ISyntaxReceiver { public ImmutableList CandidateClasses { get; private set; } = ImmutableList.Empty; diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave b/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave index 5f5bc0c2..31184913 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave +++ b/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave @@ -29,6 +29,10 @@ using __DI__ = Microsoft.Extensions.DependencyInjection; using __COMPARERS__ = NexusMods.MnemonicDB.Abstractions.ElementComparers; +/// +/// The top level model definition for the {{= model.Name}} model. This class is rarely +/// used directly, instead, the ReadOnly struct or the New class should be used. +/// {{= model.Comments}} public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name}}, {{= model.Name}}.ReadOnly> { @@ -45,6 +49,9 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} {{each attr in model.Attributes}} {{if attr.IsIndexed || attr.IsReference}} + /// + /// Finds all {{= model.Name}} entities with the given value for the {{= attr.Name}} attribute. + /// public static __SEGMENTS__.Entities<{{= model.Name}}.ReadOnly> FindBy{{= attr.Name}}(__ABSTRACTIONS__.IDb db, {{= attr.HighLevelType.ToDisplayString()}} value) { return db.Datoms({{= attr.FieldName}}, value).AsModels<{{= model.Name}}.ReadOnly>(db); } @@ -137,11 +144,17 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} #endregion + /// + /// Constructs a new {{= model.Name}} model from the given entity id, used to provide a typed structured + /// way to interact with the entity before it is commited to the database. + /// public partial class New : __MODELS__.ITemporaryEntity, __MODELS__.IHasEntityId { - {{if model.Includes.Count == 0}} + /// + /// Constructs a new {{= model.Name}} model from the given transaction with a generated temporary id. + /// public New(__ABSTRACTIONS__.ITransaction tx) : base() { Id = tx.TempId(); tx.Attach(this); @@ -149,12 +162,18 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} {{else}} + /// + /// Constructs a new {{= model.Name}} model from the given transaction with the given entity id. + /// public New(__ABSTRACTIONS__.ITransaction tx, out __ABSTRACTIONS__.EntityId id) : base() { Id = tx.TempId(); id = Id; tx.Attach(this); } + /// + /// Constructs a new {{= model.Name}} model from the given transaction with the given entity partition for the generated temporary id. + /// public New(__ABSTRACTIONS__.ITransaction tx, __ABSTRACTIONS__.PartitionId partition, out __ABSTRACTIONS__.EntityId id) : base() { Id = tx.TempId(partition); id = Id; @@ -163,12 +182,18 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} {{/if}} + /// + /// Constructs a new {{= model.Name}} model from the given transaction with the given entity id. + /// public New(__ABSTRACTIONS__.ITransaction tx, __ABSTRACTIONS__.EntityId eid) : base() { Id = eid; tx.Attach(this); } {{each include in model.Includes}} + /// + /// Gets the included entity of type {{= include.Name}} from the transaction. + /// public {{= include.ToDisplayString()}}.New Get{{=include.Name}}(__ABSTRACTIONS__.ITransaction tx) { if (!tx.TryGet<{{= include.ToDisplayString()}}.New>(Id, out var value)) throw new InvalidOperationException($"Unable to find {typeof({{= include.ToDisplayString()}}.New)} with ID {Id} in transaction!"); @@ -176,6 +201,9 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} return value; } + /// + /// Sets the included entity of type {{= include.Name}} in the transaction. + /// public required {{= include.ToDisplayString()}}.New {{= include.Name}} { init { if (Id != value.Id) @@ -184,6 +212,9 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} } {{/each}} + /// + /// Adds this model to the given transaction. + /// public void AddTo(__ABSTRACTIONS__.ITransaction tx) { {{each attr in model.Attributes}} @@ -259,6 +290,10 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} #endregion } + /// + /// The ReadOnly struct is a read-only version of the entity, it is used to access the entity + /// in a read context. It immutable and must be reloaded to get updated data when the entity changes. + /// {{= model.Comments}} public readonly partial struct ReadOnly : __MODELS__.IReadOnlyModel<{{= model.Name}}.ReadOnly> { @@ -412,8 +447,14 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} [global::System.Text.Json.Serialization.JsonConverter(typeof({{= model.Name}}Id.JsonConverter))] public readonly partial struct {{= model.Name}}Id : IEquatable<{{= model.Name}}Id>, IEquatable<__ABSTRACTIONS__.EntityId> { + /// + /// The generic EntityId value this typed id wraps. + /// public readonly __ABSTRACTIONS__.EntityId Value; + /// + /// Constructs a new {{= model.Name}}Id from the given entity id. + /// public {{= model.Name}}Id(__ABSTRACTIONS__.EntityId id) => Value = id; /// @@ -426,41 +467,60 @@ public readonly partial struct {{= model.Name}}Id : IEquatable<{{= model.Name}}I /// public static {{= model.Name}}Id From(ulong id) => new {{= model.Name}}Id(__ABSTRACTIONS__.EntityId.From(id)); + /// + /// Implicit conversion from the model id to the entity id. + /// public static implicit operator __ABSTRACTIONS__.EntityId({{= model.Name}}Id id) => id.Value; + + /// + /// Implicit conversion from the entity id to the model id. + /// public static implicit operator {{= model.Name}}Id(EntityId id) => {{= model.Name}}Id.From(id); - + /// + /// Equality comparison between two {{= model.Name}}Id values. + /// public bool Equals({{= model.Name}}Id other) { return Value.Value == other.Value.Value; } - + /// + /// Equality comparison between a {{= model.Name}}Id and an EntityId. + /// public bool Equals(__ABSTRACTIONS__.EntityId other) { return Value.Value == other.Value; } + /// public override string ToString() { return "{{= model.Name}}Id:" + Value.Value.ToString("x"); } + /// public static bool operator ==({{= model.Name}}Id left, {{= model.Name}}Id right) => left.Equals(right); - + + /// public static bool operator !=({{= model.Name}}Id left, {{= model.Name}}Id right) => !left.Equals(right); + /// public override bool Equals(object? obj) { return obj is {{= model.Name}}Id id && Equals(id); } + /// public override int GetHashCode() { return Value.GetHashCode(); } - public class JsonConverter : global::System.Text.Json.Serialization.JsonConverter<{{= model.Name}}Id> + /// + /// A JsonConverter for the {{= model.Name}}Id value object. + /// + internal class JsonConverter : global::System.Text.Json.Serialization.JsonConverter<{{= model.Name}}Id> { private readonly global::System.Text.Json.Serialization.JsonConverter<__ABSTRACTIONS__.EntityId> _innerConverter = new __ABSTRACTIONS__.EntityId.JsonConverter(); @@ -486,7 +546,9 @@ public readonly partial struct {{= model.Name}}Id : IEquatable<{{= model.Name}}I } } - +/// +/// Extension methods for the {{= model.Name}} model. +/// public static class {{= model.Name}}Extensions { public static __DI__.IServiceCollection Add{{= model.Name}}Model(this __DI__.IServiceCollection services) { {{each attr in model.Attributes}} diff --git a/src/NexusMods.MnemonicDB/NexusMods.MnemonicDB.csproj b/src/NexusMods.MnemonicDB/NexusMods.MnemonicDB.csproj index 54e06b43..912027e7 100644 --- a/src/NexusMods.MnemonicDB/NexusMods.MnemonicDB.csproj +++ b/src/NexusMods.MnemonicDB/NexusMods.MnemonicDB.csproj @@ -4,14 +4,14 @@ true - - - - - + + + + + - + diff --git a/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/NexusMods.MnemonicDB.SourceGenerator.Tests.csproj b/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/NexusMods.MnemonicDB.SourceGenerator.Tests.csproj index f79bce02..dbf3a6a9 100644 --- a/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/NexusMods.MnemonicDB.SourceGenerator.Tests.csproj +++ b/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/NexusMods.MnemonicDB.SourceGenerator.Tests.csproj @@ -4,11 +4,32 @@ - - + + + + + + all + runtime; build; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/tests/NexusMods.MnemonicDB.Storage.Tests/NexusMods.MnemonicDB.Storage.Tests.csproj b/tests/NexusMods.MnemonicDB.Storage.Tests/NexusMods.MnemonicDB.Storage.Tests.csproj index 4d7ce30b..0237ea48 100644 --- a/tests/NexusMods.MnemonicDB.Storage.Tests/NexusMods.MnemonicDB.Storage.Tests.csproj +++ b/tests/NexusMods.MnemonicDB.Storage.Tests/NexusMods.MnemonicDB.Storage.Tests.csproj @@ -28,24 +28,24 @@ - - - + + + all runtime; build; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/NexusMods.MnemonicDB.TestModel/NexusMods.MnemonicDB.TestModel.csproj b/tests/NexusMods.MnemonicDB.TestModel/NexusMods.MnemonicDB.TestModel.csproj index 3e8164f7..428fbd0c 100644 --- a/tests/NexusMods.MnemonicDB.TestModel/NexusMods.MnemonicDB.TestModel.csproj +++ b/tests/NexusMods.MnemonicDB.TestModel/NexusMods.MnemonicDB.TestModel.csproj @@ -12,25 +12,25 @@ - - - + + + all runtime; build; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -39,9 +39,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/tests/NexusMods.MnemonicDB.Tests/NexusMods.MnemonicDB.Tests.csproj b/tests/NexusMods.MnemonicDB.Tests/NexusMods.MnemonicDB.Tests.csproj index 67756545..2b1005cb 100644 --- a/tests/NexusMods.MnemonicDB.Tests/NexusMods.MnemonicDB.Tests.csproj +++ b/tests/NexusMods.MnemonicDB.Tests/NexusMods.MnemonicDB.Tests.csproj @@ -21,25 +21,25 @@ - - - + + + all runtime; build; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive From b219333b30fd120cb6fc6384da46a74d54ac49a0 Mon Sep 17 00:00:00 2001 From: halgari Date: Mon, 11 Nov 2024 11:24:18 -0700 Subject: [PATCH 2/4] Down to 78 warnings in total --- .../Benchmarks/IndexSegmentEBenchmarks.cs | 9 ---- .../ITransaction.cs | 3 ++ .../IndexSegments/Entities.cs | 1 - .../IndexSegments/IIndexSegment.cs | 6 ++- .../IndexSegments/IndexSegment.cs | 41 +------------------ .../IndexSegments/IndexSegmentExtensions.cs | 8 +++- .../IndexType.cs | 7 +++- .../Internals/KeyPrefix.cs | 6 +++ .../Models/IHasIdAndIndexSegment.cs | 6 +++ .../Models/IModelDefinition.cs | 9 ++-- .../PooledMemoryBufferWriter.cs | 14 ++++++- .../Query/ObservableDatoms.cs | 3 ++ .../Serializer.cs | 3 ++ .../ValueSerializers/TupleSerializers.cs | 5 ++- .../Analyzer.cs | 7 +++- ...exusMods.MnemonicDB.SourceGenerator.csproj | 1 + .../Template.weave | 19 ++++++++- .../ArchiveFile.cs | 2 + 18 files changed, 88 insertions(+), 62 deletions(-) diff --git a/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/IndexSegmentEBenchmarks.cs b/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/IndexSegmentEBenchmarks.cs index 55c1905f..7edec33a 100644 --- a/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/IndexSegmentEBenchmarks.cs +++ b/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/IndexSegmentEBenchmarks.cs @@ -83,13 +83,4 @@ public int FindBinarySearchRework() var find = EntityId.From((ulong)ToFind); return _index.FindFirst(find); // Return the first occurrence found, or -1 if not found } - - [Benchmark] - public int FindBinarySearchReworkAVX2() - { - var find = EntityId.From((ulong)ToFind); - return _index.FindFirstAVX2(find.Value); // Return the first occurrence found, or -1 if not found - } - - } diff --git a/src/NexusMods.MnemonicDB.Abstractions/ITransaction.cs b/src/NexusMods.MnemonicDB.Abstractions/ITransaction.cs index cb972e25..5c37acd6 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/ITransaction.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/ITransaction.cs @@ -39,6 +39,9 @@ public interface ITransaction : IDisposable void Add(EntityId entityId, TAttribute attribute, TVal val, bool isRetract = false) where TAttribute : IWritableAttribute; + /// + /// Adds a new datom to the transaction + /// void Add(EntityId entityId, Attribute attribute, TVal val, bool isRetract = false) where TSerializer : IValueSerializer; diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/Entities.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/Entities.cs index 2d4e9b7c..7162e220 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/Entities.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/Entities.cs @@ -80,7 +80,6 @@ public void Dispose() { } /// /// A wrapper around EntityIds that auto-creates the given ReadModel on-the-fly /// - /// public Entities(EntityIds ids, IDb db) { _ids = ids; diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IIndexSegment.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IIndexSegment.cs index 0c88c77e..dbb58dae 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IIndexSegment.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IIndexSegment.cs @@ -1,6 +1,10 @@ namespace NexusMods.MnemonicDB.Abstractions.IndexSegments; -public interface IIndexSegment +/// +/// An index segment that reutrns values of a specific type +/// +/// +public interface IIndexSegment { /// /// Gets the value at the given index diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegment.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegment.cs index 7ad99d25..6d78fdc2 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegment.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegment.cs @@ -227,46 +227,7 @@ public int FindFirst(EntityId find) } return result; // Return the first occurrence found, or -1 if not found } - - public int FindFirstAVX2(ulong find) - { - var targetVector = Vector256.Zero.WithElement(0, find) - .WithElement(1, find) - .WithElement(2, find) - .WithElement(3, find); - - var casted = MemoryMarshal.Cast>(Lowers); - - for (var idx = 0; idx < casted.Length; idx += 1) - { - var lowers = casted[idx]; - - var maskHigh = Avx2.And(lowers, Vector256.Create(0x7F00000000000000UL)); - var maskLow = Avx2.And(Avx2.ShiftRightLogical(lowers, 8), Vector256.Create(0x0000FFFFFFFFFFFFUL)); - var ored = Avx2.Or(maskHigh, maskLow); - - var comparison = Avx2.CompareEqual(ored, targetVector); - - var mask = Avx2.MoveMask(comparison.As()); - if (mask != 0) - { - var index = BitOperations.TrailingZeroCount(mask) / 8; - return idx * Vector256.Count + index; - } - } - - // Handle remaining elements - for (int i = (casted.Length * Vector256.Count); i < Lowers.Length; i++) - { - if (Lowers[i] >= find) - { - return i; - } - } - - return -1; // No value found that is greater than or equal to the target - } - + /// /// Enumerator. /// diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentExtensions.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentExtensions.cs index f81a0a7a..70df24c2 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentExtensions.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexSegments/IndexSegmentExtensions.cs @@ -2,6 +2,9 @@ namespace NexusMods.MnemonicDB.Abstractions.IndexSegments; +/// +/// Extensions for working with index segments +/// public static class IndexSegmentExtensions { /// @@ -88,7 +91,10 @@ public static List MergeByEntityId(this IndexSegment setA, IndexSegmen return result; } - + /// + /// Merges four index segments by entity id, returning a list of the entity ids found in all four segments. This is a + /// union operation, and assumes that the four segments ar ordered by entity id. + /// public static List MergeByEntityId(this IndexSegment setA, IndexSegment setB, IndexSegment setC, IndexSegment setD) { var lowerA = setA.Lowers; diff --git a/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs b/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs index 1b65a4a7..babe3f1b 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/IndexType.cs @@ -62,9 +62,14 @@ public enum IndexType : byte AVETHistory } - +/// +/// Extension methods for the IndexType enum +/// public static class IndexTypeExtensions { + /// + /// Get a comparator for the given index type + /// public static IDatomComparator GetComparator(this IndexType type) { return type switch diff --git a/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs b/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs index 6e5c4765..99772efc 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs @@ -154,8 +154,14 @@ public static KeyPrefix Read(ReadOnlySpan bytes) #region Constants + /// + /// The minimum key prefix possible + /// public static KeyPrefix Min => new(0, 0); + /// + /// The maximum key prefix possible + /// public static KeyPrefix Max => new(0, 0); /// diff --git a/src/NexusMods.MnemonicDB.Abstractions/Models/IHasIdAndIndexSegment.cs b/src/NexusMods.MnemonicDB.Abstractions/Models/IHasIdAndIndexSegment.cs index 90a138ac..8a94a285 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Models/IHasIdAndIndexSegment.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Models/IHasIdAndIndexSegment.cs @@ -2,7 +2,13 @@ namespace NexusMods.MnemonicDB.Abstractions.Models; +/// +/// An interface for refering to things that have an id and an index segment +/// public interface IHasIdAndIndexSegment : IHasEntityIdAndDb { + /// + /// The index segment for this entity + /// public IndexSegment IndexSegment { get; } } diff --git a/src/NexusMods.MnemonicDB.Abstractions/Models/IModelDefinition.cs b/src/NexusMods.MnemonicDB.Abstractions/Models/IModelDefinition.cs index 95015cbe..9c155b69 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Models/IModelDefinition.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Models/IModelDefinition.cs @@ -1,6 +1,7 @@ namespace NexusMods.MnemonicDB.Abstractions.Models; -public interface IModelDefinition -{ - -} +/// +/// Marker interface for model definitions, this triggers the soruce generator to generate the model +/// for the class that implements this interface +/// +public interface IModelDefinition; diff --git a/src/NexusMods.MnemonicDB.Abstractions/PooledMemoryBufferWriter.cs b/src/NexusMods.MnemonicDB.Abstractions/PooledMemoryBufferWriter.cs index 4b445060..84759f49 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/PooledMemoryBufferWriter.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/PooledMemoryBufferWriter.cs @@ -31,16 +31,21 @@ public PooledMemoryBufferWriter(int initialCapacity = 1024) } + /// + /// Gets the written memory of this writer. + /// public ReadOnlyMemory WrittenMemory => _data.Slice(0, Length); + /// + /// Gets the written span of this writer, as a writable span. + /// public Span WrittenSpanWritable => _data.Span.SliceFast(0, Length); /// /// Gets the written length of the data /// public int Length { get; private set; } - - + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Advance(int count) @@ -79,6 +84,7 @@ public Span GetSpan(int sizeHint = 0) return _data.Span.SliceFast(Length, sizeHint); } + /// public void Dispose() { _owner.Dispose(); @@ -101,6 +107,10 @@ public void Write(ReadOnlySpan span) Advance(span.Length); } + /// + /// Writes the given datom to the buffer. + /// + /// public void Write(in Datom datom) { var span = GetSpan(KeyPrefix.Size + datom.ValueSpan.Length); diff --git a/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs b/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs index 9b75cd61..d4a73bb2 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs @@ -13,6 +13,9 @@ namespace NexusMods.MnemonicDB.Abstractions.Query; +/// +/// Extensions for observing datoms in the database +/// public static class ObservableDatoms { diff --git a/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs b/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs index 82a0eb2a..96a16bf1 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs @@ -223,6 +223,9 @@ public static void Remap(this ValueTag tag, Span span, Func + /// Convert the value from the source tag to the destination tag if possible, throws an exception if the conversion is not supported + /// public static void ConvertValue(this ValueTag srcTag, ReadOnlySpan srcSpan, ValueTag destTag, TWriter destWriter) where TWriter : IBufferWriter { diff --git a/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/TupleSerializers.cs b/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/TupleSerializers.cs index f160f78c..8b93d405 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/TupleSerializers.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/ValueSerializers/TupleSerializers.cs @@ -4,6 +4,7 @@ using System.Text; using NexusMods.MnemonicDB.Abstractions.ElementComparers; using Reloaded.Memory.Extensions; +// ReSharper disable InconsistentNaming namespace NexusMods.MnemonicDB.Abstractions.ValueSerializers; @@ -12,8 +13,10 @@ namespace NexusMods.MnemonicDB.Abstractions.ValueSerializers; /// public sealed class Tuple2_UShort_Utf8I_Serializer : IValueSerializer<(ushort, string)> { + /// public static ValueTag ValueTag => ValueTag.Tuple2_UShort_Utf8I; - + + /// public static int Compare(ReadOnlySpan a, ReadOnlySpan b) { var aUShort = MemoryMarshal.Read(a); diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs b/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs index 16319347..de89cbbd 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs +++ b/src/NexusMods.MnemonicDB.SourceGenerator/Analyzer.cs @@ -7,14 +7,19 @@ namespace NexusMods.MnemonicDB.SourceGenerator; +/// +/// Generates the model classes from the given contexts +/// [Generator] -internal class ModelGenerator : ISourceGenerator +public class ModelGenerator : ISourceGenerator { + /// public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); } + /// public void Execute(GeneratorExecutionContext context) { List modelAnalyzers = new(); diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj b/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj index 05448d27..f3e475a4 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj +++ b/src/NexusMods.MnemonicDB.SourceGenerator/NexusMods.MnemonicDB.SourceGenerator.csproj @@ -5,6 +5,7 @@ netstandard2.0 true false + NexusMods.MnemonicDB.SourceGenerator.Tests diff --git a/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave b/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave index 31184913..d572f355 100644 --- a/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave +++ b/src/NexusMods.MnemonicDB.SourceGenerator/Template.weave @@ -274,7 +274,8 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} #region Attributes {{each attr in model.Attributes}} - {{= attr.Comments}} + + /// {{if attr.IsReference && !attr.IsCollection}} public {{= attr.Prefix}} {{= attr.ReferenceType.ToDisplayString()}}Id {{= attr.ContextualName}} { get; set; } {{elif attr.IsCollection}} @@ -305,6 +306,9 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} __SEGMENTS__.IndexSegment __MODELS__.IHasIdAndIndexSegment.IndexSegment => this.IndexSegment; + /// + /// Constructs a new ReadOnly model of the entity from the given segment and id. + /// public ReadOnly(__ABSTRACTIONS__.IDb db, __SEGMENTS__.IndexSegment segment, __ABSTRACTIONS__.EntityId id) { Db = db; Id = id; @@ -378,11 +382,13 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} return false; } + /// public override string ToString() { return "{{= model.Name}}<" + Id + ">"; } + /// public bool IsValid() { // This is true when the struct is a default value. @@ -392,10 +398,14 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} } {{each include in model.Includes}} + /// + /// Tries convert this entity to a {{= include.Name}} entity, if the entity is not a {{= include.Name}} entity, it returns false. + /// public {{= include.ToDisplayString()}}.ReadOnly As{{= include.Name}}() => new {{= include.ToDisplayString()}}.ReadOnly(Db, Id); {{/each}} {{each attr in model.Attributes}} + /// {{if attr.IsCollection && attr.IsReference && !attr.IsMarker}} public __SEGMENTS__.Values<__ABSTRACTIONS__.EntityId> {{= attr.ContextualName}} => {{= attr.FieldName}}.Get(this); public __SEGMENTS__.ValueEntities<{{= attr.ReferenceType.ToDisplayString()}}.ReadOnly> {{= attr.Name}} => __SEGMENTS__.ValuesExtensions.AsModels<{{= attr.ReferenceType.ToDisplayString()}}.ReadOnly>({{= attr.FieldName}}.Get(this), Db); @@ -435,6 +445,9 @@ public partial class {{= model.Name}} : __MODELS__.IModelFactory<{{= model.Name} return model.Id; } + /// + /// Implicit conversion from the model to the model id. + /// public static implicit operator {{= model.Name}}Id({{= model.Name}}.ReadOnly? model) { return {{= model.Name}}Id.From(model!.Value.Id); } @@ -550,6 +563,10 @@ public readonly partial struct {{= model.Name}}Id : IEquatable<{{= model.Name}}I /// Extension methods for the {{= model.Name}} model. /// public static class {{= model.Name}}Extensions { + + /// + /// Adds the {{= model.Name}} model to the service collection. + /// public static __DI__.IServiceCollection Add{{= model.Name}}Model(this __DI__.IServiceCollection services) { {{each attr in model.Attributes}} services.AddSingleton<__ABSTRACTIONS__.IAttribute>(_ => {{= attr.FieldName}}); diff --git a/tests/NexusMods.MnemonicDB.TestModel/ArchiveFile.cs b/tests/NexusMods.MnemonicDB.TestModel/ArchiveFile.cs index 4beb1b28..c65ead72 100644 --- a/tests/NexusMods.MnemonicDB.TestModel/ArchiveFile.cs +++ b/tests/NexusMods.MnemonicDB.TestModel/ArchiveFile.cs @@ -10,10 +10,12 @@ namespace NexusMods.MnemonicDB.TestModel; public partial class ArchiveFile : IModelDefinition { private const string Namespace = "NexusMods.MnemonicDB.TestModel.ArchiveFile"; + /// /// The path of the file in the archive /// public static readonly RelativePathAttribute Path = new(Namespace, nameof(Path)) { IsIndexed = true }; + /// /// The hash of the file in the archive /// From 933ea6c7d747fcac20d5a11c2d758a103b57241b Mon Sep 17 00:00:00 2001 From: halgari Date: Mon, 11 Nov 2024 15:13:59 -0700 Subject: [PATCH 3/4] Last bit of cleanup for now --- .../Benchmarks/ABenchmark.cs | 1 + .../Caching/IndexSegmentCache.cs | 45 ++++++++++++++++--- src/NexusMods.MnemonicDB/Connection.cs | 2 +- src/NexusMods.MnemonicDB/HistorySnapshot.cs | 2 +- .../Storage/Abstractions/IStoreBackend.cs | 11 +++++ .../Storage/DatomStore.cs | 9 ++-- .../Storage/ImportExport.cs | 7 +++ .../Storage/InMemoryBackend/Backend.cs | 18 ++++++-- .../Storage/InMemoryBackend/IInMemoryIndex.cs | 8 ---- .../Storage/InMemoryBackend/Snapshot.cs | 10 ++--- .../Storage/InternalTransaction.cs | 1 - .../Storage/RocksDbBackend/Backend.cs | 17 ++++--- .../Storage/RocksDbBackend/Batch.cs | 2 +- .../Storage/RocksDbBackend/IRocksDbIndex.cs | 3 -- .../AMnemonicDBTest.cs | 1 + tests/NexusMods.MnemonicDB.Tests/DbTests.cs | 3 ++ .../ImportExportTests.cs | 2 +- 17 files changed, 101 insertions(+), 41 deletions(-) delete mode 100644 src/NexusMods.MnemonicDB/Storage/InMemoryBackend/IInMemoryIndex.cs delete mode 100644 src/NexusMods.MnemonicDB/Storage/RocksDbBackend/IRocksDbIndex.cs diff --git a/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/ABenchmark.cs b/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/ABenchmark.cs index 00344bd3..5585ea14 100644 --- a/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/ABenchmark.cs +++ b/benchmarks/NexusMods.MnemonicDB.Benchmarks/Benchmarks/ABenchmark.cs @@ -19,6 +19,7 @@ public class ABenchmark : IAsyncLifetime public async Task InitializeAsync() { + await Task.Yield(); var builder = Host.CreateDefaultBuilder() .ConfigureServices(services => { diff --git a/src/NexusMods.MnemonicDB/Caching/IndexSegmentCache.cs b/src/NexusMods.MnemonicDB/Caching/IndexSegmentCache.cs index 9e6e1876..d7b31f1e 100644 --- a/src/NexusMods.MnemonicDB/Caching/IndexSegmentCache.cs +++ b/src/NexusMods.MnemonicDB/Caching/IndexSegmentCache.cs @@ -17,26 +17,48 @@ namespace NexusMods.MnemonicDB.Caching; +/// +/// A struct that holds enough information to uniquely identify a cache entry. +/// [StructLayout(LayoutKind.Explicit, Size = 12)] public readonly struct CacheKey : IEquatable { + /// + /// The type of index that the cache entry is for. + /// [FieldOffset(0)] public readonly IndexType IndexType; + /// + /// The attribute id that the cache entry is for. + /// [FieldOffset(1)] public readonly AttributeId AttributeId; + /// + /// The entity id that the cache entry is for. + /// [FieldOffset(4)] public readonly EntityId EntityId; - public CacheKey(IndexType indexType, AttributeId attributeId, EntityId entityId) + /// + /// Create a new cache key. + /// + private CacheKey(IndexType indexType, AttributeId attributeId, EntityId entityId) { IndexType = indexType; AttributeId = attributeId; EntityId = entityId; } + /// + /// Create a new cache key for the given index type, attribute id and entity id. + /// public static CacheKey Create(IndexType indexType, AttributeId attributeId, EntityId entityId) => new(indexType, attributeId, entityId); + + /// + /// Create a new cache key for the given index type and attribute id. + /// public static CacheKey Create(IndexType indexType, EntityId entityId) => new(indexType, AttributeId.From(0), entityId); /// @@ -58,11 +80,25 @@ public override int GetHashCode() } } +/// +/// The value of a cache entry. +/// public struct CacheValue : IEquatable { + /// + /// The last time the cache entry was accessed. + /// public long LastAccessed; + + /// + /// The cached index segment. + /// public readonly IndexSegment Segment; + /// + /// Create a new cache value. + /// + /// public CacheValue(IndexSegment segment) { LastAccessed = CreateLastAccessed(); @@ -141,7 +177,7 @@ public bool TryGetValue(CacheKey key, out IndexSegment segment) public CacheRoot With(CacheKey key, IndexSegment segment, IndexSegmentCache cache) { var newEntries = _entries.SetItem(key, new CacheValue(segment)); - if (newEntries.Count > cache._entryCapacity) + if (newEntries.Count > cache.EntryCapacity) { newEntries = PurgeEntries(newEntries, newEntries.Count / 10); } @@ -206,8 +242,7 @@ public override string ToString() public class IndexSegmentCache { private CacheRoot _root; - internal readonly int _entryCapacity; - internal readonly Size _maxSize; + internal readonly int EntryCapacity; /// /// Create a new index segment cache. @@ -215,7 +250,7 @@ public class IndexSegmentCache public IndexSegmentCache() { _root = new CacheRoot(ImmutableDictionary.Empty); - _entryCapacity = 1_000_000; + EntryCapacity = 1_000_000; } /// diff --git a/src/NexusMods.MnemonicDB/Connection.cs b/src/NexusMods.MnemonicDB/Connection.cs index c305e363..d3f3e5f1 100644 --- a/src/NexusMods.MnemonicDB/Connection.cs +++ b/src/NexusMods.MnemonicDB/Connection.cs @@ -118,7 +118,7 @@ public IDb AsOf(TxId txId) /// public IDb History() { - return new Db(new HistorySnapshot(_store.GetSnapshot(), TxId, AttributeCache), TxId, AttributeCache) + return new Db(new HistorySnapshot(_store.GetSnapshot(), AttributeCache), TxId, AttributeCache) { Connection = this }; diff --git a/src/NexusMods.MnemonicDB/HistorySnapshot.cs b/src/NexusMods.MnemonicDB/HistorySnapshot.cs index 921de9e6..25cb0dac 100644 --- a/src/NexusMods.MnemonicDB/HistorySnapshot.cs +++ b/src/NexusMods.MnemonicDB/HistorySnapshot.cs @@ -11,7 +11,7 @@ namespace NexusMods.MnemonicDB; /// id, this requires merging two indexes together, and then the deduplication of the merged index (retractions /// removing assertions). /// -internal class HistorySnapshot(ISnapshot inner, TxId asOfTxId, AttributeCache attributeCache) : ISnapshot +internal class HistorySnapshot(ISnapshot inner, AttributeCache attributeCache) : ISnapshot { public IndexSegment Datoms(SliceDescriptor descriptor) { diff --git a/src/NexusMods.MnemonicDB/Storage/Abstractions/IStoreBackend.cs b/src/NexusMods.MnemonicDB/Storage/Abstractions/IStoreBackend.cs index 8ecd030f..45d77e8b 100644 --- a/src/NexusMods.MnemonicDB/Storage/Abstractions/IStoreBackend.cs +++ b/src/NexusMods.MnemonicDB/Storage/Abstractions/IStoreBackend.cs @@ -7,6 +7,10 @@ namespace NexusMods.MnemonicDB.Storage.Abstractions; +/// +/// A store backend is the backing KV store of a datoms store. It is responsible for +/// sorting, storing and snapshotting spans of data +/// public interface IStoreBackend : IDisposable { /// @@ -14,8 +18,15 @@ public interface IStoreBackend : IDisposable /// the datom store, the connection, and the db instances /// public AttributeCache AttributeCache { get; } + + /// + /// Create a new write batch + /// public IWriteBatch CreateBatch(); + /// + /// Initialize the store backend with the given location + /// public void Init(AbsolutePath location); /// diff --git a/src/NexusMods.MnemonicDB/Storage/DatomStore.cs b/src/NexusMods.MnemonicDB/Storage/DatomStore.cs index d62fb441..7b5d02b4 100644 --- a/src/NexusMods.MnemonicDB/Storage/DatomStore.cs +++ b/src/NexusMods.MnemonicDB/Storage/DatomStore.cs @@ -23,6 +23,9 @@ namespace NexusMods.MnemonicDB.Storage; +/// +/// Implementation of the datom store +/// public sealed partial class DatomStore : IDatomStore { internal readonly IStoreBackend Backend; @@ -34,14 +37,12 @@ public sealed partial class DatomStore : IDatomStore private readonly DatomStoreSettings _settings; private readonly BlockingCollection _pendingTransactions; - private DbStream _dbStream; + private readonly DbStream _dbStream; private readonly PooledMemoryBufferWriter _writer; private readonly PooledMemoryBufferWriter _prevWriter; private TxId _asOfTx = TxId.MinValue; - - private Task? _bootStrapTask = null; - private IDb? _currentDb = null; + private IDb? _currentDb; private static readonly TimeSpan TransactionTimeout = TimeSpan.FromMinutes(120); diff --git a/src/NexusMods.MnemonicDB/Storage/ImportExport.cs b/src/NexusMods.MnemonicDB/Storage/ImportExport.cs index a1fdf3df..af37ff18 100644 --- a/src/NexusMods.MnemonicDB/Storage/ImportExport.cs +++ b/src/NexusMods.MnemonicDB/Storage/ImportExport.cs @@ -7,6 +7,7 @@ using NexusMods.MnemonicDB.Abstractions.IndexSegments; using NexusMods.MnemonicDB.Abstractions.Query; using NexusMods.MnemonicDB.Storage.Abstractions; +using Reloaded.Memory.Extensions; namespace NexusMods.MnemonicDB.Storage; @@ -31,6 +32,7 @@ public partial class DatomStore /// public async Task ExportAsync(Stream stream) { + await Task.Yield(); var exportedDatoms = 0; var binaryWriter = new BinaryWriter(stream); binaryWriter.Write(FourCC); @@ -59,8 +61,13 @@ public async Task ExportAsync(Stream stream) Logger.LogInformation("Exported {0} datoms", exportedDatoms); } + /// + /// Imports the database from the given stream, will delete all the data in the store before importing + /// the new data + /// public async Task ImportAsync(Stream stream) { + await Task.Yield(); CleanStore(); var importedCount = 0; var binaryReader = new BinaryReader(stream); diff --git a/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Backend.cs b/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Backend.cs index bf8e1982..21ce8751 100644 --- a/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Backend.cs +++ b/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Backend.cs @@ -12,19 +12,26 @@ namespace NexusMods.MnemonicDB.Storage.InMemoryBackend; using IndexData = ImmutableSortedSet; +/// +/// The in-memory backend for the datoms store +/// public class Backend : IStoreBackend { private IndexData _index; - private readonly AttributeCache _attributeCache; + /// + /// Default constructor + /// public Backend() { - _attributeCache = new AttributeCache(); + AttributeCache = new AttributeCache(); _index = IndexData.Empty.WithComparer(new GlobalComparer()); } - public AttributeCache AttributeCache => _attributeCache; + /// + public AttributeCache AttributeCache { get; } + /// public IWriteBatch CreateBatch() { return new Batch(this); @@ -35,12 +42,15 @@ internal void Alter(Func alter) _index = alter(_index); } + /// public void Init(AbsolutePath location) { } - + + /// public ISnapshot GetSnapshot() { return new Snapshot(_index, AttributeCache); } + /// public void Dispose() { } } diff --git a/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/IInMemoryIndex.cs b/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/IInMemoryIndex.cs deleted file mode 100644 index 3a4d79f4..00000000 --- a/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/IInMemoryIndex.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Collections.Immutable; - -namespace NexusMods.MnemonicDB.Storage.InMemoryBackend; - -public interface IInMemoryIndex -{ - public ImmutableSortedSet Set { get; } -} diff --git a/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Snapshot.cs b/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Snapshot.cs index fb009c57..c3439438 100644 --- a/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Snapshot.cs +++ b/src/NexusMods.MnemonicDB/Storage/InMemoryBackend/Snapshot.cs @@ -1,18 +1,16 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using NexusMods.MnemonicDB.Abstractions; using NexusMods.MnemonicDB.Abstractions.DatomIterators; using NexusMods.MnemonicDB.Abstractions.IndexSegments; using NexusMods.MnemonicDB.Abstractions.Query; -using NexusMods.MnemonicDB.Storage.Abstractions; namespace NexusMods.MnemonicDB.Storage.InMemoryBackend; using IndexData = ImmutableSortedSet; -public class Snapshot : ISnapshot +internal class Snapshot : ISnapshot { private readonly IndexData _index; private readonly AttributeCache _attributeCache; @@ -22,9 +20,7 @@ public Snapshot(IndexData index, AttributeCache attributeCache) _attributeCache = attributeCache; _index = index; } - - public void Dispose() { } - + /// public IndexSegment Datoms(SliceDescriptor descriptor) { diff --git a/src/NexusMods.MnemonicDB/Storage/InternalTransaction.cs b/src/NexusMods.MnemonicDB/Storage/InternalTransaction.cs index 57c43b0c..bb256f8d 100644 --- a/src/NexusMods.MnemonicDB/Storage/InternalTransaction.cs +++ b/src/NexusMods.MnemonicDB/Storage/InternalTransaction.cs @@ -16,7 +16,6 @@ internal class InternalTransaction(IDb basisDb, IndexSegmentBuilder datoms) : IT { private ulong _tempId = PartitionId.Temp.MakeEntityId(0).Value; private List? _temporaryEntities = null; - private List? _txFunctions = null; /// public TxId ThisTxId => TxId.From(PartitionId.Temp.MakeEntityId(0).Value); diff --git a/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Backend.cs b/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Backend.cs index f0016ac5..83184f74 100644 --- a/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Backend.cs +++ b/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Backend.cs @@ -10,26 +10,32 @@ namespace NexusMods.MnemonicDB.Storage.RocksDbBackend; public class Backend : IStoreBackend { internal RocksDb? Db = null!; - private readonly AttributeCache _attributeCache; private IntPtr _comparator; + /// + /// Default constructor + /// public Backend() { - _attributeCache = new AttributeCache(); + AttributeCache = new AttributeCache(); } - public AttributeCache AttributeCache => _attributeCache; + /// + public AttributeCache AttributeCache { get; } + /// public IWriteBatch CreateBatch() { return new Batch(Db!); } - + + /// public ISnapshot GetSnapshot() { - return new Snapshot(this, _attributeCache); + return new Snapshot(this, AttributeCache); } + /// public void Init(AbsolutePath location) { @@ -47,6 +53,7 @@ public void Init(AbsolutePath location) Db = RocksDb.Open(options, location.ToString()); } + /// public void Dispose() { Db?.Dispose(); diff --git a/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Batch.cs b/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Batch.cs index 08062acd..8acc0491 100644 --- a/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Batch.cs +++ b/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/Batch.cs @@ -10,7 +10,7 @@ namespace NexusMods.MnemonicDB.Storage.RocksDbBackend; -public class Batch(RocksDb db) : IWriteBatch +internal class Batch(RocksDb db) : IWriteBatch { private readonly WriteBatch _batch = new(); diff --git a/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/IRocksDbIndex.cs b/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/IRocksDbIndex.cs deleted file mode 100644 index af01c28b..00000000 --- a/src/NexusMods.MnemonicDB/Storage/RocksDbBackend/IRocksDbIndex.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace NexusMods.MnemonicDB.Storage.RocksDbBackend; - -public interface IRocksDbIndex; diff --git a/tests/NexusMods.MnemonicDB.Tests/AMnemonicDBTest.cs b/tests/NexusMods.MnemonicDB.Tests/AMnemonicDBTest.cs index 0f2205e6..85831626 100644 --- a/tests/NexusMods.MnemonicDB.Tests/AMnemonicDBTest.cs +++ b/tests/NexusMods.MnemonicDB.Tests/AMnemonicDBTest.cs @@ -196,6 +196,7 @@ public void Dispose() protected async Task RestartDatomStore() { + await Task.Yield(); _store.Dispose(); _backend.Dispose(); diff --git a/tests/NexusMods.MnemonicDB.Tests/DbTests.cs b/tests/NexusMods.MnemonicDB.Tests/DbTests.cs index 718c2c4f..a85dffa4 100644 --- a/tests/NexusMods.MnemonicDB.Tests/DbTests.cs +++ b/tests/NexusMods.MnemonicDB.Tests/DbTests.cs @@ -182,7 +182,10 @@ public async Task ReadModelsCanHaveExtraAttributes() archiveReadModel.AsFile().ToArray().Should().BeEquivalentTo(readModel.ToArray(), "archive file should have the same base data as the file"); readModel.TryGetAsArchiveFile(out var castedDown).Should().BeTrue(); + +#pragma warning disable CS0183 // 'is' expression's given expression is always of the provided type (castedDown is ArchiveFile.ReadOnly).Should().BeTrue(); +#pragma warning restore CS0183 // 'is' expression's given expression is always of the provided type var badCast = new File.ReadOnly(result.Db, EntityId.From(1)); badCast.IsValid().Should().BeFalse("bad cast should not validate"); diff --git a/tests/NexusMods.MnemonicDB.Tests/ImportExportTests.cs b/tests/NexusMods.MnemonicDB.Tests/ImportExportTests.cs index 4e320176..62d8dd04 100644 --- a/tests/NexusMods.MnemonicDB.Tests/ImportExportTests.cs +++ b/tests/NexusMods.MnemonicDB.Tests/ImportExportTests.cs @@ -22,7 +22,7 @@ public async Task CanExportAndImportData() Logger.LogInformation("Exported {0} bytes", ms.Length); - var datomStore = new DatomStore(provider.GetRequiredService>()!, + var datomStore = new DatomStore(Provider.GetRequiredService>()!, Config, new Backend(), bootstrap: false); ms.Position = 0; From ec65bf34e47b1c9b70c5d0aff018a118421cf8ab Mon Sep 17 00:00:00 2001 From: halgari Date: Mon, 11 Nov 2024 18:22:19 -0700 Subject: [PATCH 4/4] Fix broken test files --- ...sts_MyModelArrayTest.Generated.verified.cs | 73 +++++++++++++++++-- ...erator_Tests_MyModel.Generated.verified.cs | 73 +++++++++++++++++-- 2 files changed, 134 insertions(+), 12 deletions(-) diff --git a/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/ArrayTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModelArrayTest.Generated.verified.cs b/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/ArrayTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModelArrayTest.Generated.verified.cs index 99dc3f66..d2abfd37 100644 --- a/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/ArrayTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModelArrayTest.Generated.verified.cs +++ b/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/ArrayTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModelArrayTest.Generated.verified.cs @@ -26,6 +26,10 @@ namespace NexusMods.MnemonicDB.SourceGenerator.Tests; using __COMPARERS__ = NexusMods.MnemonicDB.Abstractions.ElementComparers; +/// +/// The top level model definition for the MyModelArrayTest model. This class is rarely +/// used directly, instead, the ReadOnly struct or the New class should be used. +/// public partial class MyModelArrayTest : __MODELS__.IModelFactory { @@ -115,22 +119,34 @@ public static bool TryGet(__ABSTRACTIONS__.IDb db, __ABSTRACTIONS__.EntityId id, #endregion + /// + /// Constructs a new MyModelArrayTest model from the given entity id, used to provide a typed structured + /// way to interact with the entity before it is commited to the database. + /// public partial class New : __MODELS__.ITemporaryEntity, __MODELS__.IHasEntityId { - + /// + /// Constructs a new MyModelArrayTest model from the given transaction with a generated temporary id. + /// public New(__ABSTRACTIONS__.ITransaction tx) : base() { Id = tx.TempId(); tx.Attach(this); } + /// + /// Constructs a new MyModelArrayTest model from the given transaction with the given entity id. + /// public New(__ABSTRACTIONS__.ITransaction tx, __ABSTRACTIONS__.EntityId eid) : base() { Id = eid; tx.Attach(this); } + /// + /// Adds this model to the given transaction. + /// public void AddTo(__ABSTRACTIONS__.ITransaction tx) { tx.Add(Id, NexusMods.MnemonicDB.SourceGenerator.Tests.MyModelArrayTest.MyAttribute, MyAttribute, false); @@ -162,10 +178,15 @@ public static implicit operator MyModelArrayTestId(MyModelArrayTest.New model) { #region Attributes + /// public required int[] MyAttribute { get; set; } #endregion } + /// + /// The ReadOnly struct is a read-only version of the entity, it is used to access the entity + /// in a read context. It immutable and must be reloaded to get updated data when the entity changes. + /// public readonly partial struct ReadOnly : __MODELS__.IReadOnlyModel { @@ -177,6 +198,9 @@ public static implicit operator MyModelArrayTestId(MyModelArrayTest.New model) { __SEGMENTS__.IndexSegment __MODELS__.IHasIdAndIndexSegment.IndexSegment => this.IndexSegment; + /// + /// Constructs a new ReadOnly model of the entity from the given segment and id. + /// public ReadOnly(__ABSTRACTIONS__.IDb db, __SEGMENTS__.IndexSegment segment, __ABSTRACTIONS__.EntityId id) { Db = db; Id = id; @@ -250,11 +274,13 @@ public bool Contains(IAttribute attribute) return false; } + /// public override string ToString() { return "MyModelArrayTest<" + Id + ">"; } + /// public bool IsValid() { // This is true when the struct is a default value. @@ -264,6 +290,7 @@ public bool IsValid() } + /// public int[] MyAttribute => NexusMods.MnemonicDB.SourceGenerator.Tests.MyModelArrayTest.MyAttribute.Get(this); @@ -284,6 +311,9 @@ public static implicit operator __ABSTRACTIONS__.EntityId(MyModelArrayTest.ReadO return model.Id; } + /// + /// Implicit conversion from the model to the model id. + /// public static implicit operator MyModelArrayTestId(MyModelArrayTest.ReadOnly? model) { return MyModelArrayTestId.From(model!.Value.Id); } @@ -296,8 +326,14 @@ public static implicit operator MyModelArrayTestId(MyModelArrayTest.ReadOnly? mo [global::System.Text.Json.Serialization.JsonConverter(typeof(MyModelArrayTestId.JsonConverter))] public readonly partial struct MyModelArrayTestId : IEquatable, IEquatable<__ABSTRACTIONS__.EntityId> { + /// + /// The generic EntityId value this typed id wraps. + /// public readonly __ABSTRACTIONS__.EntityId Value; + /// + /// Constructs a new MyModelArrayTestId from the given entity id. + /// public MyModelArrayTestId(__ABSTRACTIONS__.EntityId id) => Value = id; /// @@ -310,41 +346,60 @@ public static implicit operator MyModelArrayTestId(MyModelArrayTest.ReadOnly? mo /// public static MyModelArrayTestId From(ulong id) => new MyModelArrayTestId(__ABSTRACTIONS__.EntityId.From(id)); + /// + /// Implicit conversion from the model id to the entity id. + /// public static implicit operator __ABSTRACTIONS__.EntityId(MyModelArrayTestId id) => id.Value; + + /// + /// Implicit conversion from the entity id to the model id. + /// public static implicit operator MyModelArrayTestId(EntityId id) => MyModelArrayTestId.From(id); - + /// + /// Equality comparison between two MyModelArrayTestId values. + /// public bool Equals(MyModelArrayTestId other) { return Value.Value == other.Value.Value; } - + /// + /// Equality comparison between a MyModelArrayTestId and an EntityId. + /// public bool Equals(__ABSTRACTIONS__.EntityId other) { return Value.Value == other.Value; } + /// public override string ToString() { return "MyModelArrayTestId:" + Value.Value.ToString("x"); } + /// public static bool operator ==(MyModelArrayTestId left, MyModelArrayTestId right) => left.Equals(right); - + + /// public static bool operator !=(MyModelArrayTestId left, MyModelArrayTestId right) => !left.Equals(right); + /// public override bool Equals(object? obj) { return obj is MyModelArrayTestId id && Equals(id); } + /// public override int GetHashCode() { return Value.GetHashCode(); } - public class JsonConverter : global::System.Text.Json.Serialization.JsonConverter + /// + /// A JsonConverter for the MyModelArrayTestId value object. + /// + internal class JsonConverter : global::System.Text.Json.Serialization.JsonConverter { private readonly global::System.Text.Json.Serialization.JsonConverter<__ABSTRACTIONS__.EntityId> _innerConverter = new __ABSTRACTIONS__.EntityId.JsonConverter(); @@ -370,8 +425,14 @@ public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter } } - +/// +/// Extension methods for the MyModelArrayTest model. +/// public static class MyModelArrayTestExtensions { + + /// + /// Adds the MyModelArrayTest model to the service collection. + /// public static __DI__.IServiceCollection AddMyModelArrayTestModel(this __DI__.IServiceCollection services) { services.AddSingleton<__ABSTRACTIONS__.IAttribute>(_ => NexusMods.MnemonicDB.SourceGenerator.Tests.MyModelArrayTest.MyAttribute); return services; diff --git a/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/BasicTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModel.Generated.verified.cs b/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/BasicTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModel.Generated.verified.cs index 057e391b..57941007 100644 --- a/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/BasicTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModel.Generated.verified.cs +++ b/tests/NexusMods.MnemonicDB.SourceGenerator.Tests/BasicTest#NexusMods_MnemonicDB_SourceGenerator_Tests_MyModel.Generated.verified.cs @@ -26,6 +26,10 @@ namespace NexusMods.MnemonicDB.SourceGenerator.Tests; using __COMPARERS__ = NexusMods.MnemonicDB.Abstractions.ElementComparers; +/// +/// The top level model definition for the MyModel model. This class is rarely +/// used directly, instead, the ReadOnly struct or the New class should be used. +/// public partial class MyModel : __MODELS__.IModelFactory { @@ -115,22 +119,34 @@ public static bool TryGet(__ABSTRACTIONS__.IDb db, __ABSTRACTIONS__.EntityId id, #endregion + /// + /// Constructs a new MyModel model from the given entity id, used to provide a typed structured + /// way to interact with the entity before it is commited to the database. + /// public partial class New : __MODELS__.ITemporaryEntity, __MODELS__.IHasEntityId { - + /// + /// Constructs a new MyModel model from the given transaction with a generated temporary id. + /// public New(__ABSTRACTIONS__.ITransaction tx) : base() { Id = tx.TempId(); tx.Attach(this); } + /// + /// Constructs a new MyModel model from the given transaction with the given entity id. + /// public New(__ABSTRACTIONS__.ITransaction tx, __ABSTRACTIONS__.EntityId eid) : base() { Id = eid; tx.Attach(this); } + /// + /// Adds this model to the given transaction. + /// public void AddTo(__ABSTRACTIONS__.ITransaction tx) { tx.Add(Id, NexusMods.MnemonicDB.SourceGenerator.Tests.MyModel.Name, Name, false); @@ -162,10 +178,15 @@ public static implicit operator MyModelId(MyModel.New model) { #region Attributes + /// public required string Name { get; set; } #endregion } + /// + /// The ReadOnly struct is a read-only version of the entity, it is used to access the entity + /// in a read context. It immutable and must be reloaded to get updated data when the entity changes. + /// public readonly partial struct ReadOnly : __MODELS__.IReadOnlyModel { @@ -177,6 +198,9 @@ public static implicit operator MyModelId(MyModel.New model) { __SEGMENTS__.IndexSegment __MODELS__.IHasIdAndIndexSegment.IndexSegment => this.IndexSegment; + /// + /// Constructs a new ReadOnly model of the entity from the given segment and id. + /// public ReadOnly(__ABSTRACTIONS__.IDb db, __SEGMENTS__.IndexSegment segment, __ABSTRACTIONS__.EntityId id) { Db = db; Id = id; @@ -250,11 +274,13 @@ public bool Contains(IAttribute attribute) return false; } + /// public override string ToString() { return "MyModel<" + Id + ">"; } + /// public bool IsValid() { // This is true when the struct is a default value. @@ -264,6 +290,7 @@ public bool IsValid() } + /// public string Name => NexusMods.MnemonicDB.SourceGenerator.Tests.MyModel.Name.Get(this); @@ -284,6 +311,9 @@ public static implicit operator __ABSTRACTIONS__.EntityId(MyModel.ReadOnly model return model.Id; } + /// + /// Implicit conversion from the model to the model id. + /// public static implicit operator MyModelId(MyModel.ReadOnly? model) { return MyModelId.From(model!.Value.Id); } @@ -296,8 +326,14 @@ public static implicit operator MyModelId(MyModel.ReadOnly? model) { [global::System.Text.Json.Serialization.JsonConverter(typeof(MyModelId.JsonConverter))] public readonly partial struct MyModelId : IEquatable, IEquatable<__ABSTRACTIONS__.EntityId> { + /// + /// The generic EntityId value this typed id wraps. + /// public readonly __ABSTRACTIONS__.EntityId Value; + /// + /// Constructs a new MyModelId from the given entity id. + /// public MyModelId(__ABSTRACTIONS__.EntityId id) => Value = id; /// @@ -310,41 +346,60 @@ public static implicit operator MyModelId(MyModel.ReadOnly? model) { /// public static MyModelId From(ulong id) => new MyModelId(__ABSTRACTIONS__.EntityId.From(id)); + /// + /// Implicit conversion from the model id to the entity id. + /// public static implicit operator __ABSTRACTIONS__.EntityId(MyModelId id) => id.Value; + + /// + /// Implicit conversion from the entity id to the model id. + /// public static implicit operator MyModelId(EntityId id) => MyModelId.From(id); - + /// + /// Equality comparison between two MyModelId values. + /// public bool Equals(MyModelId other) { return Value.Value == other.Value.Value; } - + /// + /// Equality comparison between a MyModelId and an EntityId. + /// public bool Equals(__ABSTRACTIONS__.EntityId other) { return Value.Value == other.Value; } + /// public override string ToString() { return "MyModelId:" + Value.Value.ToString("x"); } + /// public static bool operator ==(MyModelId left, MyModelId right) => left.Equals(right); - + + /// public static bool operator !=(MyModelId left, MyModelId right) => !left.Equals(right); + /// public override bool Equals(object? obj) { return obj is MyModelId id && Equals(id); } + /// public override int GetHashCode() { return Value.GetHashCode(); } - public class JsonConverter : global::System.Text.Json.Serialization.JsonConverter + /// + /// A JsonConverter for the MyModelId value object. + /// + internal class JsonConverter : global::System.Text.Json.Serialization.JsonConverter { private readonly global::System.Text.Json.Serialization.JsonConverter<__ABSTRACTIONS__.EntityId> _innerConverter = new __ABSTRACTIONS__.EntityId.JsonConverter(); @@ -370,8 +425,14 @@ public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter } } - +/// +/// Extension methods for the MyModel model. +/// public static class MyModelExtensions { + + /// + /// Adds the MyModel model to the service collection. + /// public static __DI__.IServiceCollection AddMyModelModel(this __DI__.IServiceCollection services) { services.AddSingleton<__ABSTRACTIONS__.IAttribute>(_ => NexusMods.MnemonicDB.SourceGenerator.Tests.MyModel.Name); return services;