예제 #1
0
        public void VersionVector_VectorCompareAndNext()
        {
            var a = new VersionVector(A, 4);

            Assert.AreEqual(VectorRelationship.Equal, a.VectorCompare(a));

            var b = new VersionVector(B, 6);

            Assert.AreEqual(VectorRelationship.Conflict, a.VectorCompare(b));
            Assert.AreEqual(VectorRelationship.Conflict, b.VectorCompare(a));

            var cNext = a.Next(C);

            Assert.AreEqual(VectorRelationship.Equal, cNext.VectorCompare(cNext));
            Assert.AreEqual(VectorRelationship.Greater, cNext.VectorCompare(a));
            Assert.AreEqual(VectorRelationship.Conflict, cNext.VectorCompare(b));

            var aNext = (cNext | a).Next(A);
            var bNext = (cNext | b).Next(B);

            Assert.AreEqual(VectorRelationship.Greater, aNext.VectorCompare(cNext));
            Assert.AreEqual(VectorRelationship.Greater, aNext.VectorCompare(a));
            Assert.AreEqual(VectorRelationship.Conflict, aNext.VectorCompare(b));
            Assert.AreEqual(VectorRelationship.Less, cNext.VectorCompare(aNext));
            Assert.AreEqual(VectorRelationship.Less, a.VectorCompare(aNext));
            Assert.AreEqual(VectorRelationship.Conflict, b.VectorCompare(aNext));

            Assert.AreEqual(VectorRelationship.Greater, bNext.VectorCompare(cNext));
            Assert.AreEqual(VectorRelationship.Greater, bNext.VectorCompare(a));
            Assert.AreEqual(VectorRelationship.Greater, bNext.VectorCompare(b));
            Assert.AreEqual(VectorRelationship.Less, cNext.VectorCompare(bNext));
            Assert.AreEqual(VectorRelationship.Less, a.VectorCompare(bNext));
            Assert.AreEqual(VectorRelationship.Less, b.VectorCompare(bNext));
        }
예제 #2
0
        public void Parse_should_handle_multiple_events()
        {
            var vv = VersionVector.Parse("{(r,1),(s,3)}");

            vv["r"].Should().Be(1);
            vv["s"].Should().Be(3);
        }
예제 #3
0
        public void ORSet_must_verify_MergeDisjointKeys()
        {
            var keys     = ImmutableHashSet.CreateRange(new[] { "K3", "K4", "K5" });
            var elements = new Dictionary <string, VersionVector>
            {
                { "K3", VersionVector.Create(_nodeA, 4L) },
                { "K4", VersionVector.Create(new Dictionary <UniqueAddress, long> {
                        { _nodeA, 3L }, { _nodeD, 8L }
                    }.ToImmutableDictionary()) },
                { "K5", VersionVector.Create(_nodeA, 2L) },
            }.ToImmutableDictionary();
            var vvector = VersionVector.Create(new Dictionary <UniqueAddress, long> {
                { _nodeA, 3L }, { _nodeD, 7L }
            }.ToImmutableDictionary());
            var acc = new Dictionary <string, VersionVector> {
                { "K1", VersionVector.Create(_nodeA, 3L) }
            }.ToImmutableDictionary();
            var expectedDots = new Dictionary <string, VersionVector>
            {
                { "K1", VersionVector.Create(_nodeA, 3L) },
                { "K3", VersionVector.Create(_nodeA, 4L) },
                { "K4", VersionVector.Create(_nodeD, 8L) }, // "a" -> 3 removed, optimized to include only those unseen
            };

            ORSet <string> .MergeDisjointKeys(keys, elements, vvector, acc).Should().Equal(expectedDots);
        }
예제 #4
0
        public void Parse_should_handle_single_event()
        {
            var vv = VersionVector.Parse("{(r,1)}");

            vv["r"].Should().Be(1);
            vv["s"].Should().Be(0);
        }
예제 #5
0
        public async Task <OkResult> Put(HttpRequestMessage req, string key, [FromBody] JToken value)
        {
            VersionVector context = GetContext(req);

            await _node.PutAsync(key, value, context);

            return(Ok());
        }
예제 #6
0
        public void Ids_should_return_set_of_identifiers()
        {
            var vv  = new VersionVector(new[] { new CausalEvent("r", 1), new CausalEvent("s", 1) });
            var ids = vv.Ids();

            ids.Should().Contain(new[] { "r", "s" });
            ids.Should().HaveCount(2);
            ids.Should().OnlyHaveUniqueItems();
        }
