Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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);
                        }
                    }
                }
            }
        }
Exemple #3
0
        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);
                        }
                    }
                }
            }
        }