Exemplo n.º 1
0
        private void ProcessDispatches(
            ArrayDeque<NamedWindowConsumerLatch> dispatches,
            IDictionary<EPStatementAgentInstanceHandle, object> dispatchesPerStmt)
        {
            try {
                foreach (var latch in dispatches) {
                    foreach (var entry in latch.DispatchTo) {
                        var handle = entry.Key;
                        var perStmtObj = dispatchesPerStmt.Get(handle);
                        if (perStmtObj == null) {
                            dispatchesPerStmt.Put(handle, latch);
                        }
                        else if (perStmtObj is IList<NamedWindowConsumerLatch> windowConsumerLatches) {
                            windowConsumerLatches.Add(latch);
                        }
                        else {
                            // convert from object to list
                            var unitObj = (NamedWindowConsumerLatch) perStmtObj;
                            IList<NamedWindowConsumerLatch> list = new List<NamedWindowConsumerLatch>();
                            list.Add(unitObj);
                            list.Add(latch);
                            dispatchesPerStmt.Put(handle, list);
                        }
                    }
                }

                // Dispatch - with or without metrics reporting
                if (metricReportingService.IsMetricsReportingEnabled) {
                    foreach (var entry in dispatchesPerStmt) {
                        var handle = entry.Key;
                        var perStmtObj = entry.Value;

                        // dispatch of a single result to the statement
                        if (perStmtObj is NamedWindowConsumerLatch) {
                            var unit = (NamedWindowConsumerLatch) perStmtObj;
                            var newData = unit.DeltaData.NewData;
                            var oldData = unit.DeltaData.OldData;

                            if (handle.StatementHandle.MetricsHandle.IsEnabled) {
                                var performanceMetric = PerformanceMetricsHelper.Call(
                                    () => ProcessHandle(handle, unit.DispatchTo.Get(handle), newData, oldData));

                                metricReportingService.AccountTime(
                                    handle.StatementHandle.MetricsHandle, 
                                    performanceMetric, performanceMetric.NumInput);
                            }
                            else {
                                var entries = unit.DispatchTo;
                                var items = entries.Get(handle);
                                if (items != null) {
                                    ProcessHandle(handle, items, newData, oldData);
                                }
                            }

                            if (isPrioritized && handle.IsPreemptive) {
                                break;
                            }

                            continue;
                        }

                        // dispatch of multiple results to a the same statement, need to aggregate per consumer view
                        var deltaPerConsumer = GetDeltaPerConsumer(perStmtObj, handle);
                        if (handle.StatementHandle.MetricsHandle.IsEnabled) {
                            var performanceMetric = PerformanceMetricsHelper.Call(
                                () => ProcessHandleMultiple(handle, deltaPerConsumer));
                            metricReportingService.AccountTime(
                                handle.StatementHandle.MetricsHandle, 
                                performanceMetric, performanceMetric.NumInput);
                        }
                        else {
                            ProcessHandleMultiple(handle, deltaPerConsumer);
                        }

                        if (isPrioritized && handle.IsPreemptive) {
                            break;
                        }
                    }
                }
                else {
                    foreach (var entry in dispatchesPerStmt) {
                        var handle = entry.Key;
                        var perStmtObj = entry.Value;

                        // dispatch of a single result to the statement
                        if (perStmtObj is NamedWindowConsumerLatch) {
                            var unit = (NamedWindowConsumerLatch) perStmtObj;
                            var newData = unit.DeltaData.NewData;
                            var oldData = unit.DeltaData.OldData;

                            ProcessHandle(handle, unit.DispatchTo.Get(handle), newData, oldData);

                            if (isPrioritized && handle.IsPreemptive) {
                                break;
                            }

                            continue;
                        }

                        // dispatch of multiple results to a the same statement, need to aggregate per consumer view
                        var deltaPerConsumer = GetDeltaPerConsumer(perStmtObj, handle);
                        ProcessHandleMultiple(handle, deltaPerConsumer);

                        if (isPrioritized && handle.IsPreemptive) {
                            break;
                        }
                    }
                }
            }
            finally {
                foreach (var latch in dispatches) {
                    latch.Done();
                }

                dispatchesPerStmt.Clear();
                dispatches.Clear();
            }
        }
Exemplo n.º 2
0
        private void ProcessDispatches(
            ArrayDeque<NamedWindowConsumerLatch> dispatches,
            ArrayDeque<NamedWindowConsumerLatch> work,
            IDictionary<EPStatementAgentInstanceHandle, object> dispatchesPerStmt)
        {
            if (dispatches.Count == 1) {
                var latch = dispatches.First;
                try {
                    latch.Await();
                    var newData = latch.DeltaData.NewData;
                    var oldData = latch.DeltaData.OldData;

                    if (metricReportingService.IsMetricsReportingEnabled) {
                        foreach (var entry in latch.DispatchTo) {
                            var handle = entry.Key;
                            if (handle.StatementHandle.MetricsHandle.IsEnabled) {
                                var performanceMetric = PerformanceMetricsHelper.Call(
                                    () => ProcessHandle(handle, entry.Value, newData, oldData), 1);
                                metricReportingService.AccountTime(
                                    handle.StatementHandle.MetricsHandle,
                                    performanceMetric, performanceMetric.NumInput);
                            }
                            else {
                                ProcessHandle(handle, entry.Value, newData, oldData);
                            }

                            if (isPrioritized && handle.IsPreemptive) {
                                break;
                            }
                        }
                    }
                    else {
                        foreach (var entry in latch.DispatchTo) {
                            var handle = entry.Key;
                            ProcessHandle(handle, entry.Value, newData, oldData);

                            if (isPrioritized && handle.IsPreemptive) {
                                break;
                            }
                        }
                    }
                }
                finally {
                    latch.Done();
                }

                return;
            }

            // Multiple different-result dispatches to same or different statements are needed in two situations:
            // a) an event comes in, triggers two insert-into statements inserting into the same named window and the window produces 2 results
            // b) a time batch is grouped in the named window, and a timer fires for both groups at the same time producing more then one result
            // c) two on-merge/update/delete statements fire for the same arriving event each updating the named window
            // Most likely all dispatches go to different statements since most statements are not joins of
            // named windows that produce results at the same time. Therefore sort by statement handle.
            // We need to process in N-element chains to preserve dispatches that are next to each other for the same thread.
            while (!dispatches.IsEmpty()) {
                // the first latch always gets awaited
                var first = dispatches.RemoveFirst();
                first.Await();
                work.Add(first);

                // determine which further latches are in this chain and add these, skipping await for any latches in the chain

                dispatches.RemoveWhere(
                    (next, continuation) => {
                        var result = next.Earlier == null || work.Contains(next.Earlier);
                        continuation.Value = !result;
                        return result;
                    },
                    work.Add);

#if false
                var enumerator = dispatches.GetEnumerator();
                while (enumerator.MoveNext()) {
                    var next = enumerator.Current;
                    var earlier = next.Earlier;
                    if (earlier == null || work.Contains(earlier)) {
                        work.Add(next);
                        enumerator.Remove();
                    }
                    else {
                        break;
                    }
                }
#endif

                ProcessDispatches(work, dispatchesPerStmt);
            }
        }