예제 #7
0
        private void CheckThunkFor(VersionVector vc1, VersionVector vc2, Action <VersionVector, VersionVector> thunk, int times)
        {
            var vcc1 = CopyVectorClock(vc1);
            var vcc2 = CopyVectorClock(vc2);

            for (var i = 0; i < times; i++)
            {
                thunk(vcc1, vcc2);
            }
        }
예제 #8
0
        VersionVector GetContext(HttpRequestMessage request)
        {
            VersionVector vv          = null;
            string        headerValue = request.GetHeader("X-Context");

            if (!string.IsNullOrEmpty(headerValue))
            {
                vv = VersionVector.FromContextString(headerValue);
            }
            return(vv);
        }
        public void ReplicatedDataSerializer_should_serialize_VersionVector()
        {
            CheckSerialization(VersionVector.Empty);
            CheckSerialization(VersionVector.Create(_address1, 1));
            CheckSerialization(VersionVector.Empty.Increment(_address1).Increment(_address2));

            var v1 = VersionVector.Empty.Increment(_address1).Increment(_address1);
            var v2 = VersionVector.Empty.Increment(_address2);

            CheckSameContent(v1.Merge(v2), v2.Merge(v1));
        }
예제 #10
0
        internal VersionVector CopyVectorClock(VersionVector vc)
        {
            var versions   = ImmutableDictionary <UniqueAddress, long> .Empty;
            var enumerator = vc.VersionEnumerator;

            while (enumerator.MoveNext())
            {
                var nodePair = enumerator.Current;
                versions = versions.SetItem(nodePair.Key, nodePair.Value);
            }

            return(VersionVector.Create(versions));
        }
예제 #11
0
        public void ORSet_must_verify_SubtractDots()
        {
            var dot = VersionVector.Create(ImmutableDictionary.CreateRange(new Dictionary <UniqueAddress, long>
            {
                { _nodeA, 3L }, { _nodeB, 2L }, { _nodeD, 14L }, { _nodeG, 22L }
            }));
            var vvector = VersionVector.Create(ImmutableDictionary.CreateRange(new Dictionary <UniqueAddress, long>
            {
                { _nodeA, 4L }, { _nodeB, 1L }, { _nodeC, 1L }, { _nodeD, 14L }, { _nodeE, 5L }, { _nodeF, 2L }
            }));
            var expected = VersionVector.Create(ImmutableDictionary.CreateRange(new Dictionary <UniqueAddress, long>
            {
                { _nodeB, 2L }, { _nodeG, 22L }
            }));

            ORSet.SubtractDots(dot, vvector).Should().Be(expected);
        }
예제 #12
0
        public void Setup()
        {
            var(vcBefore, nodes) = CreateVectorClockOfSize(ClockSize);
            _vcBefore            = vcBefore;
            _nodes = nodes;

            _firstNode  = nodes.First();
            _lastNode   = nodes.Last();
            _middleNode = nodes[ClockSize / 2];

            _vcBaseLast         = vcBefore.Increment(_lastNode);
            _vcAfterLast        = _vcBaseLast.Increment(_firstNode);
            _vcConcurrentLast   = _vcBaseLast.Increment(_lastNode);
            _vcBaseMiddle       = _vcBefore.Increment(_middleNode);
            _vcAfterMiddle      = _vcBaseMiddle.Increment(_firstNode);
            _vcConcurrentMiddle = _vcBaseMiddle.Increment(_middleNode);
        }
예제 #13
0
        public void Join_should_return_a_clock_that_describes_the_collective_causal_past()
        {
            var kernel = new DvvKernel();

            var s1 = new Siblings
            {
                { new JObject(new JProperty("v", 1)), "((r,1),{})" },
                { new JObject(new JProperty("v", 2)), "((r,2),{(s,2)})" }
            };

            VersionVector vv = kernel.Join(s1);

            vv.Events.Should().Contain(new[]
            {
                new KeyValuePair <string, long>("r", 2),
                new KeyValuePair <string, long>("s", 2)
            });
        }
예제 #14
0
        public void VersionVector_ConstructorAndEquality()
        {
            var items = new []
            {
                new VectorItem <int>(A, 4),
                new VectorItem <int>(B, 6),
            };

            var a = new VersionVector(items);

            Assert.IsTrue(a.SequenceEqual(items));

            var b = new VersionVector(
                new VectorItem <int>(A, 4),
                new VectorItem <int>(B, 6));

            Assert.AreEqual(a, b);
        }
