github.com/m3db/m3@v1.5.0/src/query/storage/m3/consolidators/series_consolidator.go (about)

     1  // Copyright (c) 2018 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package consolidators
    22  
    23  import (
    24  	"math"
    25  	"time"
    26  
    27  	"github.com/m3db/m3/src/dbnode/ts"
    28  	xtime "github.com/m3db/m3/src/x/time"
    29  )
    30  
    31  // SeriesLookbackConsolidator is a helper for consolidating a full single
    32  // series. It has some differences with the step consolidator in that it
    33  // collects points for a single series, and is reset when the next series
    34  // needs to be consolidated.
    35  type SeriesLookbackConsolidator struct {
    36  	lookbackDuration time.Duration
    37  	stepSize         time.Duration
    38  	earliestLookback xtime.UnixNano
    39  	consolidated     float64
    40  	datapoints       []ts.Datapoint
    41  	fn               ConsolidationFunc
    42  }
    43  
    44  // NewSeriesLookbackConsolidator creates a single value consolidator used for
    45  // series iteration with a given lookback.
    46  func NewSeriesLookbackConsolidator(
    47  	lookbackDuration, stepSize time.Duration,
    48  	startTime xtime.UnixNano,
    49  	fn ConsolidationFunc,
    50  ) *SeriesLookbackConsolidator {
    51  	datapoints := make([]ts.Datapoint, 0, initLength)
    52  	return &SeriesLookbackConsolidator{
    53  		lookbackDuration: lookbackDuration,
    54  		stepSize:         stepSize,
    55  		earliestLookback: startTime.Add(-1 * lookbackDuration),
    56  		consolidated:     math.NaN(),
    57  		datapoints:       datapoints,
    58  		fn:               fn,
    59  	}
    60  }
    61  
    62  // AddPoint adds a datapoint if it's within the valid time period;
    63  // otherwise drops it silently, which is fine for consolidation.
    64  func (c *SeriesLookbackConsolidator) AddPoint(
    65  	dp ts.Datapoint,
    66  ) {
    67  	if dp.TimestampNanos.Before(c.earliestLookback) {
    68  		// this datapoint is too far in the past, it can be dropped.
    69  		return
    70  	}
    71  
    72  	c.datapoints = append(c.datapoints, dp)
    73  }
    74  
    75  // ConsolidateAndMoveToNext consolidates the current values and moves the
    76  // consolidator to the next given value, purging stale values.
    77  func (c *SeriesLookbackConsolidator) ConsolidateAndMoveToNext() float64 {
    78  	c.earliestLookback = c.earliestLookback.Add(c.stepSize)
    79  	c.consolidated = c.fn(c.datapoints)
    80  	c.datapoints = removeStale(c.earliestLookback, c.datapoints)
    81  
    82  	// Remove any datapoints not relevant to the next step now.
    83  	datapointsRelevant := removeStale(c.earliestLookback, c.datapoints)
    84  	if len(datapointsRelevant) > 0 {
    85  		// Move them back to the start of the slice to reuse the slice
    86  		// as best as possible.
    87  		c.datapoints = c.datapoints[:len(datapointsRelevant)]
    88  		copy(c.datapoints, datapointsRelevant)
    89  	} else {
    90  		// No relevant datapoints, repoint to the start of the buffer.
    91  		c.datapoints = c.datapoints[:0]
    92  	}
    93  
    94  	return c.consolidated
    95  }
    96  
    97  // Empty returns true if there are no datapoints in the consolidator. It
    98  // is used to let consumers of the consolidators shortcircuit logic.
    99  func (c *SeriesLookbackConsolidator) Empty() bool {
   100  	return len(c.datapoints) == 0
   101  }
   102  
   103  // Reset purges all points from the consolidator. This should be called
   104  // when moving to the next series to consolidate.
   105  func (c *SeriesLookbackConsolidator) Reset(
   106  	startTime xtime.UnixNano,
   107  ) {
   108  	c.earliestLookback = startTime.Add(-1 * c.lookbackDuration)
   109  	c.datapoints = c.datapoints[:0]
   110  }