示例#1
0
        private static bool AddAggregator(IMetricSeriesAggregator aggregator, AggregatorCollection aggregatorCollection)
        {
            if (aggregatorCollection == null)
            {
                return(false);
            }

            IMetricSeriesFilter seriesFilter = aggregatorCollection.Filter;
            IMetricValueFilter  valueFilter;

            if (!Util.FilterWillConsume(seriesFilter, aggregator.DataSeries, out valueFilter))
            {
                return(false);
            }

            aggregator.Reset(aggregatorCollection.PeriodStart, valueFilter);
            aggregatorCollection.Aggregators.Add(aggregator);

            return(true);
        }
        private List <MetricAggregate> GetPersistentAggregations(DateTimeOffset tactTimestamp, IMetricSeriesFilter previousFilter)
        {
            // Complete each persistent aggregator:
            // The Enumerator of GrowingCollection is a thread-safe lock-free implementation that operates on a "snapshot" of a collection taken at the
            // time when the enumerator is created. We expand the foreach statement (like the compiler normally does) so that we can use the typed
            // enumerator's Count property which is constsent with the data in the snapshot.

            GrowingCollection <IMetricSeriesAggregator> .Enumerator persistentValsAggregators = this.aggregatorsForPersistent.Aggregators.GetEnumerator();
            List <MetricAggregate> persistentValsAggregations = new List <MetricAggregate>(capacity: persistentValsAggregators.Count);

            try
            {
                while (persistentValsAggregators.MoveNext())
                {
                    IMetricSeriesAggregator aggregator = persistentValsAggregators.Current;
                    if (aggregator != null)
                    {
                        // Persistent aggregators are always active, regardless of filters for a particular cycle.
                        // But we can apply the cycle's filters to determine whether or not to pull the aggregator
                        // for a aggregate at this time. Of course, only series filters, not value filters, can be considered.
                        IMetricValueFilter unusedValueFilter;
                        bool satisfiesFilter = Util.FilterWillConsume(previousFilter, aggregator.DataSeries, out unusedValueFilter);
                        if (satisfiesFilter)
                        {
                            MetricAggregate aggregate = aggregator.CompleteAggregation(tactTimestamp);

                            if (aggregate != null)
                            {
                                persistentValsAggregations.Add(aggregate);
                            }
                        }
                    }
                }
            }
            finally
            {
                persistentValsAggregators.Dispose();
            }

            return(persistentValsAggregations);
        }
示例#3
0
        private IMetricSeriesAggregator GetOrCreateAggregator(MetricAggregationCycleKind aggregationCycleKind, ref WeakReference <IMetricSeriesAggregator> aggregatorWeakRef)
        {
            while (true)
            {
                // Local cache for the reference in case of concurrnet updates:
                WeakReference <IMetricSeriesAggregator> currentAggregatorWeakRef = aggregatorWeakRef;

                // Try to dereference the weak reference:
                IMetricSeriesAggregator aggregatorHardRef = UnwrapAggregator(currentAggregatorWeakRef);
                if (aggregatorHardRef != null)
                {
                    return(aggregatorHardRef);
                }

                // END OF FAST PATH. Could not dereference aggregator. Will attempt to create it...

                // So aggretator is NULL. For non-default cycle kinds, see if the there is even a cycle hooked up:

                if (aggregationCycleKind != CycleKind.Default)
                {
                    IMetricSeriesFilter dataSeriesFilter;
                    if (false == this.aggregationManager.IsCycleActive(aggregationCycleKind, out dataSeriesFilter))
                    {
                        return(null);
                    }

                    // Ok, a cycle is, indeed, acgive up. See if the cycle's filter is interested in this series:

                    // Respect the filter. Note: Filter may be user code. If user code is broken, assume we accept the series.
                    IMetricValueFilter valuesFilter;
                    if (false == Util.FilterWillConsume(dataSeriesFilter, this, out valuesFilter))
                    {
                        return(null);
                    }
                }

                // Ok, they want to consume us. Create new aggregator and a weak reference to it:

                IMetricSeriesAggregator newAggregator = this.GetNewOrRecycledAggregatorInstance(aggregationCycleKind);
                WeakReference <IMetricSeriesAggregator> newAggregatorWeakRef = new WeakReference <IMetricSeriesAggregator>(newAggregator, trackResurrection: false);

                // Store the weak reference to the aggregator. However, there is a race on doing it, so check for it:
                WeakReference <IMetricSeriesAggregator> prevAggregatorWeakRef = Interlocked.CompareExchange(ref aggregatorWeakRef, newAggregatorWeakRef, currentAggregatorWeakRef);
                if (prevAggregatorWeakRef == currentAggregatorWeakRef)
                {
                    // We won the race and stored the aggregator. Now tell the manager about it and go on using it.
                    // Note that the status of IsCycleActive and the dataSeriesFilter may have changed concurrently.
                    // So it is essential that we do this after the above interlocked assignment of aggregator.
                    // It ensures that only objects are added to the aggregator collection that are also referenced by the data series.
                    // In addition, AddAggregator(..) always uses the current value of the aggregator-collection in a thread-safe manner.
                    // Becasue the aggregator collection reference is always updated before telling the aggregators to cycle,
                    // we know that any aggregator added will be eventually cycled.
                    // If adding succeeds, AddAggregator(..) will have set the correct filter.
                    bool added = this.aggregationManager.AddAggregator(newAggregator, aggregationCycleKind);

                    // If the manager does not accept the addition, it means that the aggregationCycleKind is disabled or that the filter is not interested in this data series.
                    // Either way we need to give up.
                    if (added)
                    {
                        return(newAggregator);
                    }
                    else
                    {
                        // We could have accepted some values into this aggregator in the short time it was set in this series. We will loose those values.
                        Interlocked.CompareExchange(ref aggregatorWeakRef, null, newAggregatorWeakRef);
                        return(null);
                    }
                }

                // We lost the race and a different aggregator was used. Loop again. Doing so will attempt to dereference the latest aggregator reference.
            }
        }