예제 #15
0
        public void DataEnvelopes_with_identical_content_must_match()
        {
            var g1  = GCounter.Empty.Increment(node1, 1);
            var d1  = new DataEnvelope(g1);
            var d1a = new DataEnvelope(g1);
            var g2  = GCounter.Empty.Increment(node2, 2);
            var d2  = new DataEnvelope(g2);

            d1.Should().NotBe(d2);
            d1a.Should().Be(d1);
            d1a.GetHashCode().Should().Be(d1.GetHashCode());

            // add some delta versions
            var d1b = d1.WithDeltaVersions(VersionVector.Create(node1, 1));

            d1.Should().NotBe(d1b);
            d1.GetHashCode().Should().NotBe(d1b.GetHashCode());

            // add identical delta version on different instance
            var d1b2 = d1.WithDeltaVersions(VersionVector.Create(node1, 1));

            d1b2.Should().Be(d1b);
            d1b2.GetHashCode().Should().Be(d1b.GetHashCode());

            // merge with another instance
            var d2b1 = d1b2.Merge(d2);

            d2b1.Should().NotBe(d1b2);
            d2b1.GetHashCode().Should().NotBe(d1b2.GetHashCode());

            // prune
            var d3 = d2b1.WithPruning(
                ImmutableDictionary <UniqueAddress, IPruningState> .Empty.Add(node2, new PruningPerformed(obsoleteTime)));

            d3.Should().NotBe(d2b1);
            d3.GetHashCode().Should().NotBe(d2b1.GetHashCode());

            // create identical instance
            var d3b = d2b1.WithPruning(
                ImmutableDictionary <UniqueAddress, IPruningState> .Empty.Add(node2, new PruningPerformed(obsoleteTime)));

            d3.Should().Be(d3b);
            d3.GetHashCode().Should().Be(d3b.GetHashCode());
        }
예제 #16
0
        public static Proto.Msg.VersionVector VersionVectorToProto(VersionVector versionVector)
        {
            var b = new Proto.Msg.VersionVector();

            using (var enumerator = versionVector.VersionEnumerator)
            {
                while (enumerator.MoveNext())
                {
                    var current = enumerator.Current;
                    b.Entries.Add(new Proto.Msg.VersionVector.Types.Entry()
                    {
                        Node    = UniqueAddressToProto(current.Key),
                        Version = current.Value
                    });
                }
            }

            return(b);
        }
예제 #17
0
        public void Event_should_generate_a_new_clock_to_represent_a_new_version()
        {
            var kernel = new DvvKernel();

            var context = new VersionVector(new[]
            {
                new CausalEvent("s", 2),
                new CausalEvent("r", 2),
            });

            var s1 = new Siblings
            {
                { new JObject(new JProperty("v", 1)), "((r,1),{})" },
                { new JObject(new JProperty("v", 2)), "((r,2),{(s,2)})" }
            };

            DottedVersionVector dvv = kernel.Event(context, s1, "r");

            dvv.ToString().Should().Be("((r,3),{(r,2),(s,2)})");
        }
예제 #18
0
        public async Task <IHttpActionResult> Get(HttpRequestMessage req, string key)
        {
            try
            {
                Siblings siblings = await _node.GetAsync(key);

                // Only return the values (strip-off the clocks)
                List <JToken> values = siblings.Select(s => s.Value).ToList();

                HttpResponseMessage res     = req.CreateResponse(values);
                VersionVector       context = _node.Kernel.Join(siblings);
                res.Headers.Add("X-Context", context.ToContextString());

                return(ResponseMessage(res));
            }
            catch (KeyNotFoundException e)
            {
                return(NotFound());
            }
        }
예제 #19
0
        public void Discard_should_remove_obsolete_siblings()
        {
            var kernel = new DvvKernel();

            var s1 = new Siblings
            {
                { new JObject(new JProperty("v", 1)), "((r,1),{})" },
                { new JObject(new JProperty("v", 2)), "((r,2),{})" }
            };

            // This is the context we'd receive representing ((r,3),{(r,1)}) : v3
            var context = new VersionVector(new CausalEvent("r", 1));

            Siblings siblings = kernel.Discard(s1, context);

            // Assert
            siblings.Should().HaveCount(1);

            siblings.Should().NotContain(x => x.Clock.Equals(DottedVersionVector.Parse("((r,1),{})")));
            siblings.Should().Contain(x => x.Clock.Equals(DottedVersionVector.Parse("((r,2),{})")));
        }
