Пример #1
0
        public override unsafe void OnNext(StreamMessage <TKey, TInput> batch)
        {
            this.batch.iter = batch.iter;

            var count      = batch.Count;
            var colkey     = batch.key.col;
            var colpayload = batch.payload.col;

            fixed(long *col_vsync = batch.vsync.col)
            fixed(long *col_vother = batch.vother.col)
            fixed(int *col_hash    = batch.hash.col)
            fixed(long *col_bv     = batch.bitvector.col)
            {
                for (int i = 0; i < count; i++)
                {
                    if ((col_bv[i >> 6] & (1L << (i & 0x3f))) != 0)
                    {
                        if (col_vother[i] == PartitionedStreamEvent.LowWatermarkOtherTime)
                        {
                            OnLowWatermark(col_vsync[i]);

                            int c = this.batch.Count;
                            this.batch.vsync.col[c]           = col_vsync[i];
                            this.batch.vother.col[c]          = PartitionedStreamEvent.LowWatermarkOtherTime;
                            this.batch.key.col[c]             = default;
                            this.batch.hash.col[c]            = 0;
                            this.batch.bitvector.col[c >> 6] |= 1L << (c & 0x3f);
                            this.batch.Count++;
                            if (this.batch.Count == Config.DataBatchSize)
                            {
                                FlushContents();
                            }
                        }
                        else if (col_vother[i] == PartitionedStreamEvent.PunctuationOtherTime)
                        {
                            // We have found a row that corresponds to punctuation
                            var            p = this.getPartitionKey(colkey[i]);
                            PartitionEntry partitionEntry;
                            if (!this.partitionData.Lookup(p, out int partitionIndex))
                            {
                                this.partitionData.Insert(p, partitionEntry = new PartitionEntry {
                                    lastSyncTime = col_vsync[i], ecq = new CircularBuffer <EcqState>(this.hopsPerDuration)
                                });
                            }
                            else
                            {
                                partitionEntry = this.partitionData.entries[partitionIndex].value;
                            }
                            OnPunctuation(partitionEntry, col_vsync[i]);

                            int c = this.batch.Count;
                            this.batch.vsync.col[c]           = col_vsync[i];
                            this.batch.vother.col[c]          = long.MinValue;
                            this.batch.key.col[c]             = colkey[i];
                            this.batch.hash.col[c]            = this.keyComparerGetHashCode(colkey[i]);
                            this.batch.bitvector.col[c >> 6] |= 1L << (c & 0x3f);
                            this.batch.Count++;
                            if (this.batch.Count == Config.DataBatchSize)
                            {
                                FlushContents();
                            }
                        }
                        continue;
                    }

                    var syncTime  = col_vsync[i];
                    var partition = this.getPartitionKey(colkey[i]);
                    HeldState <TState> heldState;
                    PartitionEntry     entry;

                    // Handle time moving forward
                    if (!this.partitionData.Lookup(partition, out int pIndex))
                    {
                        this.partitionData.Insert(partition, entry = new PartitionEntry {
                            lastSyncTime = syncTime, ecq = new CircularBuffer <EcqState>(this.hopsPerDuration)
                        });
                    }
                    else if (syncTime > (entry = this.partitionData.entries[pIndex].value).lastSyncTime)
                    {
                        AdvanceTime(entry, syncTime);
                    }

                    // Need to retrieve the key from the dictionary
                    if (!this.aggregateByKey.Lookup(colkey[i], col_hash[i], out int aggindex))
                    {
                        // New group. Create new state
                        heldState = new HeldState <TState> {
                            state = this.initialState(), timestamp = syncTime
                        };
                        entry.heldAggregates.Add(this.aggregateByKey.Insert(colkey[i], heldState, col_hash[i]));

                        // No output because initial state is empty
                    }
                    else if (entry.heldAggregates.Add(aggindex))
                    {
                        // First time group is active for this time
                        heldState = this.aggregateByKey.entries[aggindex].value;
                        if (syncTime > heldState.timestamp)
                        {
                            if (heldState.active > 0)
                            {
                                // Output end edge
                                int c = this.batch.Count;
                                this.batch.vsync.col[c]   = syncTime;
                                this.batch.vother.col[c]  = heldState.timestamp;
                                this.batch.payload.col[c] = this.computeResult(heldState.state);
                                this.batch.key.col[c]     = colkey[i];
                                this.batch.hash.col[c]    = this.keyComparerGetHashCode(colkey[i]);
                                this.batch.Count++;
                                if (this.batch.Count == Config.DataBatchSize)
                                {
                                    this.batch.iter = batch.iter;
                                    FlushContents();
                                    this.batch.iter = batch.iter;
                                }
                            }
                            heldState.timestamp = syncTime;
                        }
                    }
                    else
                    {
                        // read new currentState from _heldAgg index
                        heldState = this.aggregateByKey.entries[aggindex].value;
                    }

                    if (col_vsync[i] < col_vother[i]) // insert event
                    {
                        heldState.state = this.accumulate(heldState.state, col_vsync[i], colpayload[i]);
                        heldState.active++;

                        // Update ECQ
                        if (col_vother[i] < StreamEvent.InfinitySyncTime)
                        {
                            EcqState state;
                            StateAndActive <TState> newState;
                            int index;
                            if (entry.ecq.Count > 0)
                            {
                                state = entry.ecq.PeekLast();
                                if (state.timestamp != col_vother[i])
                                {
                                    state = new EcqState {
                                        timestamp = col_vother[i]
                                    };
                                    this.ecqEntryPool.Get(out state.states);

                                    newState = new StateAndActive <TState> {
                                        state = this.initialState()
                                    };

                                    state.states.Lookup(colkey[i], col_hash[i], out index);
                                    state.states.Insert(ref index, colkey[i], newState);
                                    entry.ecq.Enqueue(ref state);
                                }
                                else
                                {
                                    if (!state.states.Lookup(colkey[i], col_hash[i], out index))
                                    {
                                        newState = new StateAndActive <TState> {
                                            state = this.initialState()
                                        };
                                        state.states.Insert(ref index, colkey[i], newState);
                                    }
                                    else
                                    {
                                        newState = state.states.entries[index].value;
                                    }
                                }
                            }
                            else
                            {
                                state = new EcqState {
                                    timestamp = col_vother[i]
                                };
                                this.ecqEntryPool.Get(out state.states);

                                newState = new StateAndActive <TState> {
                                    state = this.initialState()
                                };

                                state.states.Lookup(colkey[i], col_hash[i], out index);
                                state.states.Insert(ref index, colkey[i], newState);
                                entry.ecq.Enqueue(ref state);
                            }

                            newState.state = this.accumulate(newState.state, col_vsync[i], colpayload[i]);
                            newState.active++;
                        }
                    }
                    else // is a retraction
                    {
                        heldState.state = this.deaccumulate(heldState.state, col_vsync[i], colpayload[i]);
                        heldState.active--;
                    }
                }
            }

            batch.Release();
            batch.Return();
        }
