Пример #1
0
        private void Delete(DocumentsOperationContext context, Slice lowerId, Slice idSlice, string id, CollectionName collectionName,
                            BlittableJsonReaderObject deleteRevisionDocument, string changeVector,
                            long lastModifiedTicks, NonPersistentDocumentFlags nonPersistentFlags, DocumentFlags flags)
        {
            Debug.Assert(changeVector != null, "Change vector must be set");

            if (flags.Contain(DocumentFlags.HasAttachments))
            {
                flags &= ~DocumentFlags.HasAttachments;
            }

            var configuration = GetRevisionsConfiguration(collectionName.Name, flags);

            if (configuration.Disabled)
            {
                return;
            }

            var table = EnsureRevisionTableCreated(context.Transaction.InnerTransaction, collectionName);

            if (configuration.PurgeOnDelete)
            {
                using (GetKeyPrefix(context, lowerId, out Slice prefixSlice))
                {
                    DeleteRevisions(context, table, prefixSlice, collectionName, long.MaxValue, null, changeVector, lastModifiedTicks);
                    DeleteCountOfRevisions(context, prefixSlice);
                }

                return;
            }

            var fromReplication = (nonPersistentFlags & NonPersistentDocumentFlags.FromReplication) == NonPersistentDocumentFlags.FromReplication;

            if (fromReplication)
            {
                void DeleteFromRevisionIfChangeVectorIsGreater()
                {
                    TableValueReader tvr;

                    try
                    {
                        var hasDoc = _documentsStorage.GetTableValueReaderForDocument(context, lowerId, throwOnConflict: true, tvr: out tvr);
                        if (hasDoc == false)
                        {
                            return;
                        }
                    }
                    catch (DocumentConflictException)
                    {
                        // Do not modify the document.
                        return;
                    }

                    var docChangeVector = TableValueToChangeVector(context, (int)DocumentsTable.ChangeVector, ref tvr);

                    if (ChangeVectorUtils.GetConflictStatus(changeVector, docChangeVector) == ConflictStatus.Update)
                    {
                        _documentsStorage.Delete(context, lowerId, id, null, lastModifiedTicks, changeVector, collectionName,
                                                 nonPersistentFlags | NonPersistentDocumentFlags.FromRevision);
                    }
                }

                DeleteFromRevisionIfChangeVectorIsGreater();
            }

            var newEtag          = _database.DocumentsStorage.GenerateNextEtag();
            var newEtagSwapBytes = Bits.SwapBytes(newEtag);

            using (table.Allocate(out TableValueBuilder tvb))
                using (Slice.From(context.Allocator, changeVector, out var cv))
                {
                    tvb.Add(cv.Content.Ptr, cv.Size);
                    tvb.Add(lowerId);
                    tvb.Add(SpecialChars.RecordSeparator);
                    tvb.Add(newEtagSwapBytes);
                    tvb.Add(idSlice);
                    tvb.Add(deleteRevisionDocument.BasePointer, deleteRevisionDocument.Size);
                    tvb.Add((int)(DocumentFlags.DeleteRevision | flags));
                    tvb.Add(newEtagSwapBytes);
                    tvb.Add(lastModifiedTicks);
                    tvb.Add(context.GetTransactionMarker());
                    if (flags.Contain(DocumentFlags.Resolved))
                    {
                        tvb.Add((int)DocumentFlags.Resolved);
                    }
                    else
                    {
                        tvb.Add(0);
                    }
                    tvb.Add(Bits.SwapBytes(lastModifiedTicks));
                    var isNew = table.Set(tvb);
                    if (isNew == false)
                    {
                        // It might be just an update from replication as we call this twice, both for the doc delete and for deleteRevision.
                        return;
                    }
                }

            DeleteOldRevisions(context, table, lowerId, collectionName, configuration, nonPersistentFlags, changeVector, lastModifiedTicks);
        }