コード例 #1
0
        protected override void ProcessLeftBatch(StreamMessage <TKey, TLeft> batch, out bool leftBatchDone, out bool leftBatchFree)
        {
            leftBatchDone = true;
            leftBatchFree = true;
            batch.iter    = 0;

            PooledElasticCircularBuffer <LEntry> queue = null;
            TPartitionKey previous = default;
            bool          first    = true;

            for (var i = 0; i < batch.Count; i++)
            {
                if ((batch.bitvector.col[i >> 6] & (1L << (i & 0x3f))) != 0 &&
                    (batch.vother.col[i] >= 0))
                {
                    continue;
                }

                if (batch.vother.col[i] == PartitionedStreamEvent.LowWatermarkOtherTime)
                {
                    bool timeAdvanced = this.lastLeftCTI != batch.vsync.col[i];
                    if (timeAdvanced && this.lastLeftCTI < this.lastRightCTI)
                    {
                        this.emitCTI = true;
                    }
                    this.lastLeftCTI = batch.vsync.col[i];
                    foreach (var p in this.seenKeys)
                    {
                        this.processQueue.Add(p);
                    }
                    continue;
                }

                var partitionKey = this.getPartitionKey(batch.key.col[i]);
                if (first || !partitionKey.Equals(previous))
                {
                    if (this.seenKeys.Add(partitionKey))
                    {
                        NewPartition(partitionKey);
                    }
                    this.leftQueue.Lookup(partitionKey, out int index);
                    queue = this.leftQueue.entries[index].value;
                    this.processQueue.Add(partitionKey);
                }
                var e = new LEntry
                {
                    Key     = batch.key.col[i],
                    Sync    = batch.vsync.col[i],
                    Other   = batch.vother.col[i],
                    Payload = batch.payload.col[i],
                    Hash    = batch.hash.col[i],
                };
                queue.Enqueue(ref e);
                first    = false;
                previous = partitionKey;
            }

            ProcessPendingEntries();
        }
コード例 #2
0
        public void Return(TKey partitionKey, PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > streamEvents)
        {
            if (!this.sorters.Lookup(partitionKey, out int index))
            {
                return;
            }
            var sorter = this.sorters.entries[index].value;

            sorter.Return(streamEvents);
        }
コード例 #3
0
            private static PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > Merge(
                PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > left,
                PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > right,
                PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > result,
                long timestamp)
            {
                while (true)
                {
                    if ((left.Count == 0) || (left.PeekFirst().SyncTime > timestamp))
                    {
                        while ((right.Count > 0) && (right.PeekFirst().SyncTime <= timestamp))
                        {
                            var tmp = right.Dequeue();
                            result.Enqueue(ref tmp);
                        }

                        return(result);
                    }

                    if ((right.Count == 0) || (right.PeekFirst().SyncTime > timestamp))
                    {
                        while ((left.Count > 0) && (left.PeekFirst().SyncTime <= timestamp))
                        {
                            var tmp = left.Dequeue();
                            result.Enqueue(ref tmp);
                        }
                        return(result);
                    }

                    if (left.PeekFirst().SyncTime < right.PeekFirst().SyncTime)
                    {
                        var tmp = left.Dequeue();
                        result.Enqueue(ref tmp);
                    }
                    else
                    {
                        var tmp = right.Dequeue();
                        result.Enqueue(ref tmp);
                    }
                }
            }
コード例 #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();
        }
コード例 #5
0
 public void Return(PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > streamEvents)
 {
     this.ecbPool.Return(streamEvents);
 }
コード例 #6
0
 public void Return(PooledElasticCircularBuffer <StreamEvent <TPayload> > streamEvents)
 {
     this.ecbPool.Return(streamEvents);
 }
コード例 #7
0
ファイル: PartitionedUnionPipe.cs プロジェクト: yorek/Trill
        private void ProcessPendingEntries()
        {
            foreach (var workingPartitionKey in this.processQueue)
            {
                PooledElasticCircularBuffer <Entry> leftWorking  = null;
                PooledElasticCircularBuffer <Entry> rightWorking = null;

                this.leftQueue.Lookup(workingPartitionKey, out int index);
                leftWorking = this.leftQueue.entries[index].value;
                this.rightQueue.Lookup(workingPartitionKey, out index);
                rightWorking = this.rightQueue.entries[index].value;

                while (true)
                {
                    bool hasLeftEntry  = leftWorking.TryPeekFirst(out Entry leftEntry);
                    bool hasRightEntry = rightWorking.TryPeekFirst(out Entry rightEntry);

                    if (hasLeftEntry && hasRightEntry)
                    {
                        this.nextLeftTime.Lookup(workingPartitionKey, out int workingIndex);
                        this.nextLeftTime.entries[workingIndex].value = leftEntry.Sync;
                        this.nextRightTime.Lookup(workingPartitionKey, out workingIndex);
                        this.nextRightTime.entries[workingIndex].value = rightEntry.Sync;

                        switch (leftEntry.Sync.CompareTo(rightEntry.Sync))
                        {
                        case -1:
                            // Output the left tuple
                            OutputCurrentTuple(leftEntry);
                            leftWorking.TryDequeue(out leftEntry);
                            break;

                        case 0:
                            // Output both tuples
                            OutputCurrentTuple(leftEntry);
                            OutputCurrentTuple(rightEntry);
                            leftWorking.TryDequeue(out leftEntry);
                            rightWorking.TryDequeue(out rightEntry);
                            break;

                        case 1:
                            // Output the right tuple
                            OutputCurrentTuple(rightEntry);
                            rightWorking.TryDequeue(out rightEntry);
                            break;

                        default: throw new InvalidOperationException();
                        }
                    }
                    else if (hasLeftEntry)
                    {
                        this.nextLeftTime.Lookup(workingPartitionKey, out int workingIndex);
                        this.nextLeftTime.entries[workingIndex].value = leftEntry.Sync;

                        var lastRightTime = !this.nextRightTime.Lookup(workingPartitionKey, out workingIndex)
                            ? long.MinValue
                            : this.nextRightTime.entries[workingIndex].value;

                        if (leftEntry.Sync <= Math.Max(lastRightTime, this.lastRightCTI))
                        {
                            // Output the left tuple
                            OutputCurrentTuple(leftEntry);
                            leftWorking.TryDequeue(out leftEntry);
                        }
                        else
                        {
                            // Need to wait for the other input
                            break;
                        }
                    }
                    else if (hasRightEntry)
                    {
                        this.nextRightTime.Lookup(workingPartitionKey, out int workingIndex);
                        this.nextRightTime.entries[workingIndex].value = rightEntry.Sync;

                        var lastLeftTime = !this.nextLeftTime.Lookup(workingPartitionKey, out workingIndex)
                            ? long.MinValue
                            : this.nextLeftTime.entries[workingIndex].value;

                        if (rightEntry.Sync <= Math.Max(lastLeftTime, this.lastLeftCTI))
                        {
                            // Output the right tuple
                            OutputCurrentTuple(rightEntry);
                            rightWorking.TryDequeue(out rightEntry);
                        }
                        else
                        {
                            // Need to wait for the other input
                            break;
                        }
                    }
                    else
                    {
                        this.cleanKeys.Add(workingPartitionKey);
                        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();
        }