예제 #1
0
        public static ReplicationBatchItem From(Tombstone doc)
        {
            var item = new ReplicationBatchItem
            {
                Etag = doc.Etag,
                Id   = doc.LowerId,
                TransactionMarker = doc.TransactionMarker,
                ChangeVector      = doc.ChangeVector
            };

            switch (doc.Type)
            {
            case Tombstone.TombstoneType.Document:
                item.Type              = ReplicationItemType.DocumentTombstone;
                item.Collection        = doc.Collection;
                item.Flags             = doc.Flags;
                item.LastModifiedTicks = doc.LastModified.Ticks;
                break;

            case Tombstone.TombstoneType.Attachment:
                item.Type = ReplicationItemType.AttachmentTombstone;
                break;

            case Tombstone.TombstoneType.Revision:
                item.Type       = ReplicationItemType.RevisionTombstone;
                item.Collection = doc.Collection;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(doc.Type));
            }

            return(item);
        }
예제 #2
0
 private void DisposeReplicationItem(ReplicationBatchItem item)
 {
     if (item.Type == ReplicationBatchItem.ReplicationItemType.Attachment)
     {
         item.Stream.Dispose();
     }
     else
     {
         item.Data?.Dispose(); //item.Value.Data is null if tombstone
     }
 }
예제 #3
0
 public string GetItemInformation(ReplicationBatchItem item)
 {
     return(item switch
     {
         AttachmentReplicationItem a => "Attachment for " + GetDocumentId(a.Key),
         AttachmentTombstoneReplicationItem at => "Attachment tombstone for: " + GetDocumentId(at.Key),
         CounterReplicationItem c => "Counter for " + c.Id,
         DocumentReplicationItem d => "Document " + d.Id,
         RevisionTombstoneReplicationItem r => "Revision for: " + r.Id,
         TimeSeriesDeletedRangeItem td => "Time Series deletion range for: " + GetDocumentId(td.Key),
         TimeSeriesReplicationItem t => "Time Series for: " + GetDocumentId(t.Key),
         _ => throw new ArgumentOutOfRangeException($"{nameof(item)} - {item}")
     });
예제 #4
0
        private unsafe bool AddReplicationItemToBatch(ReplicationBatchItem item, OutgoingReplicationStatsScope stats)
        {
            if (item.Type == ReplicationBatchItem.ReplicationItemType.Document ||
                item.Type == ReplicationBatchItem.ReplicationItemType.DocumentTombstone)
            {
                if ((item.Flags & DocumentFlags.Artificial) == DocumentFlags.Artificial)
                {
                    stats.RecordArtificialDocumentSkip();

                    if (_log.IsInfoEnabled)
                    {
                        _log.Info($"Skipping replication of {item.Id} because it is an artificial document");
                    }
                    return(false);
                }

                if (CollectionName.IsSystemDocument(item.Id.Buffer, item.Id.Size, out bool isHiLo) && isHiLo == false)
                {
                    stats.RecordSystemDocumentSkip();

                    if (_log.IsInfoEnabled)
                    {
                        _log.Info($"Skipping replication of {item.Id} because it is a system document");
                    }
                    return(false);
                }
            }

            // destination already has it
            if (ChangeVectorUtils.GetConflictStatus(item.ChangeVector, _parent.LastAcceptedChangeVector) == ConflictStatus.AlreadyMerged)
            {
                stats.RecordChangeVectorSkip();

                if (_log.IsInfoEnabled)
                {
                    _log.Info($"Skipping replication of {item.Type} '{item.Id}' because destination has a higher change vector. Current: {item.ChangeVector} < Destination: {_parent._destinationLastKnownChangeVectorAsString} ");
                }
                return(false);
            }

            if (item.Type == ReplicationBatchItem.ReplicationItemType.Attachment)
            {
                _replicaAttachmentStreams[item.Base64Hash] = item;
            }

            Debug.Assert(item.Flags.HasFlag(DocumentFlags.Artificial) == false);
            _orderedReplicaItems.Add(item.Etag, item);
            return(true);
        }
        private void AssertNoLegacyReplicationViolation(ReplicationBatchItem item)
        {
            if (_parent.SupportedFeatures.Replication.CountersBatch == false)
            {
                AssertNotCounterForLegacyReplication(item);
            }

            if (_parent.SupportedFeatures.Replication.ClusterTransaction == false)
            {
                AssertNotClusterTransactionDocumentForLegacyReplication(item);
            }

            if (_parent.SupportedFeatures.Replication.TimeSeries == false)
            {
                AssertNotTimeSeriesForLegacyReplication(item);
            }
        }
예제 #6
0
        private void AssertNotIncrementalTimeSeriesForLegacyReplication(ReplicationBatchItem item)
        {
            if (item.Type == ReplicationBatchItem.ReplicationItemType.TimeSeriesSegment || item.Type == ReplicationBatchItem.ReplicationItemType.DeletedTimeSeriesRange)
            {
                using (_parent._database.DocumentsStorage.ContextPool.AllocateOperationContext(out JsonOperationContext context))
                {
                    LazyStringValue name;
                    switch (item)
                    {
                    case TimeSeriesDeletedRangeItem timeSeriesDeletedRangeItem:
                        TimeSeriesValuesSegment.ParseTimeSeriesKey(timeSeriesDeletedRangeItem.Key, context, out _, out name);
                        break;

                    case TimeSeriesReplicationItem timeSeriesReplicationItem:
                        name = timeSeriesReplicationItem.Name;
                        break;

                    default:
                        return;
                    }

                    if (TimeSeriesHandler.CheckIfIncrementalTs(name) == false)
                    {
                        return;
                    }
                }

                // the other side doesn't support incremental time series, stopping replication
                var message = $"{_parent.Node.FromString()} found an item of type 'IncrementalTimeSeries' to replicate to {_parent.Destination.FromString()}, " +
                              $"while we are in legacy mode (downgraded our replication version to match the destination). " +
                              $"Can't send Incremental-TimeSeries in legacy mode, destination {_parent.Destination.FromString()} does not support Incremental-TimeSeries feature. Stopping replication.";

                if (_log.IsInfoEnabled)
                {
                    _log.Info(message);
                }

                throw new LegacyReplicationViolationException(message);
            }
        }