public IReplicatedData Merge(IReplicatedData other) { var atomic = other as AtomicDeltaOperation; if (atomic != null) { var lastIndex = Operations.Length - 1; var last = Operations[lastIndex]; if (last is PutDeltaOperation || last is UpdateDeltaOperation) { var builder = this.Operations.ToList(); var merged = (IDeltaOperation)last.Merge(atomic); if (merged is AtomicDeltaOperation) { builder[lastIndex] = merged; return(new DeltaGroup(builder)); } else { builder.RemoveAt(lastIndex); builder.AddRange(((DeltaGroup)merged).Operations); return(new DeltaGroup(builder)); } } else { return(new DeltaGroup(Operations.Union(new[] { atomic }))); } } else { var group = (DeltaGroup)other; return(new DeltaGroup(this.Operations.Union(group.Operations))); } }
/// <summary> /// Modify value of local <see cref="Replicator"/> and replicate with given <see cref="IWriteConsistency"/>. /// /// The current value for the <see cref="Key"/> is passed to the <see cref="Modify"/> function. /// If there is no current data value for the <see cref="Key"/> the <paramref name="initial"/> value will be /// passed to the <see cref="Modify"/> function. /// /// The optional <paramref name="request"/> context is included in the reply messages. This is a convenient /// way to pass contextual information (e.g. original sender) without having to use `ask` /// or local correlation data structures. /// </summary> public Update(IKey key, IReplicatedData initial, IWriteConsistency consistency, Func <IReplicatedData, IReplicatedData> modify, object request = null) { Key = key; Consistency = consistency; Request = request; Modify = x => ModifyWithInitial(initial, modify, x); }
private IReplicatedData Cleaned(IReplicatedData c, IImmutableDictionary <UniqueAddress, IPruningState> p) => p.Aggregate(c, (state, kvp) => { if (c is IRemovedNodePruning pruning && kvp.Value is PruningPerformed && pruning.NeedPruningFrom(kvp.Key)) { return(pruning.PruningCleanup(kvp.Key));
public override IReplicatedData Merge(IReplicatedData other) { switch (other) { case AddDeltaOperation operation: { var u = operation.Underlying; // Note that we only merge deltas originating from the same node return(new AddDeltaOperation(new ORSet <T>( ConcatElementsMap(u.ElementsMap), Underlying.VersionVector.Merge(u.VersionVector)))); } case AtomicDeltaOperation _: return(new DeltaGroup(ImmutableArray.Create(this, other))); case DeltaGroup dg: { var vector = dg.Operations; return(new DeltaGroup(vector.Add(this))); } default: throw new ArgumentException($"Unknown delta operation of type {other.GetType()}", nameof(other)); } }
public IReplicatedData Merge(IReplicatedData other) { if (other is ORMultiValueDictionaryDelta d) { return(new ORMultiValueDictionaryDelta((ORDictionary <TKey, ORSet <TValue> > .IDeltaOperation)Underlying.Merge(d.Underlying), WithValueDeltas || d.WithValueDeltas)); } return(new ORMultiValueDictionaryDelta((ORDictionary <TKey, ORSet <TValue> > .IDeltaOperation)Underlying.Merge(other), WithValueDeltas)); }
public IReplicatedData Merge(IReplicatedData other) { if (other is PNCounterDictionaryDelta d) { return(new PNCounterDictionaryDelta((ORDictionary <TKey, PNCounter> .IDeltaOperation)Underlying.Merge(d.Underlying))); } return(new PNCounterDictionaryDelta((ORDictionary <TKey, PNCounter> .IDeltaOperation)Underlying.Merge(other))); }
public IReplicatedData Merge(IReplicatedData other) { if (other is LWWDictionaryDelta d) { return(new LWWDictionaryDelta((ORDictionary <TKey, LWWRegister <TValue> > .IDeltaOperation)Underlying.Merge(d.Underlying))); } return(new LWWDictionaryDelta((ORDictionary <TKey, LWWRegister <TValue> > .IDeltaOperation)Underlying.Merge(other))); }
private IReplicatedData PruningCleanupTombstoned(IReplicatedData data) { if (_tombstonedNodes.IsEmpty) { return(data); } else { return(_tombstonedNodes.Aggregate(data, (d, removed) => PruningCleanupTombstoned(removed, d))); } }
/// <summary> /// TBD /// </summary> /// <param name="otherData">TBD</param> /// <returns>TBD</returns> internal DataEnvelope Merge(IReplicatedData otherData) { if (otherData is DeletedData) { return(DeletedEnvelope); } var data = Data.Merge(Cleaned(otherData, Pruning)); return(new DataEnvelope(data, Pruning)); }
public void Update(string key, IReplicatedData delta) { // bump the counter for each update var version = _deltaCounter.GetValueOrDefault(key, 0L) + 1; _deltaCounter = _deltaCounter.SetItem(key, version); var deltaEntriesForKey = _deltaEntries.GetValueOrDefault(key, ImmutableSortedDictionary <long, IReplicatedData> .Empty); _deltaEntries = _deltaEntries.SetItem(key, deltaEntriesForKey.SetItem(version, delta)); }
private IReplicatedData PruningCleanupTombstoned(UniqueAddress removed, IReplicatedData data) { var d = data as IRemovedNodePruning; if (d != null) { if (d.NeedPruningFrom(removed)) { return(d.PruningCleanup(removed)); } } return(data); }
private IReplicatedData PruningCleanupTombstoned(IReplicatedData data) { if (_tombstonedNodes.Count == 0) { return(data); } else { return(_tombstonedNodes.Aggregate(data, (d, removed) => { return PruningCleanupTombstoned(removed, d); })); } }
public virtual IReplicatedData Merge(IReplicatedData other) { if (other is AtomicDeltaOperation) { return(new DeltaGroup(ImmutableArray.Create(this, (IDeltaOperation)other))); } else { var builder = ImmutableArray <IDeltaOperation> .Empty.ToBuilder(); builder.Add(this); builder.AddRange(((DeltaGroup)other).Operations); return(new DeltaGroup(builder.ToImmutable())); } }
public override IReplicatedData Merge(IReplicatedData other) { if (other is AtomicDeltaOperation) { return(new DeltaGroup(ImmutableArray.Create(this, other))); } else if (other is DeltaGroup) { var vector = ((DeltaGroup)other).Operations; return(new DeltaGroup(vector.Add(this))); } else { throw new ArgumentException($"Unknown delta operation of type {other.GetType()}", nameof(other)); } }
public IReplicatedData Merge(IReplicatedData other) { if (other is AddDeltaOperation) { // merge AddDeltaOp into last AddDeltaOp in the group, if possible var last = Operations[Operations.Length - 1]; return(last is AddDeltaOperation ? new DeltaGroup(Operations.SetItem(Operations.Length - 1, other.Merge(last))) : new DeltaGroup(Operations.Add(other))); } else if (other is DeltaGroup @group) { var otherVector = @group.Operations; return(new DeltaGroup(Operations.AddRange(otherVector))); } else { return(new DeltaGroup(Operations.Add(other))); } }
public override IReplicatedData Merge(IReplicatedData other) { PutDeltaOperation put; if (other is UpdateDeltaOperation) { var update = (UpdateDeltaOperation)other; var builder = this.Values.ToBuilder(); foreach (var entry in update.Values) { IReplicatedData value; if (this.Values.TryGetValue(entry.Key, out value)) { builder[entry.Key] = value.Merge(entry.Value); } else { builder.Add(entry); } } return(new UpdateDeltaOperation( underlying: (ORSet <TKey> .IDeltaOperation) this.Underlying.Merge(update.Underlying), values: builder.ToImmutable())); } else if ((put = other as PutDeltaOperation) != null && this.Values.Count == 1 && this.Values.ContainsKey(put.Key)) { return(new PutDeltaOperation((ORSet <TKey> .IDeltaOperation) this.Underlying.Merge(put.Underlying), put.Key, put.Value)); } else if (other is AtomicDeltaOperation) { return(new DeltaGroup(ImmutableArray.Create(this, (IDeltaOperation)other))); } else { var builder = ImmutableArray <IDeltaOperation> .Empty.ToBuilder(); builder.Add(this); builder.AddRange(((DeltaGroup)other).Operations); return(new DeltaGroup(builder.ToImmutable())); } }
/// <summary> /// TBD /// </summary> /// <param name="otherData">TBD</param> /// <returns>TBD</returns> internal DataEnvelope Merge(IReplicatedData otherData) { if (otherData is DeletedData) { return(DeletedEnvelope); } var cleanedData = Cleaned(otherData, Pruning); IReplicatedData mergedData; if (cleanedData is IReplicatedDelta d) { var delta = Data as IDeltaReplicatedData ?? throw new ArgumentException($"Expected {nameof(IDeltaReplicatedData)} but got '{Data}' instead."); mergedData = delta.MergeDelta(d); } else { mergedData = Data.Merge(cleanedData); } return(new DataEnvelope(mergedData, Pruning, DeltaVersions)); }
public override IReplicatedData Merge(IReplicatedData other) { UpdateDeltaOperation update; var put = other as PutDeltaOperation; if (put != null && Equals(Key, put.Key)) { return(new PutDeltaOperation((ORSet <TKey> .IDeltaOperation)Underlying.Merge(put.Underlying), put.Key, put.Value)); } else if ((update = other as UpdateDeltaOperation) != null && update.Values.Count == 1 && update.Values.ContainsKey(Key)) { var merged = (ORSet <TKey> .IDeltaOperation) this.Underlying.Merge(update.Underlying); var e2 = update.Values.First().Value; if (Value is IDeltaReplicatedData) { var mergedDelta = ((IDeltaReplicatedData)Value).MergeDelta((IReplicatedDelta)e2); return(new PutDeltaOperation(merged, Key, (TValue)mergedDelta)); } else { var mergedDelta = Value.Merge(e2); return(new PutDeltaOperation(merged, Key, (TValue)mergedDelta)); } } else if (other is AtomicDeltaOperation) { return(new DeltaGroup(ImmutableArray.Create(this, (IDeltaOperation)other))); } else { var builder = ImmutableArray <IDeltaOperation> .Empty.ToBuilder(); builder.Add(this); builder.AddRange(((DeltaGroup)other).Operations); return(new DeltaGroup(builder.ToImmutable())); } }
public override IReplicatedData Merge(IReplicatedData other) { if (other is AddDeltaOperation) { var u = ((AddDeltaOperation)other).Underlying; // Note that we only merge deltas originating from the same node return(new AddDeltaOperation(new ORSet <T>( ConcatElementsMap(u.ElementsMap), Underlying.VersionVector.Merge(u.VersionVector)))); } else if (other is AtomicDeltaOperation) { return(new DeltaGroup(ImmutableArray.Create(this, other))); } else if (other is DeltaGroup) { var vector = ((DeltaGroup)other).Operations; return(new DeltaGroup(vector.Add(this))); } else { throw new ArgumentException($"Unknown delta operation of type {other.GetType()}", nameof(other)); } }
/// <summary> /// The <see cref="DataEnvelope"/> wraps a data entry and carries state of the pruning process for the entry. /// </summary> /// <param name="data">TBD</param> /// <param name="pruning">TBD</param> /// <param name="deltaVersions"></param> internal DataEnvelope(IReplicatedData data, ImmutableDictionary <UniqueAddress, IPruningState> pruning = null, VersionVector deltaVersions = null) { Data = data; Pruning = pruning ?? ImmutableDictionary <UniqueAddress, IPruningState> .Empty; DeltaVersions = deltaVersions ?? VersionVector.Empty; }
/// <summary> /// TBD /// </summary> /// <returns>TBD</returns> public IReplicatedData Merge(IReplicatedData other) => Merge((DeletedData)other);
public IReplicatedData Merge(IReplicatedData other) => Merge((VersionVector)other);
/// <summary> /// Reply from <see cref="Get"/>. The data value is retrieved with <see cref="Data"/>. /// </summary> public GetSuccess(IKey key, object request, IReplicatedData data) { Key = key; Request = request; Data = data; }
private IReplicatedData ModifyWithInitial(IReplicatedData initial, Func <IReplicatedData, IReplicatedData> modifier, IReplicatedData data) => modifier(data ?? initial);
public IReplicatedData Merge(IReplicatedData other) => Merge((PNCounterDictionary <TKey>)other);
public IReplicatedData Merge(IReplicatedData other) => Merge((PNCounter)other);
public IReplicatedData Merge(IReplicatedData other) => Merge((ORMultiValueDictionary <TKey, TValue>)other);
internal DataEnvelope WithData(IReplicatedData data) => new DataEnvelope(data, Pruning, DeltaVersions);
/// <summary> /// TBD /// </summary> /// <param name="other">TBD</param> /// <returns>TBD</returns> public IReplicatedData Merge(IReplicatedData other) => Merge((T)other);
/// <summary> /// TBD /// </summary> /// <param name="other">TBD</param> /// <returns>TBD</returns> public IReplicatedData Merge(IReplicatedData other) => Merge((LWWDictionary <TKey, TValue>)other);