influxdb/pkg/data/gen/series_generator.go

182 lines
3.7 KiB
Go
Raw Normal View History

package gen
import (
"math"
"time"
"github.com/influxdata/influxdb/v2/models"
)
type SeriesGenerator interface {
// Next advances the series generator to the next series key.
Next() bool
// Key returns the series key.
// The returned value may be cached.
Key() []byte
2020-04-24 16:47:22 +00:00
// Name returns the name of the measurement.
// The returned value may be modified by a subsequent call to Next.
Name() []byte
// Tags returns the tag set.
// The returned value may be modified by a subsequent call to Next.
Tags() models.Tags
// Field returns the name of the field.
// The returned value may be modified by a subsequent call to Next.
Field() []byte
// FieldType returns the data type for the field.
FieldType() models.FieldType
// TimeValuesGenerator returns a values sequence for the current series.
TimeValuesGenerator() TimeValuesSequence
}
type TimeSequenceSpec struct {
// Count specifies the maximum number of values to generate.
Count int
// Start specifies the starting time for the values.
Start time.Time
2020-04-24 16:47:22 +00:00
// Delta specifies the interval between time stamps.
Delta time.Duration
// Precision specifies the precision of timestamp intervals
Precision time.Duration
}
func (ts TimeSequenceSpec) ForTimeRange(tr TimeRange) TimeSequenceSpec {
// Truncate time range
if ts.Delta > 0 {
tr = tr.Truncate(ts.Delta)
} else {
tr = tr.Truncate(ts.Precision)
}
ts.Start = tr.Start
if ts.Delta > 0 {
intervals := int(tr.End.Sub(tr.Start) / ts.Delta)
if intervals > ts.Count {
// if the number of intervals in the specified time range exceeds
// the maximum count, move the start forward to limit the number of values
ts.Start = tr.End.Add(-time.Duration(ts.Count) * ts.Delta)
} else {
ts.Count = intervals
}
} else {
ts.Delta = tr.End.Sub(tr.Start) / time.Duration(ts.Count)
if ts.Delta < ts.Precision {
// count is too high for the range of time and precision
ts.Count = int(tr.End.Sub(tr.Start) / ts.Precision)
ts.Delta = ts.Precision
} else {
ts.Delta = ts.Delta.Round(ts.Precision)
}
ts.Precision = 0
}
return ts
}
type TimeRange struct {
Start time.Time
End time.Time
}
func (t TimeRange) Truncate(d time.Duration) TimeRange {
return TimeRange{
Start: t.Start.Truncate(d),
End: t.End.Truncate(d),
}
}
type TimeValuesSequence interface {
Reset()
Next() bool
Values() Values
ValueType() models.FieldType
}
type Values interface {
MinTime() int64
MaxTime() int64
Encode([]byte) ([]byte, error)
}
type cache struct {
key []byte
tags models.Tags
}
type seriesGenerator struct {
2020-04-24 16:47:22 +00:00
name []byte
tags TagsSequence
field []byte
vg TimeValuesSequence
n int64
c cache
}
2020-04-24 16:47:22 +00:00
func NewSeriesGenerator(name []byte, field []byte, vg TimeValuesSequence, tags TagsSequence) SeriesGenerator {
return NewSeriesGeneratorLimit(name, field, vg, tags, math.MaxInt64)
}
2020-04-24 16:47:22 +00:00
func NewSeriesGeneratorLimit(name []byte, field []byte, vg TimeValuesSequence, tags TagsSequence, n int64) SeriesGenerator {
return &seriesGenerator{
2020-04-24 16:47:22 +00:00
name: name,
field: field,
tags: tags,
vg: vg,
n: n,
}
}
func (g *seriesGenerator) Next() bool {
if g.n > 0 {
g.n--
if g.tags.Next() {
g.c = cache{}
g.vg.Reset()
return true
}
g.n = 0
}
return false
}
func (g *seriesGenerator) Key() []byte {
if len(g.c.key) == 0 {
2020-04-24 16:47:22 +00:00
g.c.key = models.MakeKey(g.name, g.tags.Value())
}
return g.c.key
}
2020-04-24 16:47:22 +00:00
func (g *seriesGenerator) Name() []byte {
return g.name
}
func (g *seriesGenerator) Tags() models.Tags {
if len(g.c.tags) == 0 {
g.c.tags = g.tags.Value().Clone()
}
return g.c.tags
}
func (g *seriesGenerator) Field() []byte {
return g.field
}
func (g *seriesGenerator) FieldType() models.FieldType {
return g.vg.ValueType()
}
func (g *seriesGenerator) TimeValuesGenerator() TimeValuesSequence {
return g.vg
}