1package gen 2 3import ( 4 "math" 5 "time" 6 7 "github.com/influxdata/influxdb/models" 8) 9 10type SeriesGenerator interface { 11 // Next advances the series generator to the next series key. 12 Next() bool 13 14 // Key returns the series key. 15 // The returned value may be cached. 16 Key() []byte 17 18 // Name returns the name of the measurement. 19 // The returned value may be modified by a subsequent call to Next. 20 Name() []byte 21 22 // Tags returns the tag set. 23 // The returned value may be modified by a subsequent call to Next. 24 Tags() models.Tags 25 26 // Field returns the name of the field. 27 // The returned value may be modified by a subsequent call to Next. 28 Field() []byte 29 30 // TimeValuesGenerator returns a values sequence for the current series. 31 TimeValuesGenerator() TimeValuesSequence 32} 33 34type TimeSequenceSpec struct { 35 // Count specifies the maximum number of values to generate. 36 Count int 37 38 // Start specifies the starting time for the values. 39 Start time.Time 40 41 // Delta specifies the interval between time stamps. 42 Delta time.Duration 43 44 // Precision specifies the precision of timestamp intervals 45 Precision time.Duration 46} 47 48func (ts TimeSequenceSpec) ForTimeRange(tr TimeRange) TimeSequenceSpec { 49 // Truncate time range 50 if ts.Delta > 0 { 51 tr = tr.Truncate(ts.Delta) 52 } else { 53 tr = tr.Truncate(ts.Precision) 54 } 55 56 ts.Start = tr.Start 57 58 if ts.Delta > 0 { 59 intervals := int(tr.End.Sub(tr.Start) / ts.Delta) 60 if intervals > ts.Count { 61 // if the number of intervals in the specified time range exceeds 62 // the maximum count, move the start forward to limit the number of values 63 ts.Start = tr.End.Add(-time.Duration(ts.Count) * ts.Delta) 64 } else { 65 ts.Count = intervals 66 } 67 } else { 68 ts.Delta = tr.End.Sub(tr.Start) / time.Duration(ts.Count) 69 if ts.Delta < ts.Precision { 70 // count is too high for the range of time and precision 71 ts.Count = int(tr.End.Sub(tr.Start) / ts.Precision) 72 ts.Delta = ts.Precision 73 } else { 74 ts.Delta = ts.Delta.Round(ts.Precision) 75 } 76 ts.Precision = 0 77 } 78 79 return ts 80} 81 82type TimeRange struct { 83 Start time.Time 84 End time.Time 85} 86 87func (t TimeRange) Truncate(d time.Duration) TimeRange { 88 return TimeRange{ 89 Start: t.Start.Truncate(d), 90 End: t.End.Truncate(d), 91 } 92} 93 94type TimeValuesSequence interface { 95 Reset() 96 Next() bool 97 Values() Values 98} 99 100type Values interface { 101 MinTime() int64 102 MaxTime() int64 103 Encode([]byte) ([]byte, error) 104} 105 106type cache struct { 107 key []byte 108 tags models.Tags 109} 110 111type seriesGenerator struct { 112 name []byte 113 tags TagsSequence 114 field []byte 115 vg TimeValuesSequence 116 n int64 117 118 c cache 119} 120 121func NewSeriesGenerator(name []byte, field []byte, vg TimeValuesSequence, tags TagsSequence) SeriesGenerator { 122 return NewSeriesGeneratorLimit(name, field, vg, tags, math.MaxInt64) 123} 124 125func NewSeriesGeneratorLimit(name []byte, field []byte, vg TimeValuesSequence, tags TagsSequence, n int64) SeriesGenerator { 126 return &seriesGenerator{ 127 name: name, 128 field: field, 129 tags: tags, 130 vg: vg, 131 n: n, 132 } 133} 134 135func (g *seriesGenerator) Next() bool { 136 if g.n > 0 { 137 g.n-- 138 if g.tags.Next() { 139 g.c = cache{} 140 g.vg.Reset() 141 return true 142 } 143 g.n = 0 144 } 145 146 return false 147} 148 149func (g *seriesGenerator) Key() []byte { 150 if len(g.c.key) == 0 { 151 g.c.key = models.MakeKey(g.name, g.tags.Value()) 152 } 153 return g.c.key 154} 155 156func (g *seriesGenerator) Name() []byte { 157 return g.name 158} 159 160func (g *seriesGenerator) Tags() models.Tags { 161 if len(g.c.tags) == 0 { 162 g.c.tags = g.tags.Value().Clone() 163 } 164 return g.c.tags 165} 166 167func (g *seriesGenerator) Field() []byte { 168 return g.field 169} 170 171func (g *seriesGenerator) TimeValuesGenerator() TimeValuesSequence { 172 return g.vg 173} 174