Ejemplo n.º 1
0
        /// <summary>
        /// Returns the merged result of all the <paramref name="replicas"/>.
        /// </summary>
        /// <param name="biasAdd">True to have equal timestamps bias towards add;
        /// false to have equal timestamps bias towards remove.</param>
        /// <param name="replicas">The list of replicas to merge.</param>
        /// <returns>The merged replica of all the <paramref name="replicas"/>.
        /// </returns>
        static public LwwElementSet <T> Merge(
            bool biasAdd,
            params LwwElementSet <T>[] replicas)
        {
            LwwElementSet <T> mergedReplica = new LwwElementSet <T>();

            mergedReplica.m_biasAdd = biasAdd;

            // Collect all the unique elements from all the replicas.
            COLG.HashSet <T> allElements = new COLG.HashSet <T>();

            for (int i = 0; i < replicas.Length; i++)
            {
                allElements.UnionWith(replicas[i].m_addSet.Keys);
                allElements.UnionWith(replicas[i].m_removeSet.Keys);
            }

            // Go through all the unique elements and get the latest timestamp for
            // its add and/or remove operation.
            foreach (T element in allElements)
            {
                long maxAddTimestamp    = DateTime.MinValue.Ticks;
                long maxRemoveTimestamp = DateTime.MinValue.Ticks;

                for (int i = 0; i < replicas.Length; i++)
                {
                    if (replicas[i].m_addSet.TryGetValue(
                            element, out long addTimestamp))
                    {
                        maxAddTimestamp = Math.Max(maxAddTimestamp, addTimestamp);
                    }

                    if (replicas[i].m_removeSet.TryGetValue(
                            element, out long removeTimestamp))
                    {
                        maxRemoveTimestamp = Math.Max(maxRemoveTimestamp, removeTimestamp);
                    }
                }

                if (maxAddTimestamp != DateTime.MinValue.Ticks)
                {
                    mergedReplica.m_addSet[element] = maxAddTimestamp;
                }

                if (maxRemoveTimestamp != DateTime.MinValue.Ticks)
                {
                    mergedReplica.m_removeSet[element] = maxRemoveTimestamp;
                }
            }

            return(mergedReplica);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Override Equals method to check if two objects are equal.
        /// </summary>
        /// <param name="obj">The object to compare.</param>
        /// <returns>True if they're equal; false if not.</returns>
        public override bool Equals(object obj)
        {
            LwwElementSet <T> other = obj as LwwElementSet <T>;

            if (obj == null ||
                this.m_biasAdd != other.m_biasAdd ||
                this.m_addSet.Count != other.m_addSet.Count ||
                this.m_removeSet.Count != other.m_removeSet.Count)
            {
                return(false);
            }

            // Check the elements and timestamps in the add sets are equal.
            foreach (COLG.KeyValuePair <T, long> kvp in this.m_addSet)
            {
                T    element   = kvp.Key;
                long timestamp = kvp.Value;

                if (other.m_addSet.TryGetValue(element, out long otherTimestamp))
                {
                    if (timestamp != otherTimestamp)
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            // Check the elements and timestamps in the remove sets are equal.
            foreach (COLG.KeyValuePair <T, long> kvp in this.m_removeSet)
            {
                T    element   = kvp.Key;
                long timestamp = kvp.Value;

                if (other.m_removeSet.TryGetValue(element, out long otherTimestamp))
                {
                    if (timestamp != otherTimestamp)
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 3
0
        public void BiasRemoveTest()
        {
            int  element = 1;
            long time    = m_time.GetDateTimeNow();

            LwwElementSet <int> replica = new LwwElementSet <int>();

            replica.Add(element, time);
            replica.Remove(element, time);

            replica.SetBiasRemove();
            Assert.IsTrue(replica.IsEmpty());
            Assert.IsFalse(replica.Lookup(element));
        }
Ejemplo n.º 4
0
        public void MergeReplicasAddTest()
        {
            LwwElementSet <int> replica1 = new LwwElementSet <int>();

            replica1.Add(1, m_time.GetDateTimeNow());

            LwwElementSet <int> replica2 = new LwwElementSet <int>();

            replica2.Add(2, m_time.GetDateTimeNow());

            LwwElementSet <int> mergedReplica =
                LwwElementSet <int> .Merge(true, replica1, replica2);

            Assert.IsFalse(mergedReplica.IsEmpty());
            Assert.IsTrue(mergedReplica.Lookup(1));
            Assert.IsTrue(mergedReplica.Lookup(2));
        }
Ejemplo n.º 5
0
        public void RemoveTest()
        {
            LwwElementSet <int> replica = new LwwElementSet <int>();

            int[] elements = { 1, 2 };

            for (int i = 0; i < elements.Length; i++)
            {
                replica.Remove(elements[i], m_time.GetDateTimeNow());
            }

            Assert.IsTrue(replica.IsEmpty());

            for (int i = 0; i < elements.Length; i++)
            {
                Assert.IsFalse(replica.Lookup(elements[i]));
            }
        }
Ejemplo n.º 6
0
        public void MergeReplicasAddRemoveTest()
        {
            int element = 1;

            LwwElementSet <int> replica1 = new LwwElementSet <int>();

            replica1.Add(element, m_time.GetDateTimeNow());

            LwwElementSet <int> replica2 = new LwwElementSet <int>();

            replica2.Add(element, m_time.GetDateTimeNow());
            replica2.Remove(element, m_time.GetDateTimeNow());

            LwwElementSet <int> mergedReplica =
                LwwElementSet <int> .Merge(true, replica1, replica2);

            Assert.IsTrue(mergedReplica.IsEmpty());
            Assert.IsFalse(mergedReplica.Lookup(element));
        }
Ejemplo n.º 7
0
        public void EmptyReplicaTest()
        {
            LwwElementSet <char> replica = new LwwElementSet <char>();

            Assert.IsTrue(replica.IsEmpty());
        }
Ejemplo n.º 8
0
        public void MergeReplicasRandomOperationsTest()
        {
            // Create multiple replicas to apply multiple operations across.
            int numReplicas = 5;

            COLG.List <LwwElementSet <int> > replicas =
                new COLG.List <LwwElementSet <int> >(numReplicas);

            for (int i = 0; i < numReplicas; i++)
            {
                replicas.Add(new LwwElementSet <int>());
            }

            // Create a single replica to apply all the operations on.
            // This will be used to verify the merged replica of the replicas above.
            LwwElementSet <int> expectedReplica = new LwwElementSet <int>();

            Random rand = new Random();

            COLG.List <long> previousTimes = new COLG.List <long>();
            previousTimes.Add(m_time.GetDateTimeNow());

            int numOperations = 1000;

            for (int i = 0; i < numOperations; i++)
            {
                // Determine which replica to use.
                int index = rand.Next(numReplicas);

                // Determine to use the current time or a previously used time.
                long time;
                if (rand.NextDouble() < 0.5)
                {
                    time = m_time.GetDateTimeNow();
                    previousTimes.Add(time);
                }
                else
                {
                    time = previousTimes[rand.Next(previousTimes.Count)];
                }

                // Determine which element to use (0 to 9, both inclusive).
                int element = rand.Next(100);

                // Determine which operation to use.
                if (rand.NextDouble() < 0.5)
                {
                    replicas[index].Add(element, time);
                    expectedReplica.Add(element, time);
                }
                else
                {
                    replicas[index].Remove(element, time);
                    expectedReplica.Remove(element, time);
                }
            }

            LwwElementSet <int> mergedReplica = LwwElementSet <int> .Merge(
                true, replicas.ToArray());

            Assert.IsTrue(expectedReplica.Equals(mergedReplica));
        }