2019-03-13 00:10:38 +00:00
|
|
|
package gen
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
|
|
|
"time"
|
|
|
|
|
2020-07-28 22:59:11 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/models"
|
2019-03-13 00:10:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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
|
2019-03-13 00:10:38 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
|
2019-03-18 23:47:59 +00:00
|
|
|
// FieldType returns the data type for the field.
|
|
|
|
FieldType() models.FieldType
|
|
|
|
|
2019-03-13 00:10:38 +00:00
|
|
|
// TimeValuesGenerator returns a values sequence for the current series.
|
|
|
|
TimeValuesGenerator() TimeValuesSequence
|
|
|
|
}
|
|
|
|
|
|
|
|
type TimeSequenceSpec struct {
|
2019-03-18 23:49:04 +00:00
|
|
|
// Count specifies the maximum number of values to generate.
|
2019-03-13 00:10:38 +00:00
|
|
|
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.
|
2019-03-13 00:10:38 +00:00
|
|
|
Delta time.Duration
|
|
|
|
|
|
|
|
// Precision specifies the precision of timestamp intervals
|
|
|
|
Precision time.Duration
|
|
|
|
}
|
|
|
|
|
2019-03-18 23:49:04 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-03-13 00:10:38 +00:00
|
|
|
type TimeRange struct {
|
|
|
|
Start time.Time
|
|
|
|
End time.Time
|
|
|
|
}
|
|
|
|
|
2019-03-18 23:49:04 +00:00
|
|
|
func (t TimeRange) Truncate(d time.Duration) TimeRange {
|
|
|
|
return TimeRange{
|
|
|
|
Start: t.Start.Truncate(d),
|
|
|
|
End: t.End.Truncate(d),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 00:10:38 +00:00
|
|
|
type TimeValuesSequence interface {
|
|
|
|
Reset()
|
|
|
|
Next() bool
|
|
|
|
Values() Values
|
2019-03-18 23:47:59 +00:00
|
|
|
ValueType() models.FieldType
|
2019-03-13 00:10:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2019-03-13 00:10:38 +00:00
|
|
|
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)
|
2019-03-13 00:10:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 16:47:22 +00:00
|
|
|
func NewSeriesGeneratorLimit(name []byte, field []byte, vg TimeValuesSequence, tags TagsSequence, n int64) SeriesGenerator {
|
2019-03-13 00:10:38 +00:00
|
|
|
return &seriesGenerator{
|
2020-04-24 16:47:22 +00:00
|
|
|
name: name,
|
2019-03-13 00:10:38 +00:00
|
|
|
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())
|
2019-03-13 00:10:38 +00:00
|
|
|
}
|
|
|
|
return g.c.key
|
|
|
|
}
|
|
|
|
|
2020-04-24 16:47:22 +00:00
|
|
|
func (g *seriesGenerator) Name() []byte {
|
|
|
|
return g.name
|
2019-03-13 00:10:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-03-18 23:47:59 +00:00
|
|
|
func (g *seriesGenerator) FieldType() models.FieldType {
|
|
|
|
return g.vg.ValueType()
|
|
|
|
}
|
|
|
|
|
2019-03-13 00:10:38 +00:00
|
|
|
func (g *seriesGenerator) TimeValuesGenerator() TimeValuesSequence {
|
|
|
|
return g.vg
|
|
|
|
}
|