package storageflux import ( "sync" "github.com/influxdata/flux" "github.com/influxdata/flux/arrow" "github.com/influxdata/flux/execute" "github.com/influxdata/flux/memory" "github.com/influxdata/influxdb/models" storage "github.com/influxdata/influxdb/storage/reads" "github.com/influxdata/influxdb/tsdb/cursors" "github.com/pkg/errors" ) {{range .}} // // *********** {{.Name}} *********** // type {{.name}}Table struct { table mu sync.Mutex cur cursors.{{.Name}}ArrayCursor alloc *memory.Allocator } func new{{.Name}}Table( done chan struct{}, cur cursors.{{.Name}}ArrayCursor, bounds execute.Bounds, key flux.GroupKey, cols []flux.ColMeta, tags models.Tags, defs [][]byte, cache *tagsCache, alloc *memory.Allocator, ) *{{.name}}Table { t := &{{.name}}Table{ table: newTable(done, bounds, key, cols, defs, cache, alloc), cur: cur, } t.readTags(tags) t.advance() return t } func (t *{{.name}}Table) Close() { t.mu.Lock() if t.cur != nil { t.cur.Close() t.cur = nil } t.mu.Unlock() } func (t *{{.name}}Table) Statistics() cursors.CursorStats { t.mu.Lock() defer t.mu.Unlock() cur := t.cur if cur == nil { return cursors.CursorStats{} } cs := cur.Stats() return cursors.CursorStats{ ScannedValues: cs.ScannedValues, ScannedBytes: cs.ScannedBytes, } } func (t *{{.name}}Table) Do(f func(flux.ColReader) error) error { return t.do(f, t.advance) } func (t *{{.name}}Table) advance() bool { a := t.cur.Next() l := a.Len() if l == 0 { return false } // Retrieve the buffer for the data to avoid allocating // additional slices. If the buffer is still being used // because the references were retained, then we will // allocate a new buffer. cr := t.allocateBuffer(l) cr.cols[timeColIdx] = arrow.NewInt(a.Timestamps, t.alloc) cr.cols[valueColIdx] = t.toArrowBuffer(a.Values) t.appendTags(cr) t.appendBounds(cr) return true } // group table type {{.name}}GroupTable struct { table mu sync.Mutex gc storage.GroupCursor cur cursors.{{.Name}}ArrayCursor } func new{{.Name}}GroupTable( done chan struct{}, gc storage.GroupCursor, cur cursors.{{.Name}}ArrayCursor, bounds execute.Bounds, key flux.GroupKey, cols []flux.ColMeta, tags models.Tags, defs [][]byte, cache *tagsCache, alloc *memory.Allocator, ) *{{.name}}GroupTable { t := &{{.name}}GroupTable{ table: newTable(done, bounds, key, cols, defs, cache, alloc), gc: gc, cur: cur, } t.readTags(tags) t.advance() return t } func (t *{{.name}}GroupTable) Close() { t.mu.Lock() if t.cur != nil { t.cur.Close() t.cur = nil } if t.gc != nil { t.gc.Close() t.gc = nil } t.mu.Unlock() } func (t *{{.name}}GroupTable) Do(f func(flux.ColReader) error) error { return t.do(f, t.advance) } func (t *{{.name}}GroupTable) advance() bool { RETRY: a := t.cur.Next() l := a.Len() if l == 0 { if t.advanceCursor() { goto RETRY } return false } // Retrieve the buffer for the data to avoid allocating // additional slices. If the buffer is still being used // because the references were retained, then we will // allocate a new buffer. cr := t.allocateBuffer(l) cr.cols[timeColIdx] = arrow.NewInt(a.Timestamps, t.alloc) cr.cols[valueColIdx] = t.toArrowBuffer(a.Values) t.appendTags(cr) t.appendBounds(cr) return true } func (t *{{.name}}GroupTable) advanceCursor() bool { t.cur.Close() t.cur = nil for t.gc.Next() { cur := t.gc.Cursor() if cur == nil { continue } if typedCur, ok := cur.(cursors.{{.Name}}ArrayCursor); !ok { // TODO(sgc): error or skip? cur.Close() t.err = errors.Errorf("expected {{.name}} cursor type, got %T", cur) return false } else { t.readTags(t.gc.Tags()) t.cur = typedCur return true } } return false } func (t *{{.name}}GroupTable) Statistics() cursors.CursorStats { if t.cur == nil { return cursors.CursorStats{} } cs := t.cur.Stats() return cursors.CursorStats{ ScannedValues: cs.ScannedValues, ScannedBytes: cs.ScannedBytes, } } {{end}}