Example #1
0
        public void DeleteRevisionsFor(DocumentsOperationContext context, string id)
        {
            using (DocumentIdWorker.GetSliceFromId(context, id, out Slice lowerId))
                using (GetKeyPrefix(context, lowerId, out Slice prefixSlice))
                {
                    var collectionName = GetCollectionFor(context, prefixSlice);
                    if (collectionName == null)
                    {
                        if (_logger.IsInfoEnabled)
                        {
                            _logger.Info($"Tried to delete all revisions for '{id}' but no revisions found.");
                        }
                        return;
                    }

                    var table        = EnsureRevisionTableCreated(context.Transaction.InnerTransaction, collectionName);
                    var newEtag      = _documentsStorage.GenerateNextEtag();
                    var changeVector = _documentsStorage.GetNewChangeVector(context, newEtag);
                    context.LastDatabaseChangeVector = changeVector;
                    DeleteRevisions(context, table, prefixSlice, collectionName, long.MaxValue, null, changeVector);
                    DeleteCountOfRevisions(context, prefixSlice);
                }
        }
Example #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);
        }