Exemple #1
0
        public (List <string> ChangeVectors, NonPersistentDocumentFlags NonPersistentFlags) DeleteConflictsFor(
            DocumentsOperationContext context, Slice lowerId, BlittableJsonReaderObject document)
        {
            if (ConflictsCount == 0)
            {
                return(null, NonPersistentDocumentFlags.None);
            }

            var    changeVectors                = new List <string>();
            var    nonPersistentFlags           = NonPersistentDocumentFlags.None;
            string deleteAttachmentChangeVector = null;

            using (GetConflictsIdPrefix(context, lowerId, out Slice prefixSlice))
            {
                var conflictsTable = context.Transaction.InnerTransaction.OpenTable(ConflictsSchema, ConflictsSlice);
                conflictsTable.DeleteForwardFrom(ConflictsSchema.Indexes[IdAndChangeVectorSlice], prefixSlice, true, long.MaxValue, conflictDocument =>
                {
                    var etag = TableValueToEtag((int)ConflictsTable.Etag, ref conflictDocument.Reader);
                    _documentsStorage.EnsureLastEtagIsPersisted(context, etag);

                    var conflictChangeVector = TableValueToChangeVector(context, (int)ConflictsTable.ChangeVector, ref conflictDocument.Reader);
                    changeVectors.Add(conflictChangeVector);

                    var flags = TableValueToFlags((int)ConflictsTable.Flags, ref conflictDocument.Reader);
                    if ((flags & DocumentFlags.HasAttachments) != DocumentFlags.HasAttachments)
                    {
                        return;
                    }

                    if (string.IsNullOrEmpty(deleteAttachmentChangeVector))
                    {
                        var newEtag = _documentsStorage.GenerateNextEtag();
                        deleteAttachmentChangeVector     = _documentsStorage.GetNewChangeVector(context, newEtag);
                        context.LastDatabaseChangeVector = conflictChangeVector;
                    }
                    nonPersistentFlags |= DeleteAttachmentConflicts(context, lowerId, document, conflictDocument, deleteAttachmentChangeVector);
                });
            }

            // once this value has been set, we can't set it to false
            // an older transaction may be running and seeing it is false it
            // will not detect a conflict. It is an optimization only that
            // we have to do, so we'll handle it.

            // Only register the event if we actually deleted any conflicts
            var listCount = changeVectors.Count;

            if (listCount > 0)
            {
                var tx = context.Transaction.InnerTransaction.LowLevelTransaction;
                tx.AfterCommitWhenNewReadTransactionsPrevented += () =>
                {
                    Interlocked.Add(ref ConflictsCount, -listCount);
                };
            }
            return(changeVectors, nonPersistentFlags);
        }
Exemple #2
0
        public (List <string> ChangeVectors, NonPersistentDocumentFlags NonPersistentFlags) DeleteConflictsFor(
            DocumentsOperationContext context, Slice lowerId, BlittableJsonReaderObject document)
        {
            if (ConflictsCount == 0)
            {
                return(null, NonPersistentDocumentFlags.None);
            }

            var    changeVectors                = new List <string>();
            var    nonPersistentFlags           = NonPersistentDocumentFlags.None;
            string deleteAttachmentChangeVector = null;

            using (GetConflictsIdPrefix(context, lowerId, out Slice prefixSlice))
            {
                var conflictsTable = context.Transaction.InnerTransaction.OpenTable(ConflictsSchema, ConflictsSlice);
                conflictsTable.DeleteForwardFrom(ConflictsSchema.Indexes[IdAndChangeVectorSlice], prefixSlice, true, long.MaxValue, conflictDocument =>
                {
                    var conflicted = TableValueToConflictDocument(context, ref conflictDocument.Reader);
                    var collection = _documentsStorage.ExtractCollectionName(context, conflicted.Collection);

                    if (conflicted.Doc != null)
                    {
                        _documentsStorage.RevisionsStorage.Put(
                            context, conflicted.Id, conflicted.Doc, conflicted.Flags | DocumentFlags.Conflicted, nonPersistentFlags, conflicted.ChangeVector,
                            conflicted.LastModified.Ticks,
                            collectionName: collection, configuration: RevisionsStorage.ConflictConfiguration.Default);
                    }
                    else if (conflicted.Flags.Contain(DocumentFlags.FromReplication) == false)
                    {
                        using (Slice.External(context.Allocator, conflicted.LowerId, out var key))
                        {
                            var lastModifiedTicks = _documentDatabase.Time.GetUtcNow().Ticks;
                            _documentsStorage.RevisionsStorage.DeleteRevision(context, key, conflicted.Collection, conflicted.ChangeVector, lastModifiedTicks);
                        }
                    }
                    _documentsStorage.EnsureLastEtagIsPersisted(context, conflicted.Etag);
                    changeVectors.Add(conflicted.ChangeVector);

                    if (conflicted.Flags.Contain(DocumentFlags.HasAttachments) == false)
                    {
                        return;
                    }

                    if (string.IsNullOrEmpty(deleteAttachmentChangeVector))
                    {
                        var newEtag = _documentsStorage.GenerateNextEtag();
                        deleteAttachmentChangeVector     = _documentsStorage.GetNewChangeVector(context, newEtag);
                        context.LastDatabaseChangeVector = conflicted.ChangeVector;
                    }
                    nonPersistentFlags |= DeleteAttachmentConflicts(context, lowerId, document, conflictDocument, deleteAttachmentChangeVector);
                });
            }

            // once this value has been set, we can't set it to false
            // an older transaction may be running and seeing it is false it
            // will not detect a conflict. It is an optimization only that
            // we have to do, so we'll handle it.

            // Only register the event if we actually deleted any conflicts
            var listCount = changeVectors.Count;

            if (listCount > 0)
            {
                var tx = context.Transaction.InnerTransaction.LowLevelTransaction;
                tx.AfterCommitWhenNewReadTransactionsPrevented += () =>
                {
                    Interlocked.Add(ref ConflictsCount, -listCount);
                };
            }
            return(changeVectors, nonPersistentFlags | NonPersistentDocumentFlags.Resolved);
        }