Beispiel #1
0
        private static void SimpleMapTest()
        {
            var map = new FastMap <string>();

            Assert.IsTrue(map.IsEmpty);
            Assert.AreEqual(0, map.Count);
            Assert.IsFalse(map.Find(5).Next(out _));
            Assert.IsFalse(map.Find(6).Next(out _));
            Assert.IsFalse(map.Find(7).Next(out _));

            int indexA5 = map.Insert(5, "a");

            Assert.IsFalse(map.IsEmpty);
            Assert.AreEqual(1, map.Count);
            Assert.IsTrue(map.Find(5).Next(out var index));
            Assert.AreEqual(indexA5, index);
            Assert.IsFalse(map.Find(6).Next(out _));
            Assert.IsFalse(map.Find(7).Next(out _));

            int indexB6    = map.Insert(6, "b");
            int indexA5Two = map.Insert(5, "a");
            int indexB5    = map.Insert(5, "b");

            Assert.IsTrue(indexA5 != indexA5Two);
            Assert.IsTrue(indexA5 != indexB5);
            Assert.IsTrue(indexA5Two != indexB5);

            Assert.IsFalse(map.IsEmpty);
            Assert.AreEqual(4, map.Count);

            var traverser = map.Find(5);

            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexB5, index);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexA5Two, index);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexA5, index);
            Assert.IsFalse(traverser.Next(out _));

            traverser = map.Find(6);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexB6, index);
            Assert.IsFalse(traverser.Next(out _));

            Assert.IsFalse(map.Find(7).Next(out _));

            map.Remove(indexA5);

            Assert.IsFalse(map.IsEmpty);
            Assert.AreEqual(3, map.Count);

            traverser = map.Find(5);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexB5, index);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexA5Two, index);
            Assert.IsFalse(traverser.Next(out _));

            traverser = map.Find(6);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexB6, index);
            Assert.IsFalse(traverser.Next(out _));

            Assert.IsFalse(map.Find(7).Next(out _));

            map.Remove(indexA5Two);
            map.Remove(indexB6);

            Assert.IsFalse(map.IsEmpty);
            Assert.AreEqual(1, map.Count);

            traverser = map.Find(5);
            Assert.IsTrue(traverser.Next(out index));
            Assert.AreEqual(indexB5, index);
            Assert.IsFalse(traverser.Next(out _));
            Assert.IsFalse(map.Find(6).Next(out _));
            Assert.IsFalse(map.Find(7).Next(out _));

            map.Remove(indexB5);

            Assert.IsTrue(map.IsEmpty);
            Assert.AreEqual(0, map.Count);
            Assert.IsFalse(map.Find(5).Next(out _));
            Assert.IsFalse(map.Find(6).Next(out _));
            Assert.IsFalse(map.Find(7).Next(out _));
        }
Beispiel #2
0
        private static void ReuseTest()
        {
            var map = new FastMap <string>(5);

            Assert.AreEqual(1, map.Insert(5, "0"));
            Assert.AreEqual(2, map.Insert(5, "1"));
            Assert.AreEqual(3, map.Insert(5, "2"));
            Assert.AreEqual(4, map.Insert(5, "3"));
            Assert.AreEqual(5, map.Insert(5, "4"));

            map.Remove(3);
            Assert.AreEqual(3, map.Insert(5, "5"));

            map.Remove(2);
            map.Remove(1);
            map.Remove(5);
            map.Remove(3);
            map.Remove(4);
            Assert.AreEqual(4, map.Insert(5, "6"));
            Assert.AreEqual(3, map.Insert(5, "7"));
            Assert.AreEqual(5, map.Insert(5, "8"));
            Assert.AreEqual(1, map.Insert(5, "9"));
            Assert.AreEqual(2, map.Insert(5, "10"));

            Assert.AreEqual(6, map.Insert(5, "11"));
        }
