339 lines
7.6 KiB
Cheetah
339 lines
7.6 KiB
Cheetah
package tsm1
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/influxdata/influxdb/tsdb"
|
|
"github.com/influxdata/influxdb/tsdb/cursors"
|
|
)
|
|
|
|
// Array Cursors
|
|
|
|
{{range .}}
|
|
{{$arrayType := print "*tsdb." .Name "Array"}}
|
|
{{$type := print .name "ArrayAscendingCursor"}}
|
|
{{$Type := print .Name "ArrayAscendingCursor"}}
|
|
|
|
type {{$type}} struct {
|
|
cache struct {
|
|
values Values
|
|
pos int
|
|
}
|
|
|
|
tsm struct {
|
|
buf {{$arrayType}}
|
|
values {{$arrayType}}
|
|
pos int
|
|
keyCursor *KeyCursor
|
|
}
|
|
|
|
end int64
|
|
res {{$arrayType}}
|
|
stats cursors.CursorStats
|
|
}
|
|
|
|
func new{{$Type}}() *{{$type}} {
|
|
c := &{{$type}}{
|
|
res: tsdb.New{{.Name}}ArrayLen(MaxPointsPerBlock),
|
|
}
|
|
c.tsm.buf = tsdb.New{{.Name}}ArrayLen(MaxPointsPerBlock)
|
|
return c
|
|
}
|
|
|
|
func (c *{{$type}}) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
|
|
c.end = end
|
|
c.cache.values = cacheValues
|
|
c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
|
|
return c.cache.values[i].UnixNano() >= seek
|
|
})
|
|
|
|
c.tsm.keyCursor = tsmKeyCursor
|
|
c.tsm.values = c.readArrayBlock()
|
|
c.tsm.pos = sort.Search(c.tsm.values.Len(), func(i int) bool {
|
|
return c.tsm.values.Timestamps[i] >= seek
|
|
})
|
|
}
|
|
|
|
func (c *{{$type}}) Err() error { return nil }
|
|
|
|
// close closes the cursor and any dependent cursors.
|
|
func (c *{{$type}}) Close() {
|
|
if c.tsm.keyCursor != nil {
|
|
c.tsm.keyCursor.Close()
|
|
c.tsm.keyCursor = nil
|
|
}
|
|
c.cache.values = nil
|
|
c.tsm.values = nil
|
|
}
|
|
|
|
func (c *{{$type}}) Stats() cursors.CursorStats { return c.stats }
|
|
|
|
// Next returns the next key/value for the cursor.
|
|
func (c *{{$type}}) Next() {{$arrayType}} {
|
|
pos := 0
|
|
cvals := c.cache.values
|
|
tvals := c.tsm.values
|
|
|
|
c.res.Timestamps = c.res.Timestamps[:cap(c.res.Timestamps)]
|
|
c.res.Values = c.res.Values[:cap(c.res.Values)]
|
|
|
|
for pos < len(c.res.Timestamps) && c.tsm.pos < len(tvals.Timestamps) && c.cache.pos < len(cvals) {
|
|
ckey := cvals[c.cache.pos].UnixNano()
|
|
tkey := tvals.Timestamps[c.tsm.pos]
|
|
if ckey == tkey {
|
|
c.res.Timestamps[pos] = ckey
|
|
c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue()
|
|
c.cache.pos++
|
|
c.tsm.pos++
|
|
} else if ckey < tkey {
|
|
c.res.Timestamps[pos] = ckey
|
|
c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue()
|
|
c.cache.pos++
|
|
} else {
|
|
c.res.Timestamps[pos] = tkey
|
|
c.res.Values[pos] = tvals.Values[c.tsm.pos]
|
|
c.tsm.pos++
|
|
}
|
|
|
|
pos++
|
|
|
|
if c.tsm.pos >= len(tvals.Timestamps) {
|
|
tvals = c.nextTSM()
|
|
}
|
|
}
|
|
|
|
if pos < len(c.res.Timestamps) {
|
|
if c.tsm.pos < len(tvals.Timestamps) {
|
|
if pos == 0 {
|
|
// optimization: all points served from TSM data
|
|
copy(c.res.Timestamps, tvals.Timestamps)
|
|
pos += copy(c.res.Values, tvals.Values)
|
|
c.nextTSM()
|
|
} else {
|
|
// copy as much as we can
|
|
n := copy(c.res.Timestamps[pos:], tvals.Timestamps[c.tsm.pos:])
|
|
copy(c.res.Values[pos:], tvals.Values[c.tsm.pos:])
|
|
pos += n
|
|
c.tsm.pos += n
|
|
if c.tsm.pos >= len(tvals.Timestamps) {
|
|
c.nextTSM()
|
|
}
|
|
}
|
|
}
|
|
|
|
if c.cache.pos < len(cvals) {
|
|
// TSM was exhausted
|
|
for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) {
|
|
c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano()
|
|
c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue()
|
|
pos++
|
|
c.cache.pos++
|
|
}
|
|
}
|
|
}
|
|
|
|
if pos > 0 && c.res.Timestamps[pos-1] > c.end {
|
|
pos -= 2
|
|
for pos >= 0 && c.res.Timestamps[pos] > c.end {
|
|
pos--
|
|
}
|
|
pos++
|
|
}
|
|
|
|
c.res.Timestamps = c.res.Timestamps[:pos]
|
|
c.res.Values = c.res.Values[:pos]
|
|
|
|
c.stats.ScannedValues += len(c.res.Values)
|
|
{{if eq .Name "String" }}
|
|
for _, v := range c.res.Values {
|
|
c.stats.ScannedBytes += len(v)
|
|
}
|
|
{{else}}
|
|
c.stats.ScannedBytes += len(c.res.Values) * {{.Size}}
|
|
{{end}}
|
|
|
|
return c.res
|
|
}
|
|
|
|
func (c *{{$type}}) nextTSM() {{$arrayType}} {
|
|
c.tsm.keyCursor.Next()
|
|
c.tsm.values = c.readArrayBlock()
|
|
c.tsm.pos = 0
|
|
return c.tsm.values
|
|
}
|
|
|
|
func (c *{{$type}}) readArrayBlock() {{$arrayType}} {
|
|
values, _ := c.tsm.keyCursor.Read{{.Name}}ArrayBlock(c.tsm.buf)
|
|
return values
|
|
}
|
|
|
|
{{$type := print .name "ArrayDescendingCursor"}}
|
|
{{$Type := print .Name "ArrayDescendingCursor"}}
|
|
|
|
type {{$type}} struct {
|
|
cache struct {
|
|
values Values
|
|
pos int
|
|
}
|
|
|
|
tsm struct {
|
|
buf {{$arrayType}}
|
|
values {{$arrayType}}
|
|
pos int
|
|
keyCursor *KeyCursor
|
|
}
|
|
|
|
end int64
|
|
res {{$arrayType}}
|
|
stats cursors.CursorStats
|
|
}
|
|
|
|
func new{{$Type}}() *{{$type}} {
|
|
c := &{{$type}}{
|
|
res: tsdb.New{{.Name}}ArrayLen(MaxPointsPerBlock),
|
|
}
|
|
c.tsm.buf = tsdb.New{{.Name}}ArrayLen(MaxPointsPerBlock)
|
|
return c
|
|
}
|
|
|
|
func (c *{{$type}}) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
|
|
c.end = end
|
|
c.cache.values = cacheValues
|
|
if len(c.cache.values) > 0 {
|
|
c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
|
|
return c.cache.values[i].UnixNano() >= seek
|
|
})
|
|
if c.cache.pos == len(c.cache.values) {
|
|
c.cache.pos--
|
|
} else if c.cache.values[c.cache.pos].UnixNano() != seek {
|
|
c.cache.pos--
|
|
}
|
|
} else {
|
|
c.cache.pos = -1
|
|
}
|
|
|
|
c.tsm.keyCursor = tsmKeyCursor
|
|
c.tsm.values = c.readArrayBlock()
|
|
c.tsm.pos = sort.Search(c.tsm.values.Len(), func(i int) bool {
|
|
return c.tsm.values.Timestamps[i] >= seek
|
|
})
|
|
if c.tsm.values.Len() > 0 {
|
|
if c.tsm.pos == c.tsm.values.Len() {
|
|
c.tsm.pos--
|
|
} else if c.tsm.values.Timestamps[c.tsm.pos] != seek {
|
|
c.tsm.pos--
|
|
}
|
|
} else {
|
|
c.tsm.pos = -1
|
|
}
|
|
}
|
|
|
|
func (c *{{$type}}) Err() error { return nil }
|
|
|
|
func (c *{{$type}}) Close() {
|
|
if c.tsm.keyCursor != nil {
|
|
c.tsm.keyCursor.Close()
|
|
c.tsm.keyCursor = nil
|
|
}
|
|
c.cache.values = nil
|
|
c.tsm.values = nil
|
|
}
|
|
|
|
func (c *{{$type}}) Stats() cursors.CursorStats { return c.stats }
|
|
|
|
func (c *{{$type}}) Next() {{$arrayType}} {
|
|
pos := 0
|
|
cvals := c.cache.values
|
|
tvals := c.tsm.values
|
|
|
|
c.res.Timestamps = c.res.Timestamps[:cap(c.res.Timestamps)]
|
|
c.res.Values = c.res.Values[:cap(c.res.Values)]
|
|
|
|
for pos < len(c.res.Timestamps) && c.tsm.pos >= 0 && c.cache.pos >= 0 {
|
|
ckey := cvals[c.cache.pos].UnixNano()
|
|
tkey := tvals.Timestamps[c.tsm.pos]
|
|
if ckey == tkey {
|
|
c.res.Timestamps[pos] = ckey
|
|
c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue()
|
|
c.cache.pos--
|
|
c.tsm.pos--
|
|
} else if ckey > tkey {
|
|
c.res.Timestamps[pos] = ckey
|
|
c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue()
|
|
c.cache.pos--
|
|
} else {
|
|
c.res.Timestamps[pos] = tkey
|
|
c.res.Values[pos] = tvals.Values[c.tsm.pos]
|
|
c.tsm.pos--
|
|
}
|
|
|
|
pos++
|
|
|
|
if c.tsm.pos < 0 {
|
|
tvals = c.nextTSM()
|
|
}
|
|
}
|
|
|
|
if pos < len(c.res.Timestamps) {
|
|
// cache was exhausted
|
|
if c.tsm.pos >= 0 {
|
|
for pos < len(c.res.Timestamps) && c.tsm.pos >= 0 {
|
|
c.res.Timestamps[pos] = tvals.Timestamps[c.tsm.pos]
|
|
c.res.Values[pos] = tvals.Values[c.tsm.pos]
|
|
pos++
|
|
c.tsm.pos--
|
|
if c.tsm.pos < 0 {
|
|
tvals = c.nextTSM()
|
|
}
|
|
}
|
|
}
|
|
|
|
if c.cache.pos >= 0 {
|
|
// TSM was exhausted
|
|
for pos < len(c.res.Timestamps) && c.cache.pos >= 0 {
|
|
c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano()
|
|
c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue()
|
|
pos++
|
|
c.cache.pos--
|
|
}
|
|
}
|
|
}
|
|
|
|
if pos > 0 && c.res.Timestamps[pos-1] < c.end {
|
|
pos -= 2
|
|
for pos >= 0 && c.res.Timestamps[pos] < c.end {
|
|
pos--
|
|
}
|
|
pos++
|
|
}
|
|
|
|
c.res.Timestamps = c.res.Timestamps[:pos]
|
|
c.res.Values = c.res.Values[:pos]
|
|
|
|
return c.res
|
|
}
|
|
|
|
func (c *{{$type}}) nextTSM() {{$arrayType}} {
|
|
c.tsm.keyCursor.Next()
|
|
c.tsm.values = c.readArrayBlock()
|
|
c.tsm.pos = len(c.tsm.values.Timestamps) - 1
|
|
return c.tsm.values
|
|
}
|
|
|
|
func (c *{{$type}}) readArrayBlock() {{$arrayType}} {
|
|
values, _ := c.tsm.keyCursor.Read{{.Name}}ArrayBlock(c.tsm.buf)
|
|
|
|
c.stats.ScannedValues += len(values.Values)
|
|
{{if eq .Name "String" }}
|
|
for _, v := range values.Values {
|
|
c.stats.ScannedBytes += len(v)
|
|
}
|
|
{{else}}
|
|
c.stats.ScannedBytes += len(values.Values) * {{.Size}}
|
|
{{end}}
|
|
|
|
return values
|
|
}
|
|
|
|
{{end}}
|