/// <summary> /// This method updates child views and clears the batch of events. /// </summary> protected void SendBatch() { // If there are child views and the batch was filled, fireStatementStopped update method if (child != null) { // Convert to object arrays EventBean[] newData = null; EventBean[] oldData = null; if (!currentBatch.IsEmpty()) { newData = currentBatch.ToArray(); } if (lastBatch != null && !lastBatch.IsEmpty()) { oldData = lastBatch.ToArray(); } // update view buffer to serve expressions require access to events held viewUpdatedCollection?.Update(newData, oldData); // Post new data (current batch) and old data (prior batch) if (newData != null || oldData != null) { agentInstanceContext.InstrumentationProvider.QViewIndicate( lengthBatchViewFactory, newData, oldData); child.Update(newData, oldData); agentInstanceContext.InstrumentationProvider.AViewIndicate(); } } lastBatch = currentBatch; currentBatch = new ArrayDeque<EventBean>(); }
/// <summary>Adds event to the time window for the specified timestamp. </summary> /// <param name="timestamp">the time slot for the event</param> /// <param name="bean">event to add</param> public void Add(long timestamp, EventBean bean) { // Empty window if (_window.IsEmpty()) { var pairX = new TimeWindowPair(timestamp, bean); _window.Add(pairX); if (_reverseIndex != null) { _reverseIndex[bean] = pairX; } _size = 1; return; } TimeWindowPair lastPair = _window.Last; // Windows last timestamp matches the one supplied if (lastPair.Timestamp == timestamp) { if (lastPair.EventHolder is IList <EventBean> ) { var list = (IList <EventBean>)lastPair.EventHolder; list.Add(bean); } else if (lastPair.EventHolder == null) { lastPair.EventHolder = bean; } else { var existing = (EventBean)lastPair.EventHolder; IList <EventBean> list = new List <EventBean>(4); list.Add(existing); list.Add(bean); lastPair.EventHolder = list; } if (_reverseIndex != null) { _reverseIndex[bean] = lastPair; } _size++; return; } // Append to window var pair = new TimeWindowPair(timestamp, bean); if (_reverseIndex != null) { _reverseIndex[bean] = pair; } _window.Add(pair); _size++; }
/// <summary> /// This method updates child views and clears the batch of events. /// We schedule a new callback at this time if there were events in the batch. /// </summary> public void SendBatch() { _isCallbackScheduled = false; // If there are child views and the batch was filled, fireStatementStopped update method if (HasViews) { // Convert to object arrays EventBean[] newData = null; EventBean[] oldData = null; if (!_currentBatch.IsEmpty()) { newData = _currentBatch.ToArray(); } if ((_lastBatch != null) && (!_lastBatch.IsEmpty())) { oldData = _lastBatch.ToArray(); } // Post new data (current batch) and old data (prior batch) if (_viewUpdatedCollection != null) { _viewUpdatedCollection.Update(newData, oldData); } if ((newData != null) || (oldData != null) || _isForceOutput) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().QViewIndicate(this, _timeBatchViewFactory.ViewName, newData, oldData); } UpdateChildren(newData, oldData); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().AViewIndicate(); } } } // Only if forceOutput is enabled or // there have been any events in this or the last interval do we schedule a callback, // such as to not waste resources when no events arrive. if ((!_currentBatch.IsEmpty()) || ((_lastBatch != null) && (!_lastBatch.IsEmpty())) || _isForceOutput) { ScheduleCallback(); _isCallbackScheduled = true; } _lastBatch = _currentBatch; _currentBatch = new ArrayDeque <EventBean>(); }
public override void Update(EventBean[] newData, EventBean[] oldData) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().QViewProcessIRStream(this, _timeBatchViewFactory.ViewName, newData, oldData); } // we don't care about removed data from a prior view if ((newData == null) || (newData.Length == 0)) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().AViewProcessIRStream(); } return; } // If we have an empty window about to be filled for the first time, schedule a callback if (_currentBatch.IsEmpty()) { if (_currentReferencePoint == null) { _currentReferencePoint = _initialReferencePoint; if (_currentReferencePoint == null) { _currentReferencePoint = _agentInstanceContext.StatementContext.SchedulingService.Time; } } // Schedule the next callback if there is none currently scheduled if (!_isCallbackScheduled) { ScheduleCallback(); _isCallbackScheduled = true; } } // add data points to the timeWindow foreach (EventBean newEvent in newData) { _currentBatch.Add(newEvent); } // We do not update child views, since we batch the events. if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().AViewProcessIRStream(); } }
/// <summary> /// Flatten the vector of arrays to an array. Return null if an empty vector was passed, else /// return an array containing all the events. /// </summary> /// <param name="eventVector">vector</param> /// <returns>array with all events</returns> public static EventBean[] Flatten(ArrayDeque<EventBean[]> eventVector) { if (eventVector.IsEmpty()) { return null; } if (eventVector.Count == 1) { return eventVector.First; } var totalElements = 0; foreach (var arr in eventVector) { if (arr != null) { totalElements += arr.Length; } } if (totalElements == 0) { return null; } var result = new EventBean[totalElements]; var destPos = 0; foreach (var arr in eventVector) { if (arr != null) { Array.Copy(arr, 0, result, destPos, arr.Length); destPos += arr.Length; } } return result; }
public static ICollection<EventBean> GetDistinctByProp( ArrayDeque<EventBean> events, EventPropertyValueGetter getter) { if (events == null || events.IsEmpty()) { return new EventBean[0]; } if (events.Count < 2) { return events; } var map = new LinkedHashMap<object, EventBean>(); if (events.First is NaturalEventBean) { foreach (var theEvent in events) { var inner = ((NaturalEventBean) theEvent).OptionalSynthetic; var key = getter.Get(inner); map[key] = inner; } } else { foreach (var theEvent in events) { var key = getter.Get(theEvent); map[key] = theEvent; } } return map.Values.ToArray(); }
public static EventBean[] GetNewDataNonRemoved( EventBean[] newData, ISet<EventBean> removedEvents) { var filter = false; for (var i = 0; i < newData.Length; i++) { if (removedEvents.Contains(newData[i])) { filter = true; } } if (!filter) { return newData; } if (newData.Length == 1) { return null; } var events = new ArrayDeque<EventBean>(newData.Length - 1); for (var i = 0; i < newData.Length; i++) { if (!removedEvents.Contains(newData[i])) { events.Add(newData[i]); } } if (events.IsEmpty()) { return null; } return events.ToArray(); }
public static EventBean[] GetNewDataNonRemoved( EventBean[] newData, ISet<EventBean> removedEvents, EventBean[][] newEventsPerView) { if (newData == null || newData.Length == 0) { return null; } if (newData.Length == 1) { if (removedEvents.Contains(newData[0])) { return null; } var pass = FindEvent(newData[0], newEventsPerView); return pass ? newData : null; } var events = new ArrayDeque<EventBean>(newData.Length - 1); for (var i = 0; i < newData.Length; i++) { if (!removedEvents.Contains(newData[i])) { var pass = FindEvent(newData[i], newEventsPerView); if (pass) { events.Add(newData[i]); } } } if (events.IsEmpty()) { return null; } return events.ToArray(); }
/// <summary> /// NOTE: Code-generation-invoked method, method name and parameter order matters /// </summary> /// <param name="arrays">values</param> /// <returns>array</returns> public static EventBean[][] ToArrayEventsArray(ArrayDeque<EventBean[]> arrays) { if (arrays.IsEmpty()) { return EVENTBEANARRAYARRAY_EMPTY; } return arrays.ToArray(); }
/// <summary>Add to the current node building up the tree path information.</summary> /// <param name="remainingParameters">any remaining parameters</param> /// <param name="filterCallback">the filter callback</param> /// <param name="currentNode">is the node to add to</param> /// <param name="lockFactory">the lock factory</param> private static void AddToNode( ArrayDeque<FilterValueSetParam> remainingParameters, FilterHandle filterCallback, FilterHandleSetNode currentNode, FilterServiceGranularLockFactory lockFactory) { // If no parameters are specified, add to current node, and done if (remainingParameters.IsEmpty()) { using (currentNode.NodeRWLock.WriteLock.Acquire()) { currentNode.Add(filterCallback); } return; } // Need to find an existing index that matches one of the filter parameters Pair<FilterValueSetParam, FilterParamIndexBase> pair; using (currentNode.NodeRWLock.ReadLock.Acquire()) { pair = IndexHelper.FindIndex(remainingParameters, currentNode.Indizes); // Found an index matching a filter parameter if (pair != null) { remainingParameters.Remove(pair.First); var filterForValue = pair.First.FilterForValue; var index = pair.Second; AddToIndex(remainingParameters, filterCallback, index, filterForValue, lockFactory); return; } } // An index for any of the filter parameters was not found, create one using (currentNode.NodeRWLock.WriteLock.Acquire()) { pair = IndexHelper.FindIndex(remainingParameters, currentNode.Indizes); // Attempt to find an index again this time under a write lock if (pair != null) { remainingParameters.Remove(pair.First); var filterForValue = pair.First.FilterForValue; var indexInner = pair.Second; AddToIndex(remainingParameters, filterCallback, indexInner, filterForValue, lockFactory); return; } // No index found that matches any parameters, create a new one // Pick the next parameter for an index var parameterPickedForIndex = remainingParameters.RemoveFirst(); var index = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator); currentNode.Add(index); AddToIndex(remainingParameters, filterCallback, index, parameterPickedForIndex.FilterForValue, lockFactory); } }
public override void Update( EventBean[] newData, EventBean[] oldData) { AgentInstanceContext agentInstanceContext = agentInstanceViewFactoryContext.AgentInstanceContext; agentInstanceContext.AuditProvider.View(newData, oldData, agentInstanceContext, factory); agentInstanceContext.InstrumentationProvider.QViewProcessIRStream(factory, newData, oldData); long timestamp = -1; // add data points to the window // we don't care about removed data from a prior view if (newData != null) { for (int i = 0; i < newData.Length; i++) { timestamp = GetLongValue(newData[i]); timeWindow.Add(timestamp, newData[i]); } } // Remove from the window any events that have an older timestamp then the last event's timestamp ArrayDeque<EventBean> expired = null; if (timestamp != -1) { expired = timeWindow.ExpireEvents( timestamp - timePeriodProvide.DeltaSubtract(timestamp, null, true, agentInstanceViewFactoryContext) + 1); } EventBean[] oldDataUpdate = null; if ((expired != null) && (!expired.IsEmpty())) { oldDataUpdate = expired.ToArray(); } if ((oldData != null) && (agentInstanceViewFactoryContext.IsRemoveStream)) { foreach (EventBean anOldData in oldData) { timeWindow.Remove(anOldData); } if (oldDataUpdate == null) { oldDataUpdate = oldData; } else { oldDataUpdate = CollectionUtil.AddArrayWithSetSemantics(oldData, oldDataUpdate); } } viewUpdatedCollection?.Update(newData, oldDataUpdate); // If there are child views, fireStatementStopped update method if (Child != null) { agentInstanceContext.InstrumentationProvider.QViewIndicate(factory, newData, oldDataUpdate); Child.Update(newData, oldDataUpdate); agentInstanceContext.InstrumentationProvider.AViewIndicate(); } agentInstanceContext.InstrumentationProvider.AViewProcessIRStream(); }
/// <summary> /// Flatten the vector of arrays to an array. Return null if an empty vector was passed, else /// return an array containing all the events. /// </summary> /// <param name="eventVector">vector</param> /// <returns>array with all events</returns> public static UniformPair<EventBean[]> FlattenList(ArrayDeque<UniformPair<EventBean[]>> eventVector) { if (eventVector.IsEmpty()) { return null; } if (eventVector.Count == 1) { return eventVector.First; } var totalNew = 0; var totalOld = 0; foreach (var pair in eventVector) { if (pair != null) { if (pair.First != null) { totalNew += pair.First.Length; } if (pair.Second != null) { totalOld += pair.Second.Length; } } } if (totalNew + totalOld == 0) { return null; } EventBean[] resultNew = null; if (totalNew > 0) { resultNew = new EventBean[totalNew]; } EventBean[] resultOld = null; if (totalOld > 0) { resultOld = new EventBean[totalOld]; } var destPosNew = 0; var destPosOld = 0; foreach (var pair in eventVector) { if (pair != null) { if (pair.First != null) { Array.Copy(pair.First, 0, resultNew, destPosNew, pair.First.Length); destPosNew += pair.First.Length; } if (pair.Second != null) { Array.Copy(pair.Second, 0, resultOld, destPosOld, pair.Second.Length); destPosOld += pair.Second.Length; } } } return new UniformPair<EventBean[]>(resultNew, resultOld); }
private void NextToken() { tokens.RemoveFirst(); // Pop(); if (tokens.IsEmpty()) { lookahead = new Token(TokenType.END, ""); } else { lookahead = tokens.First; } }
public EventBean[] GetProperty(EventBean theEvent, ExprEvaluatorContext exprEvaluatorContext) { var resultEvents = new ArrayDeque<EventBean>(); _eventsPerStream[0] = theEvent; PopulateEvents(theEvent, 0, resultEvents, exprEvaluatorContext); if (resultEvents.IsEmpty()) { return null; } return resultEvents.ToArray(); }
/// <summary>Returns true if the window is empty, or false if not empty. </summary> /// <returns>true if empty</returns> public bool IsEmpty() { if (LastBatch != null) { if (LastBatch.IsNotEmpty()) { return(false); } } return(CurrentBatch.IsEmpty()); }
public PropertyTokenParser( ArrayDeque<Token> tokens, bool rootedDynamic) { if (tokens.IsEmpty()) { throw new PropertyParseNodepException("Empty property name"); } lookahead = tokens.First; this.tokens = tokens; dynamic = rootedDynamic; }
/// <summary> /// This method updates child views and clears the batch of events. /// We schedule a new callback at this time if there were events in the batch. /// </summary> private void SendBatch() { _isCallbackScheduled = false; // If there are child views and the batch was filled, fireStatementStopped update method if (Child != null) { // Convert to object arrays EventBean[] newData = null; EventBean[] oldData = null; if (!_currentBatch.IsEmpty()) { newData = _currentBatch.ToArray(); } if (_lastBatch != null && !_lastBatch.IsEmpty()) { oldData = _lastBatch.ToArray(); } // Post new data (current batch) and old data (prior batch) _viewUpdatedCollection?.Update(newData, oldData); if (newData != null || oldData != null || _factory.isForceUpdate) { _agentInstanceContext.InstrumentationProvider.QViewIndicate(_factory, newData, oldData); Child.Update(newData, oldData); _agentInstanceContext.InstrumentationProvider.AViewIndicate(); } } // Only if forceOutput is enabled or // there have been any events in this or the last interval do we schedule a callback, // such as to not waste resources when no events arrive. if (!_currentBatch.IsEmpty() || _lastBatch != null && !_lastBatch.IsEmpty() || _factory.isForceUpdate) { ScheduleCallback(); _isCallbackScheduled = true; } _lastBatch = _currentBatch; _currentBatch = new ArrayDeque<EventBean>(); }
/// <summary>Returns the accumulative events for the input event. </summary> /// <param name="theEvent">is the input event</param> /// <param name="exprEvaluatorContext">expression evaluation context</param> /// <returns>events per stream for each row</returns> public ArrayDeque <EventBean[]> GetAccumulative(EventBean theEvent, ExprEvaluatorContext exprEvaluatorContext) { var resultEvents = new ArrayDeque <EventBean[]>(); var eventsPerStream = new EventBean[_levels]; eventsPerStream[0] = theEvent; PopulateEvents(eventsPerStream, theEvent, 0, resultEvents, exprEvaluatorContext); if (resultEvents.IsEmpty()) { return(null); } return(resultEvents); }
public override void Update( EventBean[] newData, EventBean[] oldData) { _agentInstanceContext.AuditProvider.View(newData, oldData, _agentInstanceContext, _factory); _agentInstanceContext.InstrumentationProvider.QViewProcessIRStream(_factory, newData, oldData); // we don't care about removed data from a prior view if (newData == null || newData.Length == 0) { _agentInstanceContext.InstrumentationProvider.AViewProcessIRStream(); return; } // If we have an empty window about to be filled for the first time, schedule a callback if (_currentBatch.IsEmpty()) { if (_currentReferencePoint == null) { _currentReferencePoint = _factory.optionalReferencePoint; if (_currentReferencePoint == null) { _currentReferencePoint = _agentInstanceContext.StatementContext.SchedulingService.Time; } } // Schedule the next callback if there is none currently scheduled if (!_isCallbackScheduled) { ScheduleCallback(); _isCallbackScheduled = true; } } // add data points to the timeWindow foreach (var newEvent in newData) { _currentBatch.Add(newEvent); } // We do not update child views, since we batch the events. _agentInstanceContext.InstrumentationProvider.AViewProcessIRStream(); }
public void DequeueBackTest() { for (int i = 0; i < 3; i++) { deque.Enqueue(i); } for (int i = 0; i < 3; i++) { deque.EnqueueFront(i); } Assert.AreEqual(2, deque.DequeueBack()); Assert.AreEqual("{2, 1, 0, 0, 1}", deque.ToString()); for (int i = 0; i < 5; i++) { deque.DequeueBack(); } Assert.AreEqual(true, deque.IsEmpty()); }
/// <summary>Returns true if the window is empty, or false if not empty. </summary> /// <returns>true if empty</returns> public bool IsEmpty() { return(_events.IsEmpty()); }
// Called based on schedule evaluation registered when a variable changes (new data is null). // Called when new data arrives. private void Expire( EventBean[] newData, EventBean[] oldData) { OneEventCollection expired = null; if (oldData != null) { expired = new OneEventCollection(); expired.Add(oldData); } var expiredCount = 0; if (!window.IsEmpty()) { var newest = window.Last; while (true) { var first = window.First; var pass = CheckEvent(first, newest, expiredCount); if (!pass) { if (expired == null) { expired = new OneEventCollection(); } var removed = window.RemoveFirst().TheEvent; expired.Add(removed); if (aggregationService != null) { removedEvents[0] = removed; aggregationService.ApplyLeave(removedEvents, null, agentInstanceContext); } expiredCount++; InternalHandleExpired(first); } else { break; } if (window.IsEmpty()) { aggregationService?.ClearResults(agentInstanceContext); break; } } } // Check for any events that get pushed out of the window EventBean[] expiredArr = null; if (expired != null) { expiredArr = expired.ToArray(); } // update event buffer for access by expressions, if any viewUpdatedCollection?.Update(newData, expiredArr); // If there are child views, call update method if (child != null) { agentInstanceContext.InstrumentationProvider.QViewIndicate(factory, newData, expiredArr); child.Update(newData, expiredArr); agentInstanceContext.InstrumentationProvider.AViewIndicate(); } }
/// <summary> /// Add to the current node building up the tree path information. /// </summary> /// <param name="remainingParameters">The remaining parameters.</param> /// <param name="filterCallback">The filter callback.</param> /// <param name="currentNode">is the node to add to</param> /// <param name="treePathInfo">is filled with information about which indizes were chosen to add the filter to</param> /// <param name="lockFactory">The lock factory.</param> private static void AddToNode( ArrayDeque <FilterValueSetParam> remainingParameters, FilterHandle filterCallback, FilterHandleSetNode currentNode, ArrayDeque <EventTypeIndexBuilderIndexLookupablePair> treePathInfo, FilterServiceGranularLockFactory lockFactory) { if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".addToNode (" + Thread.CurrentThread.ManagedThreadId + ") Adding filterCallback, node=" + currentNode + " remainingParameters=" + PrintRemainingParameters(remainingParameters)); } // If no parameters are specified, add to current node, and done if (remainingParameters.IsEmpty()) { using (currentNode.NodeRWLock.AcquireWriteLock()) { currentNode.Add(filterCallback); } return; } // Need to find an existing index that matches one of the filter parameters Pair <FilterValueSetParam, FilterParamIndexBase> pair; using (currentNode.NodeRWLock.AcquireReadLock()) { pair = IndexHelper.FindIndex(remainingParameters, currentNode.Indizes); // Found an index matching a filter parameter if (pair != null) { remainingParameters.Remove(pair.First); var filterForValue = pair.First.FilterForValue; var index = pair.Second; treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(index, filterForValue)); AddToIndex(remainingParameters, filterCallback, index, filterForValue, treePathInfo, lockFactory); return; } } // An index for any of the filter parameters was not found, create one using (currentNode.NodeRWLock.AcquireWriteLock()) { pair = IndexHelper.FindIndex(remainingParameters, currentNode.Indizes); // Attempt to find an index again this time under a write lock if (pair != null) { remainingParameters.Remove(pair.First); var filterForValue = pair.First.FilterForValue; var indexX = pair.Second; treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(indexX, filterForValue)); AddToIndex(remainingParameters, filterCallback, indexX, filterForValue, treePathInfo, lockFactory); return; } // No index found that matches any parameters, create a new one // Pick the next parameter for an index FilterValueSetParam parameterPickedForIndex = remainingParameters.RemoveFirst(); var index = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator); currentNode.Indizes.Add(index); treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(index, parameterPickedForIndex.FilterForValue)); AddToIndex(remainingParameters, filterCallback, index, parameterPickedForIndex.FilterForValue, treePathInfo, lockFactory); } }
/// <summary> /// Add to an index the value to filter for. /// </summary> /// <param name="remainingParameters">The remaining parameters.</param> /// <param name="filterCallback">The filter callback.</param> /// <param name="index">is the index to add to</param> /// <param name="filterForValue">is the filter parameter value to add</param> /// <param name="treePathInfo">is the specification to fill on where is was added</param> /// <param name="lockFactory">The lock factory.</param> private static void AddToIndex( ArrayDeque <FilterValueSetParam> remainingParameters, FilterHandle filterCallback, FilterParamIndexBase index, Object filterForValue, ArrayDeque <EventTypeIndexBuilderIndexLookupablePair> treePathInfo, FilterServiceGranularLockFactory lockFactory) { if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".addToIndex ({0}) Adding to index {1} expressionValue={2}", Thread.CurrentThread.ManagedThreadId, index, filterForValue); } EventEvaluator eventEvaluator; using (index.ReadWriteLock.AcquireReadLock()) { eventEvaluator = index[filterForValue]; // The filter parameter value already existed in bean, add and release locks if (eventEvaluator != null) { var added = AddToEvaluator(remainingParameters, filterCallback, eventEvaluator, treePathInfo, lockFactory); if (added) { return; } } } // new filter parameter value, need a write lock using (index.ReadWriteLock.AcquireWriteLock()) { eventEvaluator = index[filterForValue]; // It may exist now since another thread could have added the entry if (eventEvaluator != null) { var added = AddToEvaluator(remainingParameters, filterCallback, eventEvaluator, treePathInfo, lockFactory); if (added) { return; } // The found eventEvaluator must be converted to a new FilterHandleSetNode var nextIndexX = (FilterParamIndexBase)eventEvaluator; var newNode = new FilterHandleSetNode(lockFactory.ObtainNew()); newNode.Add(nextIndexX); index.Remove(filterForValue); index[filterForValue] = newNode; AddToNode(remainingParameters, filterCallback, newNode, treePathInfo, lockFactory); return; } // The index does not currently have this filterCallback value, // if there are no remaining parameters, create a node if (remainingParameters.IsEmpty()) { var node = new FilterHandleSetNode(lockFactory.ObtainNew()); AddToNode(remainingParameters, filterCallback, node, treePathInfo, lockFactory); index[filterForValue] = node; return; } // If there are remaining parameters, create a new index for the next parameter FilterValueSetParam parameterPickedForIndex = remainingParameters.RemoveFirst(); var nextIndex = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator); index[filterForValue] = nextIndex; treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(nextIndex, parameterPickedForIndex.FilterForValue)); AddToIndex(remainingParameters, filterCallback, nextIndex, parameterPickedForIndex.FilterForValue, treePathInfo, lockFactory); } }
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; foreach (var entry in latch.DispatchTo) { var handle = entry.Key; handle.StatementHandle.MetricsHandle.Call( _metricReportingService.PerformanceCollector, () => { 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) => { NamedWindowConsumerLatch earlier = next.Earlier; if (earlier == null || work.Contains(earlier)) { work.Add(next); return(true); } else { continuation.Value = false; return(false); } }); ProcessDispatches(work, dispatchesPerStmt); } }
/// <summary> /// Returns true if the window is empty, or false if not empty. /// </summary> /// <returns>true if empty</returns> public bool IsEmpty() { return(_window.IsEmpty()); }
private static void EvaluateEventForStatementInternal(EPServicesContext servicesContext, EventBean theEvent, IList <AgentInstance> agentInstances) { // context was created - reevaluate for the given event var callbacks = new ArrayDeque <FilterHandle>(2); servicesContext.FilterService.Evaluate(theEvent, callbacks); // evaluates for ALL statements if (callbacks.IsEmpty()) { return; } // there is a single callback and a single context, if they match we are done if (agentInstances.Count == 1 && callbacks.Count == 1) { var agentInstance = agentInstances[0]; if (agentInstance.AgentInstanceContext.StatementId == callbacks.First.StatementId) { Process(agentInstance, servicesContext, callbacks, theEvent); } return; } // use the right sorted/unsorted Map keyed by AgentInstance to sort var isPrioritized = servicesContext.ConfigSnapshot.EngineDefaults.Execution.IsPrioritized; IDictionary <AgentInstance, object> stmtCallbacks; if (!isPrioritized) { stmtCallbacks = new Dictionary <AgentInstance, object>(); } else { stmtCallbacks = new SortedDictionary <AgentInstance, object>(AgentInstanceComparator.INSTANCE); } // process all callbacks foreach (var filterHandle in callbacks) { // determine if this filter entry applies to any of the affected agent instances var statementId = filterHandle.StatementId; AgentInstance agentInstanceFound = null; foreach (var agentInstance in agentInstances) { if (agentInstance.AgentInstanceContext.StatementId == statementId) { agentInstanceFound = agentInstance; break; } } if (agentInstanceFound == null) { // when the callback is for some other stmt continue; } var handleCallback = (EPStatementHandleCallback)filterHandle; var handle = handleCallback.AgentInstanceHandle; // Self-joins require that the internal dispatch happens after all streams are evaluated. // Priority or preemptive settings also require special ordering. if (handle.CanSelfJoin || isPrioritized) { var stmtCallback = stmtCallbacks.Get(agentInstanceFound); if (stmtCallback == null) { stmtCallbacks.Put(agentInstanceFound, handleCallback); } else if (stmtCallback is ICollection <FilterHandle> ) { var collection = (ICollection <FilterHandle>)stmtCallback; if (!collection.Contains(handleCallback)) // De-duplicate for Filter OR expression paths { collection.Add(handleCallback); } } else { var deque = new ArrayDeque <FilterHandle>(4); deque.Add((EPStatementHandleCallback)stmtCallback); if (stmtCallback != handleCallback) // De-duplicate for Filter OR expression paths { deque.Add(handleCallback); } stmtCallbacks.Put(agentInstanceFound, deque); } continue; } // no need to be sorted, process Process(agentInstanceFound, servicesContext, Collections.SingletonList <FilterHandle>(handleCallback), theEvent); } if (stmtCallbacks.IsEmpty()) { return; } // Process self-join or sorted prioritized callbacks foreach (var entry in stmtCallbacks) { var agentInstance = entry.Key; var callbackList = entry.Value; if (callbackList is ICollection <FilterHandle> ) { Process(agentInstance, servicesContext, (ICollection <FilterHandle>)callbackList, theEvent); } else { Process(agentInstance, servicesContext, Collections.SingletonList <FilterHandle>((FilterHandle)callbackList), theEvent); } if (agentInstance.AgentInstanceContext.EpStatementAgentInstanceHandle.IsPreemptive) { return; } } }
public static ExprDotNodeRealizedChain GetChainEvaluators( int?streamOfProviderIfApplicable, EPType inputType, IList <ExprChainedSpec> chainSpec, ExprValidationContext validationContext, bool isDuckTyping, ExprDotNodeFilterAnalyzerInput inputDesc) { var methodEvals = new List <ExprDotEval>(); var currentInputType = inputType; EnumMethodEnum?lastLambdaFunc = null; var lastElement = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1]; ExprDotNodeFilterAnalyzerDesc filterAnalyzerDesc = null; var chainSpecStack = new ArrayDeque <ExprChainedSpec>(chainSpec); while (!chainSpecStack.IsEmpty()) { var chainElement = chainSpecStack.RemoveFirst(); lastLambdaFunc = null; // reset // compile parameters for chain element var paramEvals = new ExprEvaluator[chainElement.Parameters.Count]; var paramTypes = new Type[chainElement.Parameters.Count]; for (var i = 0; i < chainElement.Parameters.Count; i++) { paramEvals[i] = chainElement.Parameters[i].ExprEvaluator; paramTypes[i] = paramEvals[i].ReturnType; } // check if special 'size' method if (currentInputType is ClassMultiValuedEPType) { var type = (ClassMultiValuedEPType)currentInputType; if ((chainElement.Name.ToLower() == "size") && paramTypes.Length == 0 && Equals(lastElement, chainElement)) { var sizeExpr = new ExprDotEvalArraySize(); methodEvals.Add(sizeExpr); currentInputType = sizeExpr.TypeInfo; continue; } if ((chainElement.Name.ToLower() == "get") && paramTypes.Length == 1 && paramTypes[0].GetBoxedType() == typeof(int?)) { var componentType = type.Component; var get = new ExprDotEvalArrayGet(paramEvals[0], componentType); methodEvals.Add(get); currentInputType = get.TypeInfo; continue; } } // determine if there is a matching method var matchingMethod = false; var methodTarget = GetMethodTarget(currentInputType); if (methodTarget != null) { try { GetValidateMethodDescriptor(methodTarget, chainElement.Name, chainElement.Parameters, validationContext); matchingMethod = true; } catch (ExprValidationException) { // expected } } // resolve lambda if (chainElement.Name.IsEnumerationMethod() && (!matchingMethod || methodTarget.IsArray || methodTarget.IsImplementsInterface(typeof(ICollection <object>)))) { var enumerationMethod = EnumMethodEnumExtensions.FromName(chainElement.Name); var eval = TypeHelper.Instantiate <ExprDotEvalEnumMethod>(enumerationMethod.GetImplementation()); eval.Init(streamOfProviderIfApplicable, enumerationMethod, chainElement.Name, currentInputType, chainElement.Parameters, validationContext); currentInputType = eval.TypeInfo; if (currentInputType == null) { throw new IllegalStateException("Enumeration method '" + chainElement.Name + "' has not returned type information"); } methodEvals.Add(eval); lastLambdaFunc = enumerationMethod; continue; } // resolve datetime if (chainElement.Name.IsDateTimeMethod() && (!matchingMethod || methodTarget == typeof(DateTimeOffset?))) { var datetimeMethod = DatetimeMethodEnumExtensions.FromName(chainElement.Name); var datetimeImpl = ExprDotEvalDTFactory.ValidateMake( validationContext.StreamTypeService, chainSpecStack, datetimeMethod, chainElement.Name, currentInputType, chainElement.Parameters, inputDesc, validationContext.EngineImportService.TimeZone, validationContext.EngineImportService.TimeAbacus); currentInputType = datetimeImpl.ReturnType; if (currentInputType == null) { throw new IllegalStateException("Date-time method '" + chainElement.Name + "' has not returned type information"); } methodEvals.Add(datetimeImpl.Eval); filterAnalyzerDesc = datetimeImpl.IntervalFilterDesc; continue; } // try to resolve as property if the last method returned a type if (currentInputType is EventEPType) { var inputEventType = ((EventEPType)currentInputType).EventType; var type = inputEventType.GetPropertyType(chainElement.Name); var getter = inputEventType.GetGetter(chainElement.Name); if (type != null && getter != null) { var noduck = new ExprDotEvalProperty(getter, EPTypeHelper.SingleValue(type.GetBoxedType())); methodEvals.Add(noduck); currentInputType = EPTypeHelper.SingleValue(EPTypeHelper.GetClassSingleValued(noduck.TypeInfo)); continue; } } // Finally try to resolve the method if (methodTarget != null) { try { // find descriptor again, allow for duck typing var desc = GetValidateMethodDescriptor(methodTarget, chainElement.Name, chainElement.Parameters, validationContext); var fastMethod = desc.FastMethod; paramEvals = desc.ChildEvals; ExprDotEval eval; if (currentInputType is ClassEPType) { // if followed by an enumeration method, convert array to collection if (fastMethod.ReturnType.IsArray && !chainSpecStack.IsEmpty() && chainSpecStack.First.Name.IsEnumerationMethod()) { eval = new ExprDotMethodEvalNoDuckWrapArray(validationContext.StatementName, fastMethod, paramEvals); } else { eval = new ExprDotMethodEvalNoDuck(validationContext.StatementName, fastMethod, paramEvals); } } else { eval = new ExprDotMethodEvalNoDuckUnderlying(validationContext.StatementName, fastMethod, paramEvals); } methodEvals.Add(eval); currentInputType = eval.TypeInfo; } catch (Exception e) { if (!isDuckTyping) { throw new ExprValidationException(e.Message, e); } else { var duck = new ExprDotMethodEvalDuck(validationContext.StatementName, validationContext.EngineImportService, chainElement.Name, paramTypes, paramEvals); methodEvals.Add(duck); currentInputType = duck.TypeInfo; } } continue; } var message = "Could not find event property, enumeration method or instance method named '" + chainElement.Name + "' in " + currentInputType.ToTypeDescriptive(); throw new ExprValidationException(message); } var intermediateEvals = methodEvals.ToArray(); if (lastLambdaFunc != null) { ExprDotEval finalEval = null; if (currentInputType is EventMultiValuedEPType) { var mvType = (EventMultiValuedEPType)currentInputType; var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(mvType.Component); if (tableMetadata != null) { finalEval = new ExprDotEvalUnpackCollEventBeanTable(mvType.Component, tableMetadata); } else { finalEval = new ExprDotEvalUnpackCollEventBean(mvType.Component); } } else if (currentInputType is EventEPType) { var epType = (EventEPType)currentInputType; var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(epType.EventType); if (tableMetadata != null) { finalEval = new ExprDotEvalUnpackBeanTable(epType.EventType, tableMetadata); } else { finalEval = new ExprDotEvalUnpackBean(epType.EventType); } } if (finalEval != null) { methodEvals.Add(finalEval); } } var unpackingEvals = methodEvals.ToArray(); return(new ExprDotNodeRealizedChain(intermediateEvals, unpackingEvals, filterAnalyzerDesc)); }
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); } }
public override void Update(EventBean[] newData, EventBean[] oldData) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get() .QViewProcessIRStream(this, _externallyTimedWindowViewFactory.ViewName, newData, oldData); } long timestamp = -1; // add data points to the window // we don't care about removed data from a prior view if (newData != null) { for (int i = 0; i < newData.Length; i++) { timestamp = GetLongValue(newData[i]); _timeWindow.Add(timestamp, newData[i]); } } // Remove from the window any events that have an older timestamp then the last event's timestamp ArrayDeque <EventBean> expired = null; if (timestamp != -1) { expired = _timeWindow.ExpireEvents(timestamp - _timeDeltaComputation.DeltaMillisecondsSubtract(timestamp) + 1); } EventBean[] oldDataUpdate = null; if ((expired != null) && (!expired.IsEmpty())) { oldDataUpdate = expired.ToArray(); } if ((oldData != null) && (AgentInstanceViewFactoryContext.IsRemoveStream)) { foreach (EventBean anOldData in oldData) { _timeWindow.Remove(anOldData); } if (oldDataUpdate == null) { oldDataUpdate = oldData; } else { oldDataUpdate = CollectionUtil.AddArrayWithSetSemantics(oldData, oldDataUpdate); } } if (_viewUpdatedCollection != null) { _viewUpdatedCollection.Update(newData, oldDataUpdate); } // If there are child views, fireStatementStopped update method if (HasViews) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().QViewIndicate(this, _externallyTimedWindowViewFactory.ViewName, newData, oldDataUpdate); } UpdateChildren(newData, oldDataUpdate); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().AViewIndicate(); } } if (InstrumentationHelper.ENABLED) { InstrumentationHelper.Get().AViewProcessIRStream(); } }