public unsafe void WriteReferences(CurrentIndexingScope indexingScope, RavenTransaction tx) { // IndexSchema: // having 'Users' and 'Addresses' we will end up with // // #Users (tree) - splitted by collection so we can easily return all items of same collection to the indexing function // |- addresses/1 (key) -> [ users/1, users/2 ] // |- addresses/2 (key) -> [ users/3 ] // // References (tree) - used in delete operations // |- users/1 -> [ addresses/1 ] // |- users/2 -> [ addresses/1 ] // |- users/3 -> [ addresses/2 ] // // $Users (tree) - holding highest visible etag of 'referenced collection' per collection, so we will have a starting point for references processing // |- Addresses (key) -> 5 if (indexingScope.ReferencesByCollection != null) { ReferencesForDocuments.WriteReferences(indexingScope.ReferencesByCollection, tx); } if (indexingScope.ReferencesByCollectionForCompareExchange != null) { ReferencesForCompareExchange.WriteReferences(indexingScope.ReferencesByCollectionForCompareExchange, tx); } }
public unsafe void WriteReferences(CurrentIndexingScope indexingScope, RavenTransaction tx) { // IndexSchema: // having 'Users' and 'Addresses' we will end up with // // #Users (tree) - splitted by collection so we can easily return all items of same collection to the indexing function // |- addresses/1 (key) -> [ users/1, users/2 ] // |- addresses/2 (key) -> [ users/3 ] // // References (tree) - used in delete operations // |- users/1 -> [ addresses/1 ] // |- users/2 -> [ addresses/1 ] // |- users/3 -> [ addresses/2 ] // // $Users (tree) - holding highest visible etag of 'referenced collection' per collection, so we will have a starting point for references processing // |- Addresses (key) -> 5 if (indexingScope.ReferencesByCollection != null) { var referencesTree = tx.InnerTransaction.ReadTree(IndexSchema.References); foreach (var collections in indexingScope.ReferencesByCollection) { var collectionTree = tx.InnerTransaction.CreateTree("#" + collections.Key); // #collection foreach (var keys in collections.Value) { using (Slice.From(tx.InnerTransaction.Allocator, keys.Key, ByteStringType.Immutable, out Slice key)) { foreach (var referenceKey in keys.Value) { collectionTree.MultiAdd(referenceKey, key); referencesTree.MultiAdd(key, referenceKey); } RemoveReferences(key, collections.Key, keys.Value, tx); } } } } }
public unsafe void WriteReferences(CurrentIndexingScope indexingScope, RavenTransaction tx) { // IndexSchema: // having 'Users' and 'Addresses' we will end up with // // #Users (tree) - splitted by collection so we can easily return all items of same collection to the indexing function // |- addresses/1 (key) -> [ users/1, users/2 ] // |- addresses/2 (key) -> [ users/3 ] // // References (tree) - used in delete operations // |- users/1 -> [ addresses/1 ] // |- users/2 -> [ addresses/1 ] // |- users/3 -> [ addresses/2 ] // // $Users (tree) - holding highest visible etag of 'referenced collection' per collection, so we will have a starting point for references processing // |- Addresses (key) -> 5 if (indexingScope.ReferencesByCollection != null) { var referencesTree = tx.InnerTransaction.ReadTree(IndexSchema.References); foreach (var collections in indexingScope.ReferencesByCollection) { var collectionTree = tx.InnerTransaction.CreateTree("#" + collections.Key); // #collection foreach (var keys in collections.Value) { using (Slice.From(tx.InnerTransaction.Allocator, keys.Key, ByteStringType.Immutable, out Slice key)) { foreach (var referenceKey in keys.Value) { collectionTree.MultiAdd(referenceKey, key); referencesTree.MultiAdd(key, referenceKey); } RemoveReferences(key, collections.Key, keys.Value, tx); } } } } if (indexingScope.ReferenceEtagsByCollection != null) { foreach (var kvp in indexingScope.ReferenceEtagsByCollection) { var collectionEtagTree = tx.InnerTransaction.CreateTree("$" + kvp.Key); // $collection foreach (var collections in kvp.Value) { if (_referencedCollections.TryGetValue(collections.Key, out CollectionName collectionName) == false) { throw new InvalidOperationException( $"Could not find collection {collections.Key} in the index storage collections. Should not happen ever!"); } using (Slice.From(tx.InnerTransaction.Allocator, collectionName.Name, ByteStringType.Immutable, out Slice collectionKey)) { var etag = collections.Value; var result = collectionEtagTree.Read(collectionKey); var oldEtag = result?.Reader.ReadLittleEndianInt64(); if (oldEtag >= etag) { continue; } using (Slice.External(tx.InnerTransaction.Allocator, (byte *)&etag, sizeof(long), out Slice etagSlice)) collectionEtagTree.Add(collectionKey, etagSlice); } } } } }