/// <summary> /// Remove all the objects from the cache. /// </summary> /// <returns>All the objects that were in the cache.</returns> internal List <PacketInfoData> Drain() { // if neither there,we did not cache at all if (_frontEndQueue == null && _groupQueue == null) { return(null); } List <PacketInfoData> retVal = new List <PacketInfoData>(); if (_frontEndQueue != null) { if (_groupQueue == null) { // drain the front queue and return the data while (_frontEndQueue.Count > 0) { retVal.Add(_frontEndQueue.Dequeue()); } return(retVal); } // move from the front to the back queue while (_frontEndQueue.Count > 0) { List <PacketInfoData> groupQueueOut = _groupQueue.Add(_frontEndQueue.Dequeue()); if (groupQueueOut != null) { foreach (PacketInfoData x in groupQueueOut) { retVal.Add(x); } } } } // drain the back queue while (true) { PacketInfoData obj = _groupQueue.Dequeue(); if (obj == null) { break; } retVal.Add(obj); } return(retVal); }
private void UpdateObjectCount(PacketInfoData o) { // add only of it's not a control message // and it's not out of band FormatEntryData fed = o as FormatEntryData; if (fed == null || fed.outOfBand) { return; } _currentObjectCount++; }
/// <summary> /// Add an object to the cache. the behavior depends on the object added, the /// objects already in the cache and the cache settings. /// </summary> /// <param name="o">Object to add.</param> /// <returns>List of objects the cache is flushing.</returns> internal List <PacketInfoData> Add(PacketInfoData o) { // if neither there, pass thru if (_frontEndQueue == null && _groupQueue == null) { List <PacketInfoData> retVal = new List <PacketInfoData>(); retVal.Add(o); return(retVal); } // if front present, add to front if (_frontEndQueue != null) { _frontEndQueue.Enqueue(o); return(null); } // if back only, add to back return(_groupQueue.Add(o)); }
/// <summary> /// Add an object to the cache. /// </summary> /// <param name="o">Object to add.</param> /// <returns>Objects the cache needs to return. It can be null.</returns> internal List <PacketInfoData> Add(PacketInfoData o) { FormatStartData fsd = o as FormatStartData; if (fsd != null) { // just cache the reference (used during the notification call) _formatStartData = fsd; } UpdateObjectCount(o); // STATE TRANSITION: we are not processing and we start if (!_processingGroup && (o is GroupStartData)) { // just set the flag and start caching _processingGroup = true; _currentObjectCount = 0; if (_groupingDuration > TimeSpan.MinValue) { _groupingTimer = Stopwatch.StartNew(); } _queue.Enqueue(o); return(null); } // STATE TRANSITION: we are processing and we stop if (_processingGroup && ((o is GroupEndData) || (_objectCount > 0) && (_currentObjectCount >= _objectCount)) || ((_groupingTimer != null) && (_groupingTimer.Elapsed > _groupingDuration)) ) { // reset the object count _currentObjectCount = 0; if (_groupingTimer != null) { _groupingTimer.Stop(); _groupingTimer = null; } // add object to queue, to be picked up _queue.Enqueue(o); // we are at the end of a group, drain the queue Notify(); _processingGroup = false; List <PacketInfoData> retVal = new List <PacketInfoData>(); while (_queue.Count > 0) { retVal.Add(_queue.Dequeue()); } return(retVal); } // NO STATE TRANSITION: check the state we are in if (_processingGroup) { // we are in the caching state _queue.Enqueue(o); return(null); } // we are not processing, so just return it List <PacketInfoData> ret = new List <PacketInfoData>(); ret.Add(o); return(ret); }
/// <summary> /// Process an object from an input stream. It manages the context stack and /// calls back on the specified event delegates. /// </summary> /// <param name="o">Object to process.</param> internal void Process(object o) { PacketInfoData formatData = o as PacketInfoData; FormatEntryData fed = formatData as FormatEntryData; if (fed != null) { OutputContext ctx = null; if (!fed.outOfBand) { ctx = _stack.Peek(); } // notify for Payload this.payload(fed, ctx); } else { bool formatDataIsFormatStartData = formatData is FormatStartData; bool formatDataIsGroupStartData = formatData is GroupStartData; // it's one of our formatting messages // we assume for the moment that they are in the correct sequence if (formatDataIsFormatStartData || formatDataIsGroupStartData) { OutputContext oc = this.contextCreation(this.ActiveOutputContext, formatData); _stack.Push(oc); // now we have the context properly set: need to notify the // underlying algorithm to do the start document or group stuff if (formatDataIsFormatStartData) { // notify for Fs this.fs(oc); } else if (formatDataIsGroupStartData) { // GroupStartData gsd = (GroupStartData) formatData; // notify for Gs this.gs(oc); } } else { GroupEndData ged = formatData as GroupEndData; FormatEndData fEndd = formatData as FormatEndData; if (ged != null || fEndd != null) { OutputContext oc = _stack.Peek(); if (fEndd != null) { // notify for Fe, passing the Fe info, before a Pop() this.fe(fEndd, oc); } else if (ged != null) { // notify for Fe, passing the Fe info, before a Pop() this.ge(ged, oc); } _stack.Pop(); } } } }