Beispiel #3
0
        private static void LargerTest()
        {
            var map = new FastMap <string>(1);

            const int Size = 100;

            for (int i = 0; i < Size; i++)
            {
                map.Insert(i, "one" + i);
                map.Insert(i, "two" + i);
            }

            for (int i = 0; i < Size; i++)
            {
                map.Insert(i, "three" + i);
            }

            Assert.AreEqual(Size * 3, map.Count);

            for (int i = 0; i < Size; i++)
            {
                var traverse = map.Find(i);

                bool hasOne   = false;
                bool hasTwo   = false;
                bool hasThree = false;
                for (int j = 0; j < 3; j++)
                {
                    Assert.IsTrue(traverse.Next(out var index));
                    if (map.Values[index] == "one" + i)
                    {
                        hasOne = true;
                    }
                    else if (map.Values[index] == "two" + i)
                    {
                        hasTwo = true;
                    }
                    else if (map.Values[index] == "three" + i)
                    {
                        hasThree = true;
                    }
                    else
                    {
                        Assert.Fail();
                    }
                }

                Assert.IsFalse(traverse.Next(out _));
                Assert.IsTrue(hasOne);
                Assert.IsTrue(hasTwo);
                Assert.IsTrue(hasThree);
            }

            for (int i = 0; i < Size; i++)
            {
                var traverse = map.Find(i);
                while (traverse.Next(out int index))
                {
                    if (map.Values[index] == "two" + i)
                    {
                        map.Remove(index);
                        break;
                    }
                }
            }

            Assert.AreEqual(Size * 2, map.Count);

            for (int i = 0; i < Size; i++)
            {
                var traverse = map.Find(i);

                bool hasOne   = false;
                bool hasThree = false;
                for (int j = 0; j < 2; j++)
                {
                    Assert.IsTrue(traverse.Next(out var index));
                    if (map.Values[index] == "one" + i)
                    {
                        hasOne = true;
                    }
                    else if (map.Values[index] == "three" + i)
                    {
                        hasThree = true;
                    }
                    else
                    {
                        Assert.Fail();
                    }
                }

                Assert.IsFalse(traverse.Next(out _));
                Assert.IsTrue(hasOne);
                Assert.IsTrue(hasThree);
            }

            for (int i = 0; i < Size; i++)
            {
                var traverse = map.Find(i);
                while (traverse.Next(out int index))
                {
                    if (map.Values[index] == "one" + i)
                    {
                        map.Remove(index);
                        break;
                    }
                }
            }

            Assert.AreEqual(Size, map.Count);

            for (int i = 0; i < Size; i++)
            {
                var traverse = map.Find(i);

                Assert.IsTrue(traverse.Next(out int index));
                Assert.AreEqual("three" + i, map.Values[index]);
                Assert.IsFalse(traverse.Next(out _));
            }

            for (int i = 0; i < Size; i++)
            {
                var traverse = map.Find(i);
                while (traverse.Next(out int index))
                {
                    if (map.Values[index] == "three" + i)
                    {
                        map.Remove(index);
                        break;
                    }
                }
            }

            Assert.IsTrue(map.IsEmpty);
        }
