func (c *floatDescendingCursor) peekCache() (t int64, v float64) {
	if c.cache.pos < 0 || c.cache.pos >= len(c.cache.values) {
		return tsdb.EOF, 0
	}
	item := c.cache.values[c.cache.pos]
	return item.UnixNano(), item.(FloatValue).value
}
peekCache returns the current time/value from the cache.
package tsm1
import (
	"fmt"
	"runtime"
	"sort"
	"sync"
	"github.com/influxdata/influxdb/pkg/metrics"
	"github.com/influxdata/influxdb/pkg/tracing"
	"github.com/influxdata/influxdb/pkg/tracing/fields"
	"github.com/influxdata/influxdb/query"
	"github.com/influxdata/influxdb/tsdb"
	"github.com/influxdata/influxql"
	"go.uber.org/zap"
)
type cursor interface {
	close() error
	next() (t int64, v interface{})
}
type cursorAt interface {
	close() error
	peek() (k int64, v interface{})
	nextAt(seek int64) interface{}
}
type nilCursor struct{}
func (nilCursor) next() (int64, interface{}) { return tsdb.EOF, nil }
func (nilCursor) close() error               { return nil }
type bufCursor struct {
	cur cursor
	buf struct {
		key    int64
		value  interface{}
		filled bool
	}
	ascending bool
}
func newBufCursor(cur cursor, ascending bool) *bufCursor {
	return &bufCursor{cur: cur, ascending: ascending}
}
func (c *bufCursor) close() error {
	if c.cur == nil {
		return nil
	}
	err := c.cur.close()
	c.cur = nil
	return err
}
func (c *bufCursor) next() (int64, interface{}) {
	if c.buf.filled {
		k, v := c.buf.key, c.buf.value
		c.buf.filled = false
		return k, v
	}
	return c.cur.next()
}
func (c *bufCursor) unread(k int64, v interface{}) {
	c.buf.key, c.buf.value = k, v
	c.buf.filled = true
}
func (c *bufCursor) peek() (k int64, v interface{}) {
	k, v = c.next()
	c.unread(k, v)
	return
}
func (c *bufCursor) nextAt(seek int64) interface{} {
	for {
		k, v := c.next()
		if k != tsdb.EOF {
			if k == seek {
				return v
			} else if c.ascending && k < seek {
				continue
			} else if !c.ascending && k > seek {
				continue
			}
			c.unread(k, v)
		}
		switch c.cur.(type) {
		case floatCursor:
			return (*float64)(nil)
		case integerCursor:
			return (*int64)(nil)
		case unsignedCursor:
			return (*uint64)(nil)
		case stringCursor:
			return (*string)(nil)
		case booleanCursor:
			return (*bool)(nil)
		default:
			panic("unreachable")
		}
	}
}
const statsBufferCopyIntervalN = 100
type floatFinalizerIterator struct {
	query.FloatIterator
	logger *zap.Logger
}
func newFloatFinalizerIterator(inner query.FloatIterator, logger *zap.Logger) *floatFinalizerIterator {
	itr := &floatFinalizerIterator{FloatIterator: inner, logger: logger}
	runtime.SetFinalizer(itr, (*floatFinalizerIterator).closeGC)
	return itr
}
func (itr *floatFinalizerIterator) closeGC() {
	go func() {
		itr.logger.Error("FloatIterator finalized by GC")
		itr.Close()
	}()
}
func (itr *floatFinalizerIterator) Close() error {
	runtime.SetFinalizer(itr, nil)
	return itr.FloatIterator.Close()
}
type floatInstrumentedIterator struct {
	query.FloatIterator
	span  *tracing.Span
	group *metrics.Group
}
func newFloatInstrumentedIterator(inner query.FloatIterator, span *tracing.Span, group *metrics.Group) *floatInstrumentedIterator {
	return &floatInstrumentedIterator{FloatIterator: inner, span: span, group: group}
}
func (itr *floatInstrumentedIterator) Close() error {
	var f fields.Fields
	itr.group.ForEach(func(v metrics.Metric) {
		switch m := v.(type) {
		case *metrics.Counter:
			f = append(f, fields.Int64(m.Name(), m.Value()))
		case *metrics.Timer:
			f = append(f, fields.Duration(m.Name(), m.Value()))
		default:
			panic("unexpected metrics")
		}
	})
	itr.span.SetFields(f)
	itr.span.Finish()
	return itr.FloatIterator.Close()
}
type floatIterator struct {
	cur   floatCursor
	aux   []cursorAt
	conds struct {
		names []string
		curs  []cursorAt
	}
	opt query.IteratorOptions
	m     map[string]interface{}  
	point query.FloatPoint        
	statsLock sync.Mutex
	stats     query.IteratorStats
	statsBuf  query.IteratorStats
}
func newFloatIterator(name string, tags query.Tags, opt query.IteratorOptions, cur floatCursor, aux []cursorAt, conds []cursorAt, condNames []string) *floatIterator {
	itr := &floatIterator{
		cur: cur,
		aux: aux,
		opt: opt,
		point: query.FloatPoint{
			Name: name,
			Tags: tags,
		},
		statsBuf: query.IteratorStats{
			SeriesN: 1,
		},
	}
	itr.stats = itr.statsBuf
	if len(aux) > 0 {
		itr.point.Aux = make([]interface{}, len(aux))
	}
	if opt.Condition != nil {
		itr.m = make(map[string]interface{}, len(aux)+len(conds))
	}
	itr.conds.names = condNames
	itr.conds.curs = conds
	return itr
}
func (itr *floatIterator) Next() (*query.FloatPoint, error) {
	for {
		seek := tsdb.EOF
		if itr.cur != nil {
			itr.point.Time, itr.point.Value = itr.cur.nextFloat()
			seek = itr.point.Time
		} else {
			for i := range itr.aux {
				if k, _ := itr.aux[i].peek(); k != tsdb.EOF {
					if seek == tsdb.EOF || (itr.opt.Ascending && k < seek) || (!itr.opt.Ascending && k > seek) {
						seek = k
					}
				}
			}
			itr.point.Time = seek
		}
		if itr.point.Time == tsdb.EOF {
			itr.copyStats()
			return nil, nil
		} else if itr.opt.Ascending && itr.point.Time > itr.opt.EndTime {
			itr.copyStats()
			return nil, nil
		} else if !itr.opt.Ascending && itr.point.Time < itr.opt.StartTime {
			itr.copyStats()
			return nil, nil
		}
		for i := range itr.opt.Aux {
			itr.point.Aux[i] = itr.aux[i].nextAt(seek)
		}
		for i := range itr.conds.curs {
			itr.m[itr.conds.names[i]] = itr.conds.curs[i].nextAt(seek)
		}
		if itr.opt.Condition != nil && !influxql.EvalBool(itr.opt.Condition, itr.m) {
			continue
		}
		itr.statsBuf.PointN++
		if itr.statsBuf.PointN%statsBufferCopyIntervalN == 0 {
			itr.copyStats()
		}
		return &itr.point, nil
	}
}
func (itr *floatIterator) copyStats() {
	itr.statsLock.Lock()
	itr.stats = itr.statsBuf
	itr.statsLock.Unlock()
}
func (itr *floatIterator) Stats() query.IteratorStats {
	itr.statsLock.Lock()
	stats := itr.stats
	itr.statsLock.Unlock()
	return stats
}
func (itr *floatIterator) Close() error {
	cursorsAt(itr.aux).close()
	itr.aux = nil
	cursorsAt(itr.conds.curs).close()
	itr.conds.curs = nil
	if itr.cur != nil {
		err := itr.cur.close()
		itr.cur = nil
		return err
	}
	return nil
}
type floatLimitIterator struct {
	input query.FloatIterator
	opt   query.IteratorOptions
	n     int
}
func newFloatLimitIterator(input query.FloatIterator, opt query.IteratorOptions) *floatLimitIterator {
	return &floatLimitIterator{
		input: input,
		opt:   opt,
	}
}
func (itr *floatLimitIterator) Stats() query.IteratorStats { return itr.input.Stats() }
func (itr *floatLimitIterator) Close() error               { return itr.input.Close() }
func (itr *floatLimitIterator) Next() (*query.FloatPoint, error) {
	if (itr.n - itr.opt.Offset) > itr.opt.Limit {
		return nil, nil
	}
	p, err := itr.input.Next()
	if p == nil || err != nil {
		return nil, err
	}
	itr.n++
	return p, nil
}
type floatCursor interface {
	cursor
	nextFloat() (t int64, v float64)
}
func newFloatCursor(seek int64, ascending bool, cacheValues Values, tsmKeyCursor *KeyCursor) floatCursor {
	if ascending {
		return newFloatAscendingCursor(seek, cacheValues, tsmKeyCursor)
	}
	return newFloatDescendingCursor(seek, cacheValues, tsmKeyCursor)
}
type floatAscendingCursor struct {
	cache struct {
		values Values
		pos    int
	}
	tsm struct {
		values    []FloatValue
		pos       int
		keyCursor *KeyCursor
	}
}
func newFloatAscendingCursor(seek int64, cacheValues Values, tsmKeyCursor *KeyCursor) *floatAscendingCursor {
	c := &floatAscendingCursor{}
	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.tsm.keyCursor.ReadFloatBlock(&c.tsm.values)
	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
		return c.tsm.values[i].UnixNano() >= seek
	})
	return c
}
func (c *floatAscendingCursor) peekCache() (t int64, v float64) {
	if c.cache.pos >= len(c.cache.values) {
		return tsdb.EOF, 0
	}
	item := c.cache.values[c.cache.pos]
	return item.UnixNano(), item.(FloatValue).value
}
func (c *floatAscendingCursor) peekTSM() (t int64, v float64) {
	if c.tsm.pos < 0 || c.tsm.pos >= len(c.tsm.values) {
		return tsdb.EOF, 0
	}
	item := c.tsm.values[c.tsm.pos]
	return item.UnixNano(), item.value
}
func (c *floatAscendingCursor) close() error {
	if c.tsm.keyCursor == nil {
		return nil
	}
	c.tsm.keyCursor.Close()
	c.tsm.keyCursor = nil
	c.cache.values = nil
	c.tsm.values = nil
	return nil
}
func (c *floatAscendingCursor) next() (int64, interface{}) { return c.nextFloat() }
func (c *floatAscendingCursor) nextFloat() (int64, float64) {
	ckey, cvalue := c.peekCache()
	tkey, tvalue := c.peekTSM()
	if ckey == tsdb.EOF && tkey == tsdb.EOF {
		return tsdb.EOF, 0
	}
	if ckey == tkey {
		c.nextCache()
		c.nextTSM()
		return ckey, cvalue
	}
	if ckey != tsdb.EOF && (ckey < tkey || tkey == tsdb.EOF) {
		c.nextCache()
		return ckey, cvalue
	}
	c.nextTSM()
	return tkey, tvalue
}
func (c *floatAscendingCursor) nextCache() {
	if c.cache.pos >= len(c.cache.values) {
		return
	}
	c.cache.pos++
}
func (c *floatAscendingCursor) nextTSM() {
	c.tsm.pos++
	if c.tsm.pos >= len(c.tsm.values) {
		c.tsm.keyCursor.Next()
		c.tsm.values, _ = c.tsm.keyCursor.ReadFloatBlock(&c.tsm.values)
		if len(c.tsm.values) == 0 {
			return
		}
		c.tsm.pos = 0
	}
}
type floatDescendingCursor struct {
	cache struct {
		values Values
		pos    int
	}
	tsm struct {
		values    []FloatValue
		pos       int
		keyCursor *KeyCursor
	}
}
func newFloatDescendingCursor(seek int64, cacheValues Values, tsmKeyCursor *KeyCursor) *floatDescendingCursor {
	c := &floatDescendingCursor{}
	c.cache.values = cacheValues
	c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
		return c.cache.values[i].UnixNano() >= seek
	})
	if t, _ := c.peekCache(); t != seek {
		c.cache.pos--
	}
	c.tsm.keyCursor = tsmKeyCursor
	c.tsm.values, _ = c.tsm.keyCursor.ReadFloatBlock(&c.tsm.values)
	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
		return c.tsm.values[i].UnixNano() >= seek
	})
	if t, _ := c.peekTSM(); t != seek {
		c.tsm.pos--
	}
	return c
}