protected override void PerformMainLoopService()
        {
            if (sampleIntervalTimer.Started != BaseState.IsOnline)
            {
                if (BaseState.IsOnline)
                {
                    sampleIntervalTimer.Reset(triggerImmediately: true);
                    sampleRecordingIntervalTimer.Reset(triggerImmediately: true);
                }
                else
                {
                    sampleIntervalTimer.Stop();
                    sampleRecordingIntervalTimer.Stop();
                }
            }

            if (sampleIntervalTimer.IsTriggered)
            {
                NetworkInterface[] netInterfacesArray = NetworkInterface.GetAllNetworkInterfaces();

                bool occurrenceRecorded = false;

                foreach (var netIface in netInterfacesArray)
                {
                    NetIfaceTracker nit = null;
                    if (netIfaceTrackerDictionary.TryGetValue(netIface.Name, out nit) && nit != null)
                    {
                        var deltaType = nit.Service(netIface);

                        if (deltaType != DeltaType.None)
                        {
                            if (deltaType.IsSet(DeltaType.Settings))
                            {
                                var dataVC = nit.SettingsOccurrenceDataVC;
                                mdrfWriter.RecordOccurrence(netIfaceSettingChangeOccurrence, dataVC: nit.SettingsOccurrenceDataVC);
                                Log.Info.Emit("Adapter Settings changed: {0}", dataVC);

                                occurrenceRecorded = true;
                            }

                            if (deltaType.IsSet(DeltaType.Status))
                            {
                                var dataVC = nit.StateOccurrenceDataVC;
                                mdrfWriter.RecordOccurrence(netIfaceStatusChangeOccurrence, dataVC: nit.StateOccurrenceDataVC);
                                Log.Info.Emit("Adapter State changed: {0}", dataVC);

                                occurrenceRecorded = true;
                            }
                        }
                    }
                }

                if (sampleRecordingIntervalTimer.IsTriggered || occurrenceRecorded)
                {
                    mdrfWriter.RecordGroups();
                }
            }
        }
        protected override void PerformMainLoopService()
        {
            if (sampleIntervalTimer.Started != BaseState.IsOnline)
            {
                if (BaseState.IsOnline)
                {
                    sampleIntervalTimer.Reset(triggerImmediately: true);
                }
                else
                {
                    sampleIntervalTimer.Stop();
                }
            }

            bool sampleIntervalTimerTriggered = sampleIntervalTimer.IsTriggered;

            try
            {
                pingTrackerArray.DoForEach(pt => pt.Service(sampleIntervalTimerTriggered, Log));

                if (sampleIntervalTimerTriggered)
                {
                    bool aggregationIntervalTimerTriggered = aggregationIntervalTimer.IsTriggered;
                    if (aggregationIntervalTimerTriggered)
                    {
                        TimeSpan measuredAggregationInterval = aggregationIntervalTimer.ElapsedTimeAtLastTrigger;

                        pingTrackerArray.DoForEach(pt => pt.hGrp.UpdateGroupItems());

                        mdrfWriter.RecordGroups();

                        pingTrackerArray.DoForEach(pt => noMDRFLogger.Info.Emit("Ping '{0}' [{1}] results: {2} to:{3} fails:{4}", pt.HostNameOrAddress, pt.IPAddress, pt.h.ToString(Histogram.TSInclude.BaseWithMedEst), pt.timeoutCount, pt.failureCount));
                        pingTrackerArray.DoForEach(pt => pt.h.Clear());
                    }
                }
            }
            catch (System.Exception ex)
            {
                Log.Debug.Emit("{0} generated unexpected exception: {1}", CurrentMethodName, ex.ToString(ExceptionFormat.TypeAndMessage));
            }
        }
        private void TrackProcesss(Process[] processes, QpcTimeStamp getTimeStamp)
        {
            foreach (var p in processes)
            {
                ProcessTracker pt = null;

                if (trackedProcessDictionary.TryGetValue(p.Id, out pt) && pt != null)
                {
                    pt.UpdateFrom(p, getTimeStamp);
                    if (pt.activePTSetIndex >= 0)
                    {
                        activeSetItemTrackerArray[pt.activePTSetIndex].UpdateGroupItems();
                    }
                }
                else
                {
                    pt = new ProcessTracker(p, getTimeStamp);
                    RecordProcessAdded(pt);
                }
            }

            UpdatePTSetArrayIfNeeded();

            int            activeCount            = 0;
            bool           anyToElevate           = false;
            ProcessTracker possibleNextToActivate = null;

            foreach (var pt in ptSetArray)
            {
                string removeReason = null;

                double lastUpdateAge = (getTimeStamp - pt.touchedTimeStamp).TotalSeconds;
                if (lastUpdateAge > 0.0)
                {
                    removeReason = "Process drop detected after {0:f2} seconds".CheckedFormat(lastUpdateAge);
                }

                double estCpuUsage   = pt.trackedValues.cpuPerEst;
                string elevateReason = ((estCpuUsage >= Config.CPUUsageEstimateThresholdInPercentPerCore) ? "cpu [{0:f3}>={1}]".CheckedFormat(estCpuUsage, Config.CPUUsageEstimateThresholdInPercentPerCore): null)
                                       ?? ((pt.trackedValues.workingSetSize >= Config.WorkingSetUsageThreshold) ? "ws [{0}>={1}]".CheckedFormat(pt.trackedValues.workingSetSize, Config.WorkingSetUsageThreshold) : null);

                if (!removeReason.IsNullOrEmpty())
                {
                    RecordProcessRemoved(pt, removeReason);
                }
                else if (!elevateReason.IsNullOrEmpty())
                {
                    pt.elevationRequestReason = elevateReason;
                    pt.lastElevationRequestTriggerTimeStamp = getTimeStamp;

                    if (!pt.IsInActiveSet)
                    {
                        anyToElevate = true;
                    }
                }
                else if (pt.IsElevationRequested && (getTimeStamp - pt.lastElevationRequestTriggerTimeStamp) > Config.ForcedElevationHoldPeriod)
                {
                    pt.elevationRequestReason = null;
                }

                if (pt.IsInActiveSet)
                {
                    activeCount++;
                }
                else if (!pt.IsElevationRequested && (possibleNextToActivate == null || pt.trackedValues.cpuTime > possibleNextToActivate.trackedValues.cpuTime))
                {
                    possibleNextToActivate = pt;
                }
            }

            UpdatePTSetArrayIfNeeded();

            if (activeCount < ptSetArrayLength || anyToElevate || possibleNextToActivate != null)
            {
                for (; ;)
                {
                    int useActivePTSetIndex = FindFirstEmptyActivePTSetIndex();

                    // find the next inactive pt that IsElevationRequested and which has the largest totalProcessorTime
                    ProcessTracker nextElevatedPtToActivate = null;
                    ProcessTracker lowestActiveNonElevated = null, lowestActiveElevated = null;

                    for (int idx = 0; idx < ptSetArrayLength; idx++)
                    {
                        ProcessTracker pt                   = ptSetArray[idx];
                        bool           isInActiveSet        = pt.IsInActiveSet;
                        bool           isElevationRequested = pt.IsElevationRequested;

                        if (isInActiveSet && !isElevationRequested && (lowestActiveElevated == null || pt.trackedValues.cpuTime < lowestActiveElevated.trackedValues.cpuTime))
                        {
                            lowestActiveElevated = pt;
                        }
                        else if (isInActiveSet && !isElevationRequested && (lowestActiveNonElevated == null || pt.trackedValues.cpuTime < lowestActiveNonElevated.trackedValues.cpuTime))
                        {
                            lowestActiveNonElevated = pt;
                        }
                        else if (!isInActiveSet && isElevationRequested && (nextElevatedPtToActivate == null || pt.trackedValues.cpuTime > nextElevatedPtToActivate.trackedValues.cpuTime))
                        {
                            nextElevatedPtToActivate = pt;
                        }
                        else if (!isInActiveSet && !isElevationRequested && (possibleNextToActivate == null || pt.trackedValues.cpuTime > possibleNextToActivate.trackedValues.cpuTime))
                        {
                            possibleNextToActivate = pt;
                        }
                    }

                    ProcessTracker ptToActivate = nextElevatedPtToActivate;

                    if (ptToActivate == null && possibleNextToActivate != null && (useActivePTSetIndex >= 0 || lowestActiveNonElevated != null && lowestActiveNonElevated.trackedValues.cpuTime < possibleNextToActivate.trackedValues.cpuTime))
                    {
                        ptToActivate = possibleNextToActivate;
                    }

                    if (ptToActivate != null && useActivePTSetIndex < 0)
                    {
                        if (lowestActiveNonElevated != null)
                        {
                            useActivePTSetIndex = lowestActiveNonElevated.activePTSetIndex;
                        }
                        else if (lowestActiveElevated != null && nextElevatedPtToActivate != null)
                        {
                            useActivePTSetIndex = lowestActiveElevated.activePTSetIndex;
                        }
                        else
                        {
                            if (!unableToAddProcessTrackerToActiveSet)
                            {
                                unableToAddProcessTrackerToActiveSet = true;

                                RecordProcessEvent("ActiveSetFull", ptToActivate, includeExtraProcessInfo: false, includeTrackedValues: true);
                            }
                            break;      // active set is full and we have nowhere to put any new items
                        }
                    }

                    if (ptToActivate == null)
                    {
                        break;
                    }

                    Activate(ptToActivate, useActivePTSetIndex);

                    unableToAddProcessTrackerToActiveSet = false;
                    possibleNextToActivate = null;
                }
            }

            mdrfWriter.RecordGroups();
        }
        protected override void PerformMainLoopService()
        {
            if (sampleIntervalTimer.Started != BaseState.IsOnline)
            {
                if (BaseState.IsOnline)
                {
                    sampleIntervalTimer.Reset(triggerImmediately: true);
                }
                else
                {
                    sampleIntervalTimer.Stop();
                }
            }

            if (sampleIntervalTimer.IsTriggered)
            {
                try
                {
                    CreateFileIfNeeded();

                    foreach (var t in accumTupleArray)
                    {
                        t.Item1.Histogram.Clear();
                    }

                    ReadGroupOfBuffersFromFile(fsReadNormal, hReadNormal);

                    if (Config.UseFileFlagNoBuffering && fsReadThrough != null)
                    {
                        ReadGroupOfBuffersFromFile(fsReadThrough, hReadThrough);
                    }

                    if (Config.EnableContinuousWriting)
                    {
                        WriteGroupOfBuffersToFile(fsWriteThrough, hWriteThrough);
                    }

                    foreach (var t in accumTupleArray)
                    {
                        t.Item2.Histogram.Add(t.Item1.Histogram);
                        t.Item1.UpdateGroupItems();
                    }

                    bool aggregationIntervalTimerTriggered = aggregationIntervalTimer.IsTriggered;
                    if (aggregationIntervalTimerTriggered)
                    {
                        TimeSpan measuredAggregationInterval = aggregationIntervalTimer.ElapsedTimeAtLastTrigger;

                        foreach (var t in accumTupleArray)
                        {
                            t.Item2.UpdateGroupItems();
                        }

                        double peakNormalReadRate, peakThroughReadRate, peakThroughWriteRate;

                        peakReadNormalRateGPI.VC   = new ValueContainer(peakNormalReadRate = SafeRate(bufferSize, ahReadNormal));
                        peakReadThroughRateGPI.VC  = new ValueContainer(peakThroughReadRate = SafeRate(bufferSize, ahReadThrough));
                        peakWriteThroughRateGPI.VC = new ValueContainer(peakThroughWriteRate = SafeRate(bufferSize, ahWriteThrough));

                        double peakNormalReadIOPs   = SafeRate(1, ahReadNormal);
                        double peakReadThroughIOPs  = SafeRate(1, ahReadThrough);
                        double peakWriteThroughIOPs = SafeRate(1, ahWriteThrough);
                        double avgNormalReadIOPs    = SafeRate(ahReadNormal.Count, measuredAggregationInterval);
                        double avgReadThroughIOPs   = SafeRate(ahReadThrough.Count, measuredAggregationInterval);
                        double avgWriteThroughIOPs  = SafeRate(ahWriteThrough.Count, measuredAggregationInterval);

                        if (firstAHLog)
                        {
                            noMDRFLogger.Info.Emit("ahWriteThroughBoundaries: {0}", ahWriteThrough.BinBoundaryArrayVC);
                            firstAHLog = false;
                        }

                        noMDRFLogger.Info.Emit("TotalBytes:{0} Mb ahWriteThrough: {1}", totalBytesWritten * (1.0 / (1024 * 1024)), ahWriteThrough.ToString(Histogram.TSInclude.BaseWithMedEst));
                        noMDRFLogger.Info.Emit("ahWriteThrough Counts: {0}", ahWriteThrough.BinCountArrayVC);
                        noMDRFLogger.Info.Emit("PeakRates (k/s): rdNormal:{0:f1} rdThrough:{1:f1} wrThrough:{2:f1}", peakNormalReadRate * (1.0 / 1024), peakThroughReadRate * (1.0 / 1024), peakThroughWriteRate * (1.0 / 1024));
                        noMDRFLogger.Info.Emit("IOPs (rn, rt, wt): peak: {0:f1} {1:f1} {2:f1}, avg: {3:f1} {4:f1} {5:f1}", peakNormalReadIOPs, peakReadThroughIOPs, peakWriteThroughIOPs, avgNormalReadIOPs, avgReadThroughIOPs, avgWriteThroughIOPs);
                    }

                    mdrfWriter.RecordGroups();

                    if (aggregationIntervalTimerTriggered)
                    {
                        foreach (var t in accumTupleArray)
                        {
                            t.Item2.Histogram.Clear();
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    Log.Debug.Emit("{0} generated unexpected exception: {1}", CurrentMethodName, ex.ToString(ExceptionFormat.TypeAndMessage));
                }
            }
        }
        protected override void PerformMainLoopService()
        {
            if (sampleIntervalTimer.Started != BaseState.IsOnline)
            {
                if (BaseState.IsOnline)
                {
                    sampleIntervalTimer.Reset(triggerImmediately: true);
                }
                else
                {
                    sampleIntervalTimer.Stop();
                }
            }

            if (sampleIntervalTimer.IsTriggered)
            {
                h1.Clear();

                QpcTimeStamp now = QpcTimeStamp.Now;
                for (int idx = 0; idx < h1SampleSize; idx++)        // this loop is fast enough to not need to check for HasStopBeenRequested
                {
                    QpcTimeStamp start = now;
                    System.Threading.Thread.Sleep(1);
                    QpcTimeStamp end = now = QpcTimeStamp.Now;

                    h1.Add((end - start).TotalSeconds);
                }

                System.Threading.Thread.Sleep(10);

                h10.Clear();

                now = QpcTimeStamp.Now;
                for (int idx = 0; idx < h10SampleSize && !HasStopBeenRequested && actionQ.IsEmpty; idx++)
                {
                    QpcTimeStamp start = now;
                    System.Threading.Thread.Sleep(10);
                    QpcTimeStamp end = now = QpcTimeStamp.Now;

                    h10.Add((end - start).TotalSeconds);
                }

                System.Threading.Thread.Sleep(10);

                h30.Clear();

                now = QpcTimeStamp.Now;
                for (int idx = 0; idx < h100SampleSize && !HasStopBeenRequested && actionQ.IsEmpty; idx++)
                {
                    QpcTimeStamp start = now;
                    System.Threading.Thread.Sleep(30);
                    QpcTimeStamp end = now = QpcTimeStamp.Now;

                    h30.Add((end - start).TotalSeconds);
                }

                h1Grp.UpdateGroupItems();
                h10Grp.UpdateGroupItems();
                h30Grp.UpdateGroupItems();

                ah1.Add(h1);
                ah10.Add(h10);
                ah30.Add(h30);

                bool aggregationIntervalTimerTriggered = aggregationIntervalTimer.IsTriggered;
                if (aggregationIntervalTimerTriggered)
                {
                    ah1Grp.UpdateGroupItems();
                    ah10Grp.UpdateGroupItems();
                    ah30Grp.UpdateGroupItems();

                    Log.Info.Emit("AH10: {0}", ah10.ToString(Histogram.TSInclude.BaseWithMedEst | Histogram.TSInclude.BinCountArray));
                }

                mdrfWriter.RecordGroups();

                if (aggregationIntervalTimerTriggered)
                {
                    ah1.Clear();
                    ah10.Clear();
                    ah30.Clear();
                }
            }
        }