Beispiel #4
0
        private void ProcessPendingEntries()
        {
            foreach (var pKey in this.processQueue)
            {
                PooledElasticCircularBuffer <LEntry> leftWorking  = null;
                PooledElasticCircularBuffer <REntry> rightWorking = null;
                this.leftQueue.Lookup(pKey, out int index);
                leftWorking  = this.leftQueue.entries[index].value;
                rightWorking = this.rightQueue.entries[index].value;

                FastMap <ActiveEvent <TLeft> >  leftEdgeMapForPartition  = null;
                FastMap <ActiveEvent <TRight> > rightEdgeMapForPartition = null;
                this.partitionData.Lookup(pKey, out index);
                var partition = this.partitionData.entries[index].value;
                leftEdgeMapForPartition  = partition.leftEdgeMap;
                rightEdgeMapForPartition = partition.rightEdgeMap;

                while (true)
                {
                    bool hasLeftBatch  = leftWorking.TryPeekFirst(out LEntry leftEntry);
                    bool hasRightBatch = rightWorking.TryPeekFirst(out REntry rightEntry);
                    FastMap <ActiveEvent <TRight> > .FindTraverser rightEdges = default;
                    FastMap <ActiveEvent <TLeft> > .FindTraverser  leftEdges  = default;
                    if (hasLeftBatch && hasRightBatch)
                    {
                        UpdateNextLeftTime(partition, leftEntry.Sync);
                        UpdateNextRightTime(partition, rightEntry.Sync);

                        if (partition.nextLeftTime <= partition.nextRightTime)
                        {
                            if (leftEntry.Other != long.MinValue)
                            {
                                TKey key = leftEntry.Key;

                                var hash = leftEntry.Hash;
                                if (rightEdgeMapForPartition.Find(hash, ref rightEdges))
                                {
                                    while (rightEdges.Next(out int rightIndex))
                                    {
                                        if (this.keyComparer(key, rightEdgeMapForPartition.Values[rightIndex].Key))
                                        {
                                            OutputStartEdge(partition.nextLeftTime, ref key, ref leftEntry.Payload, ref rightEdgeMapForPartition.Values[rightIndex].Payload, hash);
                                        }
                                    }
                                }
                                if (!partition.isRightComplete)
                                {
                                    int newIndex = leftEdgeMapForPartition.Insert(hash);
                                    leftEdgeMapForPartition.Values[newIndex].Populate(ref key, ref leftEntry.Payload);
                                }

                                UpdateNextLeftTime(partition, leftEntry.Sync);
                            }
                            else
                            {
                                OutputPunctuation(leftEntry.Sync, ref leftEntry.Key, leftEntry.Hash);
                            }
                        }
                        else
                        {
                            if (rightEntry.Other != long.MinValue)
                            {
                                TKey key = rightEntry.Key;

                                var hash = rightEntry.Hash;
                                if (leftEdgeMapForPartition.Find(hash, ref leftEdges))
                                {
                                    while (leftEdges.Next(out int leftIndex))
                                    {
                                        if (this.keyComparer(key, leftEdgeMapForPartition.Values[leftIndex].Key))
                                        {
                                            OutputStartEdge(partition.nextRightTime, ref key, ref leftEdgeMapForPartition.Values[leftIndex].Payload, ref rightEntry.Payload, hash);
                                        }
                                    }
                                }
                                if (!partition.isLeftComplete)
                                {
                                    int newIndex = rightEdgeMapForPartition.Insert(hash);
                                    rightEdgeMapForPartition.Values[newIndex].Populate(ref key, ref rightEntry.Payload);
                                }

                                UpdateNextRightTime(partition, rightEntry.Sync);
                            }
                            else
                            {
                                OutputPunctuation(rightEntry.Sync, ref rightEntry.Key, rightEntry.Hash);
                            }
                        }
                    }
                    else if (hasLeftBatch)
                    {
                        UpdateNextLeftTime(partition, leftEntry.Sync);

                        if (leftEntry.Other != long.MinValue)
                        {
                            TKey key = leftEntry.Key;

                            var hash = leftEntry.Hash;
                            if (rightEdgeMapForPartition.Find(hash, ref rightEdges))
                            {
                                while (rightEdges.Next(out int rightIndex))
                                {
                                    if (this.keyComparer(key, rightEdgeMapForPartition.Values[rightIndex].Key))
                                    {
                                        OutputStartEdge(partition.nextLeftTime, ref key, ref leftEntry.Payload, ref rightEdgeMapForPartition.Values[rightIndex].Payload, hash);
                                    }
                                }
                            }
                            if (!partition.isRightComplete)
                            {
                                int newIndex = leftEdgeMapForPartition.Insert(hash);
                                leftEdgeMapForPartition.Values[newIndex].Populate(ref key, ref leftEntry.Payload);
                            }

                            UpdateNextLeftTime(partition, leftEntry.Sync);
                        }
                        else
                        {
                            OutputPunctuation(leftEntry.Sync, ref leftEntry.Key, leftEntry.Hash);
                            return;
                        }
                    }
                    else if (hasRightBatch)
                    {
                        UpdateNextRightTime(partition, rightEntry.Sync);

                        if (rightEntry.Other != long.MinValue)
                        {
                            TKey key = rightEntry.Key;

                            var hash = rightEntry.Hash;
                            if (leftEdgeMapForPartition.Find(hash, ref leftEdges))
                            {
                                while (leftEdges.Next(out int leftIndex))
                                {
                                    if (this.keyComparer(key, leftEdgeMapForPartition.Values[leftIndex].Key))
                                    {
                                        OutputStartEdge(partition.nextRightTime, ref key, ref leftEdgeMapForPartition.Values[leftIndex].Payload, ref rightEntry.Payload, hash);
                                    }
                                }
                            }
                            if (!partition.isLeftComplete)
                            {
                                int newIndex = rightEdgeMapForPartition.Insert(hash);
                                rightEdgeMapForPartition.Values[newIndex].Populate(ref key, ref rightEntry.Payload);
                            }

                            UpdateNextRightTime(partition, rightEntry.Sync);
                        }
                        else
                        {
                            OutputPunctuation(rightEntry.Sync, ref rightEntry.Key, rightEntry.Hash);
                        }
                    }
                    else
                    {
                        if (partition.nextLeftTime < this.lastLeftCTI)
                        {
                            UpdateNextLeftTime(partition, this.lastLeftCTI);
                        }
                        if (partition.nextRightTime < this.lastRightCTI)
                        {
                            UpdateNextRightTime(partition, this.lastRightCTI);
                        }
                        this.cleanKeys.Add(pKey);
                        break;
                    }
                }
            }

            if (this.emitCTI)
            {
                var earliest = Math.Min(this.lastLeftCTI, this.lastRightCTI);
                AddLowWatermarkToBatch(earliest);
                this.emitCTI = false;
                foreach (var p in this.cleanKeys)
                {
                    this.leftQueue.Lookup(p, out int index);
                    var l = this.leftQueue.entries[index];
                    var r = this.rightQueue.entries[index];
                    if (l.value.Count == 0 && r.value.Count == 0)
                    {
                        this.seenKeys.Remove(p);
                        l.value.Dispose();
                        this.leftQueue.Remove(p);
                        r.value.Dispose();
                        this.rightQueue.Remove(p);
                    }
                }

                this.cleanKeys.Clear();
            }

            this.processQueue.Clear();
        }