Пример #2
0
        public override unsafe void OnNext(StreamMessage <TKey, TInput> batch)
        {
            this.batch.iter = batch.iter;

            var count      = batch.Count;
            var colkey     = batch.key.col;
            var colpayload = batch.payload.col;

            fixed(long *col_vsync = batch.vsync.col)
            fixed(long *col_vother = batch.vother.col)
            fixed(int *col_hash    = batch.hash.col)
            fixed(long *col_bv     = batch.bitvector.col)
            {
                for (int i = 0; i < count; i++)
                {
                    if ((col_bv[i >> 6] & (1L << (i & 0x3f))) != 0)
                    {
                        if (col_vother[i] == StreamEvent.PunctuationOtherTime)
                        {
                            // We have found a row that corresponds to punctuation
                            OnPunctuation(col_vsync[i]);

                            int c = this.batch.Count;
                            this.batch.vsync.col[c]           = col_vsync[i];
                            this.batch.vother.col[c]          = StreamEvent.PunctuationOtherTime;
                            this.batch.key.col[c]             = default;
                            this.batch.hash.col[c]            = 0;
                            this.batch.bitvector.col[c >> 6] |= 1L << (c & 0x3f);
                            this.batch.Count++;
                            if (this.batch.Count == Config.DataBatchSize)
                            {
                                FlushContents();
                            }
                        }
                        continue;
                    }

                    var syncTime = col_vsync[i];

                    // Handle time moving forward
                    if (syncTime > this.lastSyncTime)
                    {
                        AdvanceTime(syncTime);
                    }

                    // Need to retrieve the key from the dictionary
                    HeldState <TState> heldState;
                    if (!this.aggregateByKey.Lookup(colkey[i], col_hash[i], out int aggindex))
                    {
                        // New group. Create new state
                        heldState = new HeldState <TState> {
                            state = this.initialState(), timestamp = syncTime
                        };
                        this.heldAggregates.Add(this.aggregateByKey.Insert(colkey[i], heldState, col_hash[i]));

                        // No output because initial state is empty
                    }
                    else
                    {
                        // Update instance of key in case consumer tracks lifetime of the key object.
                        // Otherwise it may live past the Window lifetime.
                        this.aggregateByKey.entries[aggindex].key = colkey[i];

                        if (this.heldAggregates.Add(aggindex))
                        {
                            // First time group is active for this time
                            heldState = this.aggregateByKey.entries[aggindex].value;
                            if (syncTime > heldState.timestamp)
                            {
                                if (heldState.active > 0)
                                {
                                    // Output end edge
                                    int c = this.batch.Count;
                                    this.batch.vsync.col[c]   = syncTime;
                                    this.batch.vother.col[c]  = heldState.timestamp;
                                    this.batch.payload.col[c] = this.computeResult(heldState.state);
                                    this.batch.key.col[c]     = colkey[i];
                                    this.batch.hash.col[c]    = this.keyComparerGetHashCode(colkey[i]);
                                    this.batch.Count++;
                                    if (this.batch.Count == Config.DataBatchSize)
                                    {
                                        FlushContents();
                                    }
                                }
                                heldState.timestamp = syncTime;
                            }
                        }
                        else
                        {
                            // read new currentState from _heldAgg index
                            heldState = this.aggregateByKey.entries[aggindex].value;
                        }
                    }

                    if (col_vsync[i] < col_vother[i]) // insert event
                    {
                        heldState.state = this.accumulate(heldState.state, col_vsync[i], colpayload[i]);
                        heldState.active++;

                        // Update ECQ
                        if (col_vother[i] < StreamEvent.InfinitySyncTime)
                        {
                            EcqState ecqState;
                            StateAndActive <TState> newState;
                            int index;
                            if (this.ecq.Count > 0)
                            {
                                ecqState = this.ecq.PeekLast();
                                if (ecqState.timestamp != col_vother[i])
                                {
                                    ecqState = new EcqState {
                                        timestamp = col_vother[i]
                                    };
                                    this.ecqEntryPool.Get(out ecqState.states);

                                    newState = new StateAndActive <TState> {
                                        state = this.initialState()
                                    };

                                    ecqState.states.Lookup(colkey[i], col_hash[i], out index);
                                    ecqState.states.Insert(ref index, colkey[i], newState);
                                    this.ecq.Enqueue(ref ecqState);
                                }
                                else
                                {
                                    if (!ecqState.states.Lookup(colkey[i], col_hash[i], out index))
                                    {
                                        newState = new StateAndActive <TState> {
                                            state = this.initialState()
                                        };
                                        ecqState.states.Insert(ref index, colkey[i], newState);
                                    }
                                    else
                                    {
                                        newState = ecqState.states.entries[index].value;
                                    }
                                }
                            }
                            else
                            {
                                ecqState = new EcqState {
                                    timestamp = col_vother[i]
                                };
                                this.ecqEntryPool.Get(out ecqState.states);
                                newState = new StateAndActive <TState> {
                                    state = this.initialState()
                                };

                                ecqState.states.Lookup(colkey[i], col_hash[i], out index);
                                ecqState.states.Insert(ref index, colkey[i], newState);
                                this.ecq.Enqueue(ref ecqState);
                            }

                            newState.state = this.accumulate(newState.state, col_vsync[i], colpayload[i]);
                            newState.active++;
                        }
                    }
                    else // is a retraction
                    {
                        heldState.state = this.deaccumulate(heldState.state, col_vsync[i], colpayload[i]);
                        heldState.active--;
                    }
                }
            }

            batch.Release();
            batch.Return();
        }