예제 #20
0
        public void ORSet_must_verify_MergeCommonKeys()
        {
            var commonKeys = ImmutableHashSet.CreateRange(new[] { "K1", "K2" });
            var thisDot1   = VersionVector.Create(new Dictionary <UniqueAddress, long> {
                { _nodeA, 3L }, { _nodeD, 7L }
            }.ToImmutableDictionary());
            var thisDot2 = VersionVector.Create(new Dictionary <UniqueAddress, long> {
                { _nodeB, 5L }, { _nodeC, 2L }
            }.ToImmutableDictionary());
            var thisVVector = VersionVector.Create(new Dictionary <UniqueAddress, long> {
                { _nodeA, 3L }, { _nodeB, 5L }, { _nodeC, 2L }, { _nodeD, 7L }
            }.ToImmutableDictionary());

            var thisSet = new ORSet <string>(
                elementsMap: new Dictionary <string, VersionVector> {
                { "K1", thisDot1 }, { "K2", thisDot2 }
            }.ToImmutableDictionary(),
                versionVector: thisVVector);

            var thatDot1    = VersionVector.Create(_nodeA, 3L);
            var thatDot2    = VersionVector.Create(_nodeB, 6L);
            var thatVVector = VersionVector.Create(new Dictionary <UniqueAddress, long> {
                { _nodeA, 3L }, { _nodeB, 6L }, { _nodeC, 1L }, { _nodeD, 8L }
            }.ToImmutableDictionary());
            var thatSet = new ORSet <string>(
                elementsMap: new Dictionary <string, VersionVector> {
                { "K1", thatDot1 }, { "K2", thatDot2 }
            }.ToImmutableDictionary(),
                versionVector: thatVVector);

            var expectedDots = new Dictionary <string, VersionVector>
            {
                { "K1", VersionVector.Create(_nodeA, 3L) },
                { "K2", VersionVector.Create(new Dictionary <UniqueAddress, long> {
                        { _nodeB, 6L }, { _nodeC, 2L }
                    }.ToImmutableDictionary()) }
            };

            ORSet <string> .MergeCommonKeys(commonKeys, thisSet, thatSet).Should().Equal(expectedDots);
        }
예제 #21
0
        public void ToString_should_handle_multiple_events()
        {
            var vv = new VersionVector(new[] { new CausalEvent("r", 1), new CausalEvent("s", 1) });

            vv.ToString().Should().Be("{(r,1),(s,1)}");
        }
예제 #22
0
 /// <summary>
 /// Wraps the value in a <see cref="Gossip.VecVersioned{T}"/> with the given version vector.
 /// </summary>
 public static VecVersioned <T> Version <T>(this T val, VersionVector version = null) =>
 new VecVersioned <T>
 {
     Value = val, Version = version ?? new VersionVector()
 };
예제 #23
0
 /// <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;
 }
예제 #24
0
        public void Indexer_should_return_zero_for_missing_id()
        {
            var vv = new VersionVector(new CausalEvent("r", 1));

            vv["x"].Should().Be(0);
        }
예제 #25
0
        public void Parse_should_return_empty_vv_when_value_is_null_or_whitespace(object value)
        {
            var vv = VersionVector.Parse((string)value);

            vv.Events.Should().HaveCount(0);
        }
예제 #26
0
 public static Version <Actor, K, V> ToVersion <ConflictV, OrdActor, Actor, K, V>(this VersionVector <ConflictV, OrdActor, TLong, Actor, long, V> vector, K key)
     where OrdActor   : struct, Ord <Actor>
     where ConflictV : struct, Conflict <V> =>
 vector.Value.IsSome
         ? new VersionValueVector <ConflictV, OrdActor, Actor, K, V>(key, vector)
 : new VersionDeletedVector <ConflictV, OrdActor, Actor, K, V>(key, vector);
예제 #27
0
 /// <summary>
 /// Register a write from any actor
 /// </summary>
 /// <param name="actor">Actor that did the write operation</param>
 /// <param name="value">Value that the actor wrote</param>
 /// <param name="vector">The vector of the actor</param>
 /// <returns></returns>
 public VersionVector <ConflictA, OrdActor, NumClock, Actor, Clock, A> Put(VersionVector <ConflictA, OrdActor, NumClock, Actor, Clock, A> version) =>
 VectorClock.relation(Vector, version.Vector) switch
 {
예제 #28
0
        public void Indexer_should_return_counter_for_id_regardless_of_case()
        {
            var vv = new VersionVector(new CausalEvent("r", 1));

            vv["R"].Should().Be(1);
        }
예제 #29
0
 internal DataEnvelope WithDeltaVersions(VersionVector deltaVersions) =>
 new DataEnvelope(Data, Pruning, deltaVersions);
예제 #30
0
        public void Parse_should_return_empty_vv_when_no_causal_events()
        {
            var vv = VersionVector.Parse("{}");

            vv.Events.Should().HaveCount(0);
        }