Esempio n. 1
0
        protected ListeningProbe()
        {
            _maxDataStoresPerSecond     = null; // no data rate limit by default
            _keepDeviceAwake            = DefaultKeepDeviceAwake;
            _deviceAwake                = false;
            _incomingDataRateCalculator = new DataRateCalculator(100);

            // store all data to start with. we'll compute a store/drop rate after data have arrived.
            _samplingModulus            = 1;
            _samplingModulusMatchAction = SamplingModulusMatchAction.Store;
        }
Esempio n. 2
0
        public sealed override Task <bool> StoreDatumAsync(Datum datum, CancellationToken?cancellationToken = default(CancellationToken?))
        {
            bool store = true;

            float maxDataStoresPerSecond = _maxDataStoresPerSecond.GetValueOrDefault(-1);

            // 0 (or negligible) data per second:  don't store. if max data per second is not set, the following inequality will be false.
            if (Math.Abs(maxDataStoresPerSecond) < DATA_RATE_EPSILON)
            {
                store = false;
            }
            // non-negligible (or default -1) data per second:  check data rate
            else if (maxDataStoresPerSecond > 0)
            {
                _incomingDataRateCalculator.Add(datum);

                // recalculate the sampling modulus after accumulating a full sample size in the data rate calculator
                if ((_incomingDataRateCalculator.TotalAdded % _incomingDataRateCalculator.SampleSize) == 0)
                {
                    double incomingDataPerSecond = _incomingDataRateCalculator.DataPerSecond;
                    double extraDataPerSecond    = incomingDataPerSecond - maxDataStoresPerSecond;

                    // if we're not over the limit then store all samples
                    if (extraDataPerSecond <= 0)
                    {
                        _samplingModulus            = 1;
                        _samplingModulusMatchAction = SamplingModulusMatchAction.Store;
                    }
                    // otherwise calculate a modulus that will get as close as possible to the desired rate given the empirical rate
                    else
                    {
                        double samplingModulusMatchRate = extraDataPerSecond / incomingDataPerSecond;
                        _samplingModulusMatchAction = SamplingModulusMatchAction.Drop;

                        if (samplingModulusMatchRate > 0.5)
                        {
                            samplingModulusMatchRate    = 1 - samplingModulusMatchRate;
                            _samplingModulusMatchAction = SamplingModulusMatchAction.Store;
                        }

                        if (_samplingModulusMatchAction == SamplingModulusMatchAction.Store)
                        {
                            // round the (store) modulus down to oversample -- more is better, right?
                            _samplingModulus = (int)Math.Floor(1 / samplingModulusMatchRate);
                        }
                        else
                        {
                            // round the (drop) modulus up to oversample -- more is better, right?
                            _samplingModulus = (int)Math.Ceiling(1 / samplingModulusMatchRate);
                        }
                    }
                }

                bool isModulusMatch = (_incomingDataRateCalculator.TotalAdded % _samplingModulus) == 0;

                if ((_samplingModulusMatchAction == SamplingModulusMatchAction.Store && !isModulusMatch) || (_samplingModulusMatchAction == SamplingModulusMatchAction.Drop && isModulusMatch))
                {
                    store = false;
                }
            }

            if (store)
            {
                return(base.StoreDatumAsync(datum, cancellationToken));
            }
            else
            {
                return(Task.FromResult(false));
            }
        }