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); } }
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); }