1// Generated by tmpl
2// https://github.com/benbjohnson/tmpl
3//
4// DO NOT EDIT!
5// Source: batch_cursor.gen.go.tmpl
6
7package tsm1
8
9import (
10	"context"
11	"sort"
12
13	"github.com/influxdata/influxdb/query"
14	"github.com/influxdata/influxdb/tsdb"
15)
16
17// buildFloatCursor creates a cursor for a float field.
18func (e *Engine) buildFloatCursor(ctx context.Context, measurement, seriesKey, field string, opt query.IteratorOptions) floatCursor {
19	key := SeriesFieldKeyBytes(seriesKey, field)
20	cacheValues := e.Cache.Values(key)
21	keyCursor := e.KeyCursor(ctx, key, opt.SeekTime(), opt.Ascending)
22	return newFloatCursor(opt.SeekTime(), opt.Ascending, cacheValues, keyCursor)
23}
24
25// buildIntegerCursor creates a cursor for a integer field.
26func (e *Engine) buildIntegerCursor(ctx context.Context, measurement, seriesKey, field string, opt query.IteratorOptions) integerCursor {
27	key := SeriesFieldKeyBytes(seriesKey, field)
28	cacheValues := e.Cache.Values(key)
29	keyCursor := e.KeyCursor(ctx, key, opt.SeekTime(), opt.Ascending)
30	return newIntegerCursor(opt.SeekTime(), opt.Ascending, cacheValues, keyCursor)
31}
32
33// buildUnsignedCursor creates a cursor for a unsigned field.
34func (e *Engine) buildUnsignedCursor(ctx context.Context, measurement, seriesKey, field string, opt query.IteratorOptions) unsignedCursor {
35	key := SeriesFieldKeyBytes(seriesKey, field)
36	cacheValues := e.Cache.Values(key)
37	keyCursor := e.KeyCursor(ctx, key, opt.SeekTime(), opt.Ascending)
38	return newUnsignedCursor(opt.SeekTime(), opt.Ascending, cacheValues, keyCursor)
39}
40
41// buildStringCursor creates a cursor for a string field.
42func (e *Engine) buildStringCursor(ctx context.Context, measurement, seriesKey, field string, opt query.IteratorOptions) stringCursor {
43	key := SeriesFieldKeyBytes(seriesKey, field)
44	cacheValues := e.Cache.Values(key)
45	keyCursor := e.KeyCursor(ctx, key, opt.SeekTime(), opt.Ascending)
46	return newStringCursor(opt.SeekTime(), opt.Ascending, cacheValues, keyCursor)
47}
48
49// buildBooleanCursor creates a cursor for a boolean field.
50func (e *Engine) buildBooleanCursor(ctx context.Context, measurement, seriesKey, field string, opt query.IteratorOptions) booleanCursor {
51	key := SeriesFieldKeyBytes(seriesKey, field)
52	cacheValues := e.Cache.Values(key)
53	keyCursor := e.KeyCursor(ctx, key, opt.SeekTime(), opt.Ascending)
54	return newBooleanCursor(opt.SeekTime(), opt.Ascending, cacheValues, keyCursor)
55}
56
57// Cursors
58
59type floatAscendingBatchCursor struct {
60	cache struct {
61		values Values
62		pos    int
63	}
64
65	tsm struct {
66		buf       []FloatValue
67		values    []FloatValue
68		pos       int
69		keyCursor *KeyCursor
70	}
71
72	end int64
73	t   []int64
74	v   []float64
75}
76
77func newFloatAscendingBatchCursor() *floatAscendingBatchCursor {
78	return &floatAscendingBatchCursor{
79		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
80		v: make([]float64, tsdb.DefaultMaxPointsPerBlock),
81	}
82}
83
84func (c *floatAscendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
85	c.end = end
86	c.cache.values = cacheValues
87	c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
88		return c.cache.values[i].UnixNano() >= seek
89	})
90
91	c.tsm.keyCursor = tsmKeyCursor
92	c.tsm.values, _ = c.tsm.keyCursor.ReadFloatBlock(&c.tsm.buf)
93	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
94		return c.tsm.values[i].UnixNano() >= seek
95	})
96}
97
98func (c *floatAscendingBatchCursor) Err() error { return nil }
99
100// close closes the cursor and any dependent cursors.
101func (c *floatAscendingBatchCursor) Close() {
102	c.tsm.keyCursor.Close()
103	c.tsm.keyCursor = nil
104	c.cache.values = nil
105	c.tsm.values = nil
106}
107
108// Next returns the next key/value for the cursor.
109func (c *floatAscendingBatchCursor) Next() ([]int64, []float64) {
110	var ckey, tkey int64
111	var cvalue, tvalue float64
112
113	pos := 0
114	for ; pos < cap(c.t); pos++ {
115		tkey, tvalue = c.peekTSM()
116
117		if c.cache.pos < len(c.cache.values) {
118			ckey, cvalue = c.peekCache()
119
120			var cache, tsm bool
121
122			// Both cache and tsm files have the same key, cache takes precedence.
123			if ckey == tkey {
124				cache, tsm = true, true
125				tkey = ckey
126				tvalue = cvalue
127			} else if ckey < tkey || tkey == tsdb.EOF {
128				// Buffered cache key precedes that in TSM file.
129				cache = true
130				tkey = ckey
131				tvalue = cvalue
132			} else {
133				// Buffered TSM key precedes that in cache.
134				tsm = true
135			}
136
137			if cache {
138				c.nextCache()
139			}
140
141			if tsm {
142				c.nextTSM()
143			}
144		} else {
145			if tkey == tsdb.EOF {
146				break
147			}
148			c.nextTSM()
149		}
150
151		c.t[pos] = tkey
152		c.v[pos] = tvalue
153	}
154
155	if pos > 0 && c.t[pos-1] > c.end {
156		pos -= 2
157		for pos >= 0 && c.t[pos] > c.end {
158			pos--
159		}
160		pos++
161	}
162
163	return c.t[:pos], c.v[:pos]
164}
165
166// peekCache returns the current time/value from the cache.
167func (c *floatAscendingBatchCursor) peekCache() (t int64, v float64) {
168	item := c.cache.values[c.cache.pos]
169	return item.UnixNano(), item.(FloatValue).value
170}
171
172// nextCache returns the next value from the cache.
173func (c *floatAscendingBatchCursor) nextCache() {
174	if c.cache.pos < len(c.cache.values) {
175		c.cache.pos++
176	}
177}
178
179// peekTSM returns the current time/value from tsm.
180func (c *floatAscendingBatchCursor) peekTSM() (t int64, v float64) {
181	if c.tsm.pos >= len(c.tsm.values) {
182		return tsdb.EOF, 0
183	}
184
185	item := c.tsm.values[c.tsm.pos]
186	return item.UnixNano(), item.value
187}
188
189// nextTSM returns the next value from the TSM files.
190func (c *floatAscendingBatchCursor) nextTSM() {
191	c.tsm.pos++
192	if c.tsm.pos >= len(c.tsm.values) {
193		c.tsm.keyCursor.Next()
194		c.tsm.values, _ = c.tsm.keyCursor.ReadFloatBlock(&c.tsm.buf)
195		c.tsm.pos = 0
196	}
197}
198
199type floatDescendingBatchCursor struct {
200	cache struct {
201		values Values
202		pos    int
203	}
204
205	tsm struct {
206		buf       []FloatValue
207		values    []FloatValue
208		pos       int
209		keyCursor *KeyCursor
210	}
211
212	end int64
213	t   []int64
214	v   []float64
215}
216
217func newFloatDescendingBatchCursor() *floatDescendingBatchCursor {
218	return &floatDescendingBatchCursor{
219		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
220		v: make([]float64, tsdb.DefaultMaxPointsPerBlock),
221	}
222}
223
224func (c *floatDescendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
225	c.end = end
226	c.cache.values = cacheValues
227	if len(c.cache.values) > 0 {
228		c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
229			return c.cache.values[i].UnixNano() >= seek
230		})
231		if c.cache.pos == len(c.cache.values) {
232			c.cache.pos--
233		} else if t, _ := c.peekCache(); t != seek {
234			c.cache.pos--
235		}
236	} else {
237		c.cache.pos = -1
238	}
239
240	c.tsm.keyCursor = tsmKeyCursor
241	c.tsm.values, _ = c.tsm.keyCursor.ReadFloatBlock(&c.tsm.buf)
242	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
243		return c.tsm.values[i].UnixNano() >= seek
244	})
245	if len(c.tsm.values) > 0 {
246		if c.tsm.pos == len(c.tsm.values) {
247			c.tsm.pos--
248		} else if t, _ := c.peekTSM(); t != seek {
249			c.tsm.pos--
250		}
251	} else {
252		c.tsm.pos = -1
253	}
254}
255
256func (c *floatDescendingBatchCursor) Err() error { return nil }
257
258// close closes the cursor and any dependent cursors.
259func (c *floatDescendingBatchCursor) Close() {
260	c.tsm.keyCursor.Close()
261	c.tsm.keyCursor = nil
262	c.cache.values = nil
263	c.tsm.values = nil
264}
265
266// nextFloat returns the next key/value for the cursor.
267func (c *floatDescendingBatchCursor) Next() ([]int64, []float64) {
268	var ckey, tkey int64
269	var cvalue, tvalue float64
270
271	pos := 0
272	for ; pos < cap(c.t); pos++ {
273		tkey, tvalue = c.peekTSM()
274
275		if c.cache.pos >= 0 {
276			ckey, cvalue = c.peekCache()
277
278			var cache, tsm bool
279
280			// Both cache and tsm files have the same key, cache takes precedence.
281			if ckey == tkey {
282				cache, tsm = true, true
283				tkey = ckey
284				tvalue = cvalue
285			} else if ckey > tkey || tkey == tsdb.EOF {
286				// Buffered cache key succeeds that in TSM file.
287				cache = true
288				tkey = ckey
289				tvalue = cvalue
290			} else {
291				// Buffered TSM key succeeds that in cache.
292				tsm = true
293			}
294
295			if cache {
296				c.nextCache()
297			}
298
299			if tsm {
300				c.nextTSM()
301			}
302		} else {
303			if tkey == tsdb.EOF {
304				break
305			}
306			c.nextTSM()
307		}
308
309		c.t[pos] = tkey
310		c.v[pos] = tvalue
311	}
312
313	// strip out remaining points
314	if pos > 0 && c.t[pos-1] < c.end {
315		pos -= 2
316		for pos >= 0 && c.t[pos] < c.end {
317			pos--
318		}
319		pos++
320	}
321
322	return c.t[:pos], c.v[:pos]
323}
324
325// peekCache returns the current time/value from the cache.
326func (c *floatDescendingBatchCursor) peekCache() (t int64, v float64) {
327	item := c.cache.values[c.cache.pos]
328	return item.UnixNano(), item.(FloatValue).value
329}
330
331// nextCache returns the next value from the cache.
332func (c *floatDescendingBatchCursor) nextCache() {
333	if c.cache.pos >= 0 {
334		c.cache.pos--
335	}
336}
337
338// peekTSM returns the current time/value from tsm.
339func (c *floatDescendingBatchCursor) peekTSM() (t int64, v float64) {
340	if c.tsm.pos < 0 {
341		return tsdb.EOF, 0
342	}
343
344	item := c.tsm.values[c.tsm.pos]
345	return item.UnixNano(), item.value
346}
347
348// nextTSM returns the next value from the TSM files.
349func (c *floatDescendingBatchCursor) nextTSM() {
350	c.tsm.pos--
351	if c.tsm.pos < 0 {
352		c.tsm.keyCursor.Next()
353		c.tsm.values, _ = c.tsm.keyCursor.ReadFloatBlock(&c.tsm.buf)
354		c.tsm.pos = len(c.tsm.values) - 1
355	}
356}
357
358type integerAscendingBatchCursor struct {
359	cache struct {
360		values Values
361		pos    int
362	}
363
364	tsm struct {
365		buf       []IntegerValue
366		values    []IntegerValue
367		pos       int
368		keyCursor *KeyCursor
369	}
370
371	end int64
372	t   []int64
373	v   []int64
374}
375
376func newIntegerAscendingBatchCursor() *integerAscendingBatchCursor {
377	return &integerAscendingBatchCursor{
378		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
379		v: make([]int64, tsdb.DefaultMaxPointsPerBlock),
380	}
381}
382
383func (c *integerAscendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
384	c.end = end
385	c.cache.values = cacheValues
386	c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
387		return c.cache.values[i].UnixNano() >= seek
388	})
389
390	c.tsm.keyCursor = tsmKeyCursor
391	c.tsm.values, _ = c.tsm.keyCursor.ReadIntegerBlock(&c.tsm.buf)
392	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
393		return c.tsm.values[i].UnixNano() >= seek
394	})
395}
396
397func (c *integerAscendingBatchCursor) Err() error { return nil }
398
399// close closes the cursor and any dependent cursors.
400func (c *integerAscendingBatchCursor) Close() {
401	c.tsm.keyCursor.Close()
402	c.tsm.keyCursor = nil
403	c.cache.values = nil
404	c.tsm.values = nil
405}
406
407// Next returns the next key/value for the cursor.
408func (c *integerAscendingBatchCursor) Next() ([]int64, []int64) {
409	var ckey, tkey int64
410	var cvalue, tvalue int64
411
412	pos := 0
413	for ; pos < cap(c.t); pos++ {
414		tkey, tvalue = c.peekTSM()
415
416		if c.cache.pos < len(c.cache.values) {
417			ckey, cvalue = c.peekCache()
418
419			var cache, tsm bool
420
421			// Both cache and tsm files have the same key, cache takes precedence.
422			if ckey == tkey {
423				cache, tsm = true, true
424				tkey = ckey
425				tvalue = cvalue
426			} else if ckey < tkey || tkey == tsdb.EOF {
427				// Buffered cache key precedes that in TSM file.
428				cache = true
429				tkey = ckey
430				tvalue = cvalue
431			} else {
432				// Buffered TSM key precedes that in cache.
433				tsm = true
434			}
435
436			if cache {
437				c.nextCache()
438			}
439
440			if tsm {
441				c.nextTSM()
442			}
443		} else {
444			if tkey == tsdb.EOF {
445				break
446			}
447			c.nextTSM()
448		}
449
450		c.t[pos] = tkey
451		c.v[pos] = tvalue
452	}
453
454	if pos > 0 && c.t[pos-1] > c.end {
455		pos -= 2
456		for pos >= 0 && c.t[pos] > c.end {
457			pos--
458		}
459		pos++
460	}
461
462	return c.t[:pos], c.v[:pos]
463}
464
465// peekCache returns the current time/value from the cache.
466func (c *integerAscendingBatchCursor) peekCache() (t int64, v int64) {
467	item := c.cache.values[c.cache.pos]
468	return item.UnixNano(), item.(IntegerValue).value
469}
470
471// nextCache returns the next value from the cache.
472func (c *integerAscendingBatchCursor) nextCache() {
473	if c.cache.pos < len(c.cache.values) {
474		c.cache.pos++
475	}
476}
477
478// peekTSM returns the current time/value from tsm.
479func (c *integerAscendingBatchCursor) peekTSM() (t int64, v int64) {
480	if c.tsm.pos >= len(c.tsm.values) {
481		return tsdb.EOF, 0
482	}
483
484	item := c.tsm.values[c.tsm.pos]
485	return item.UnixNano(), item.value
486}
487
488// nextTSM returns the next value from the TSM files.
489func (c *integerAscendingBatchCursor) nextTSM() {
490	c.tsm.pos++
491	if c.tsm.pos >= len(c.tsm.values) {
492		c.tsm.keyCursor.Next()
493		c.tsm.values, _ = c.tsm.keyCursor.ReadIntegerBlock(&c.tsm.buf)
494		c.tsm.pos = 0
495	}
496}
497
498type integerDescendingBatchCursor struct {
499	cache struct {
500		values Values
501		pos    int
502	}
503
504	tsm struct {
505		buf       []IntegerValue
506		values    []IntegerValue
507		pos       int
508		keyCursor *KeyCursor
509	}
510
511	end int64
512	t   []int64
513	v   []int64
514}
515
516func newIntegerDescendingBatchCursor() *integerDescendingBatchCursor {
517	return &integerDescendingBatchCursor{
518		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
519		v: make([]int64, tsdb.DefaultMaxPointsPerBlock),
520	}
521}
522
523func (c *integerDescendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
524	c.end = end
525	c.cache.values = cacheValues
526	if len(c.cache.values) > 0 {
527		c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
528			return c.cache.values[i].UnixNano() >= seek
529		})
530		if c.cache.pos == len(c.cache.values) {
531			c.cache.pos--
532		} else if t, _ := c.peekCache(); t != seek {
533			c.cache.pos--
534		}
535	} else {
536		c.cache.pos = -1
537	}
538
539	c.tsm.keyCursor = tsmKeyCursor
540	c.tsm.values, _ = c.tsm.keyCursor.ReadIntegerBlock(&c.tsm.buf)
541	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
542		return c.tsm.values[i].UnixNano() >= seek
543	})
544	if len(c.tsm.values) > 0 {
545		if c.tsm.pos == len(c.tsm.values) {
546			c.tsm.pos--
547		} else if t, _ := c.peekTSM(); t != seek {
548			c.tsm.pos--
549		}
550	} else {
551		c.tsm.pos = -1
552	}
553}
554
555func (c *integerDescendingBatchCursor) Err() error { return nil }
556
557// close closes the cursor and any dependent cursors.
558func (c *integerDescendingBatchCursor) Close() {
559	c.tsm.keyCursor.Close()
560	c.tsm.keyCursor = nil
561	c.cache.values = nil
562	c.tsm.values = nil
563}
564
565// nextInteger returns the next key/value for the cursor.
566func (c *integerDescendingBatchCursor) Next() ([]int64, []int64) {
567	var ckey, tkey int64
568	var cvalue, tvalue int64
569
570	pos := 0
571	for ; pos < cap(c.t); pos++ {
572		tkey, tvalue = c.peekTSM()
573
574		if c.cache.pos >= 0 {
575			ckey, cvalue = c.peekCache()
576
577			var cache, tsm bool
578
579			// Both cache and tsm files have the same key, cache takes precedence.
580			if ckey == tkey {
581				cache, tsm = true, true
582				tkey = ckey
583				tvalue = cvalue
584			} else if ckey > tkey || tkey == tsdb.EOF {
585				// Buffered cache key succeeds that in TSM file.
586				cache = true
587				tkey = ckey
588				tvalue = cvalue
589			} else {
590				// Buffered TSM key succeeds that in cache.
591				tsm = true
592			}
593
594			if cache {
595				c.nextCache()
596			}
597
598			if tsm {
599				c.nextTSM()
600			}
601		} else {
602			if tkey == tsdb.EOF {
603				break
604			}
605			c.nextTSM()
606		}
607
608		c.t[pos] = tkey
609		c.v[pos] = tvalue
610	}
611
612	// strip out remaining points
613	if pos > 0 && c.t[pos-1] < c.end {
614		pos -= 2
615		for pos >= 0 && c.t[pos] < c.end {
616			pos--
617		}
618		pos++
619	}
620
621	return c.t[:pos], c.v[:pos]
622}
623
624// peekCache returns the current time/value from the cache.
625func (c *integerDescendingBatchCursor) peekCache() (t int64, v int64) {
626	item := c.cache.values[c.cache.pos]
627	return item.UnixNano(), item.(IntegerValue).value
628}
629
630// nextCache returns the next value from the cache.
631func (c *integerDescendingBatchCursor) nextCache() {
632	if c.cache.pos >= 0 {
633		c.cache.pos--
634	}
635}
636
637// peekTSM returns the current time/value from tsm.
638func (c *integerDescendingBatchCursor) peekTSM() (t int64, v int64) {
639	if c.tsm.pos < 0 {
640		return tsdb.EOF, 0
641	}
642
643	item := c.tsm.values[c.tsm.pos]
644	return item.UnixNano(), item.value
645}
646
647// nextTSM returns the next value from the TSM files.
648func (c *integerDescendingBatchCursor) nextTSM() {
649	c.tsm.pos--
650	if c.tsm.pos < 0 {
651		c.tsm.keyCursor.Next()
652		c.tsm.values, _ = c.tsm.keyCursor.ReadIntegerBlock(&c.tsm.buf)
653		c.tsm.pos = len(c.tsm.values) - 1
654	}
655}
656
657type unsignedAscendingBatchCursor struct {
658	cache struct {
659		values Values
660		pos    int
661	}
662
663	tsm struct {
664		buf       []UnsignedValue
665		values    []UnsignedValue
666		pos       int
667		keyCursor *KeyCursor
668	}
669
670	end int64
671	t   []int64
672	v   []uint64
673}
674
675func newUnsignedAscendingBatchCursor() *unsignedAscendingBatchCursor {
676	return &unsignedAscendingBatchCursor{
677		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
678		v: make([]uint64, tsdb.DefaultMaxPointsPerBlock),
679	}
680}
681
682func (c *unsignedAscendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
683	c.end = end
684	c.cache.values = cacheValues
685	c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
686		return c.cache.values[i].UnixNano() >= seek
687	})
688
689	c.tsm.keyCursor = tsmKeyCursor
690	c.tsm.values, _ = c.tsm.keyCursor.ReadUnsignedBlock(&c.tsm.buf)
691	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
692		return c.tsm.values[i].UnixNano() >= seek
693	})
694}
695
696func (c *unsignedAscendingBatchCursor) Err() error { return nil }
697
698// close closes the cursor and any dependent cursors.
699func (c *unsignedAscendingBatchCursor) Close() {
700	c.tsm.keyCursor.Close()
701	c.tsm.keyCursor = nil
702	c.cache.values = nil
703	c.tsm.values = nil
704}
705
706// Next returns the next key/value for the cursor.
707func (c *unsignedAscendingBatchCursor) Next() ([]int64, []uint64) {
708	var ckey, tkey int64
709	var cvalue, tvalue uint64
710
711	pos := 0
712	for ; pos < cap(c.t); pos++ {
713		tkey, tvalue = c.peekTSM()
714
715		if c.cache.pos < len(c.cache.values) {
716			ckey, cvalue = c.peekCache()
717
718			var cache, tsm bool
719
720			// Both cache and tsm files have the same key, cache takes precedence.
721			if ckey == tkey {
722				cache, tsm = true, true
723				tkey = ckey
724				tvalue = cvalue
725			} else if ckey < tkey || tkey == tsdb.EOF {
726				// Buffered cache key precedes that in TSM file.
727				cache = true
728				tkey = ckey
729				tvalue = cvalue
730			} else {
731				// Buffered TSM key precedes that in cache.
732				tsm = true
733			}
734
735			if cache {
736				c.nextCache()
737			}
738
739			if tsm {
740				c.nextTSM()
741			}
742		} else {
743			if tkey == tsdb.EOF {
744				break
745			}
746			c.nextTSM()
747		}
748
749		c.t[pos] = tkey
750		c.v[pos] = tvalue
751	}
752
753	if pos > 0 && c.t[pos-1] > c.end {
754		pos -= 2
755		for pos >= 0 && c.t[pos] > c.end {
756			pos--
757		}
758		pos++
759	}
760
761	return c.t[:pos], c.v[:pos]
762}
763
764// peekCache returns the current time/value from the cache.
765func (c *unsignedAscendingBatchCursor) peekCache() (t int64, v uint64) {
766	item := c.cache.values[c.cache.pos]
767	return item.UnixNano(), item.(UnsignedValue).value
768}
769
770// nextCache returns the next value from the cache.
771func (c *unsignedAscendingBatchCursor) nextCache() {
772	if c.cache.pos < len(c.cache.values) {
773		c.cache.pos++
774	}
775}
776
777// peekTSM returns the current time/value from tsm.
778func (c *unsignedAscendingBatchCursor) peekTSM() (t int64, v uint64) {
779	if c.tsm.pos >= len(c.tsm.values) {
780		return tsdb.EOF, 0
781	}
782
783	item := c.tsm.values[c.tsm.pos]
784	return item.UnixNano(), item.value
785}
786
787// nextTSM returns the next value from the TSM files.
788func (c *unsignedAscendingBatchCursor) nextTSM() {
789	c.tsm.pos++
790	if c.tsm.pos >= len(c.tsm.values) {
791		c.tsm.keyCursor.Next()
792		c.tsm.values, _ = c.tsm.keyCursor.ReadUnsignedBlock(&c.tsm.buf)
793		c.tsm.pos = 0
794	}
795}
796
797type unsignedDescendingBatchCursor struct {
798	cache struct {
799		values Values
800		pos    int
801	}
802
803	tsm struct {
804		buf       []UnsignedValue
805		values    []UnsignedValue
806		pos       int
807		keyCursor *KeyCursor
808	}
809
810	end int64
811	t   []int64
812	v   []uint64
813}
814
815func newUnsignedDescendingBatchCursor() *unsignedDescendingBatchCursor {
816	return &unsignedDescendingBatchCursor{
817		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
818		v: make([]uint64, tsdb.DefaultMaxPointsPerBlock),
819	}
820}
821
822func (c *unsignedDescendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
823	c.end = end
824	c.cache.values = cacheValues
825	if len(c.cache.values) > 0 {
826		c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
827			return c.cache.values[i].UnixNano() >= seek
828		})
829		if c.cache.pos == len(c.cache.values) {
830			c.cache.pos--
831		} else if t, _ := c.peekCache(); t != seek {
832			c.cache.pos--
833		}
834	} else {
835		c.cache.pos = -1
836	}
837
838	c.tsm.keyCursor = tsmKeyCursor
839	c.tsm.values, _ = c.tsm.keyCursor.ReadUnsignedBlock(&c.tsm.buf)
840	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
841		return c.tsm.values[i].UnixNano() >= seek
842	})
843	if len(c.tsm.values) > 0 {
844		if c.tsm.pos == len(c.tsm.values) {
845			c.tsm.pos--
846		} else if t, _ := c.peekTSM(); t != seek {
847			c.tsm.pos--
848		}
849	} else {
850		c.tsm.pos = -1
851	}
852}
853
854func (c *unsignedDescendingBatchCursor) Err() error { return nil }
855
856// close closes the cursor and any dependent cursors.
857func (c *unsignedDescendingBatchCursor) Close() {
858	c.tsm.keyCursor.Close()
859	c.tsm.keyCursor = nil
860	c.cache.values = nil
861	c.tsm.values = nil
862}
863
864// nextUnsigned returns the next key/value for the cursor.
865func (c *unsignedDescendingBatchCursor) Next() ([]int64, []uint64) {
866	var ckey, tkey int64
867	var cvalue, tvalue uint64
868
869	pos := 0
870	for ; pos < cap(c.t); pos++ {
871		tkey, tvalue = c.peekTSM()
872
873		if c.cache.pos >= 0 {
874			ckey, cvalue = c.peekCache()
875
876			var cache, tsm bool
877
878			// Both cache and tsm files have the same key, cache takes precedence.
879			if ckey == tkey {
880				cache, tsm = true, true
881				tkey = ckey
882				tvalue = cvalue
883			} else if ckey > tkey || tkey == tsdb.EOF {
884				// Buffered cache key succeeds that in TSM file.
885				cache = true
886				tkey = ckey
887				tvalue = cvalue
888			} else {
889				// Buffered TSM key succeeds that in cache.
890				tsm = true
891			}
892
893			if cache {
894				c.nextCache()
895			}
896
897			if tsm {
898				c.nextTSM()
899			}
900		} else {
901			if tkey == tsdb.EOF {
902				break
903			}
904			c.nextTSM()
905		}
906
907		c.t[pos] = tkey
908		c.v[pos] = tvalue
909	}
910
911	// strip out remaining points
912	if pos > 0 && c.t[pos-1] < c.end {
913		pos -= 2
914		for pos >= 0 && c.t[pos] < c.end {
915			pos--
916		}
917		pos++
918	}
919
920	return c.t[:pos], c.v[:pos]
921}
922
923// peekCache returns the current time/value from the cache.
924func (c *unsignedDescendingBatchCursor) peekCache() (t int64, v uint64) {
925	item := c.cache.values[c.cache.pos]
926	return item.UnixNano(), item.(UnsignedValue).value
927}
928
929// nextCache returns the next value from the cache.
930func (c *unsignedDescendingBatchCursor) nextCache() {
931	if c.cache.pos >= 0 {
932		c.cache.pos--
933	}
934}
935
936// peekTSM returns the current time/value from tsm.
937func (c *unsignedDescendingBatchCursor) peekTSM() (t int64, v uint64) {
938	if c.tsm.pos < 0 {
939		return tsdb.EOF, 0
940	}
941
942	item := c.tsm.values[c.tsm.pos]
943	return item.UnixNano(), item.value
944}
945
946// nextTSM returns the next value from the TSM files.
947func (c *unsignedDescendingBatchCursor) nextTSM() {
948	c.tsm.pos--
949	if c.tsm.pos < 0 {
950		c.tsm.keyCursor.Next()
951		c.tsm.values, _ = c.tsm.keyCursor.ReadUnsignedBlock(&c.tsm.buf)
952		c.tsm.pos = len(c.tsm.values) - 1
953	}
954}
955
956type stringAscendingBatchCursor struct {
957	cache struct {
958		values Values
959		pos    int
960	}
961
962	tsm struct {
963		buf       []StringValue
964		values    []StringValue
965		pos       int
966		keyCursor *KeyCursor
967	}
968
969	end int64
970	t   []int64
971	v   []string
972}
973
974func newStringAscendingBatchCursor() *stringAscendingBatchCursor {
975	return &stringAscendingBatchCursor{
976		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
977		v: make([]string, tsdb.DefaultMaxPointsPerBlock),
978	}
979}
980
981func (c *stringAscendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
982	c.end = end
983	c.cache.values = cacheValues
984	c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
985		return c.cache.values[i].UnixNano() >= seek
986	})
987
988	c.tsm.keyCursor = tsmKeyCursor
989	c.tsm.values, _ = c.tsm.keyCursor.ReadStringBlock(&c.tsm.buf)
990	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
991		return c.tsm.values[i].UnixNano() >= seek
992	})
993}
994
995func (c *stringAscendingBatchCursor) Err() error { return nil }
996
997// close closes the cursor and any dependent cursors.
998func (c *stringAscendingBatchCursor) Close() {
999	c.tsm.keyCursor.Close()
1000	c.tsm.keyCursor = nil
1001	c.cache.values = nil
1002	c.tsm.values = nil
1003}
1004
1005// Next returns the next key/value for the cursor.
1006func (c *stringAscendingBatchCursor) Next() ([]int64, []string) {
1007	var ckey, tkey int64
1008	var cvalue, tvalue string
1009
1010	pos := 0
1011	for ; pos < cap(c.t); pos++ {
1012		tkey, tvalue = c.peekTSM()
1013
1014		if c.cache.pos < len(c.cache.values) {
1015			ckey, cvalue = c.peekCache()
1016
1017			var cache, tsm bool
1018
1019			// Both cache and tsm files have the same key, cache takes precedence.
1020			if ckey == tkey {
1021				cache, tsm = true, true
1022				tkey = ckey
1023				tvalue = cvalue
1024			} else if ckey < tkey || tkey == tsdb.EOF {
1025				// Buffered cache key precedes that in TSM file.
1026				cache = true
1027				tkey = ckey
1028				tvalue = cvalue
1029			} else {
1030				// Buffered TSM key precedes that in cache.
1031				tsm = true
1032			}
1033
1034			if cache {
1035				c.nextCache()
1036			}
1037
1038			if tsm {
1039				c.nextTSM()
1040			}
1041		} else {
1042			if tkey == tsdb.EOF {
1043				break
1044			}
1045			c.nextTSM()
1046		}
1047
1048		c.t[pos] = tkey
1049		c.v[pos] = tvalue
1050	}
1051
1052	if pos > 0 && c.t[pos-1] > c.end {
1053		pos -= 2
1054		for pos >= 0 && c.t[pos] > c.end {
1055			pos--
1056		}
1057		pos++
1058	}
1059
1060	return c.t[:pos], c.v[:pos]
1061}
1062
1063// peekCache returns the current time/value from the cache.
1064func (c *stringAscendingBatchCursor) peekCache() (t int64, v string) {
1065	item := c.cache.values[c.cache.pos]
1066	return item.UnixNano(), item.(StringValue).value
1067}
1068
1069// nextCache returns the next value from the cache.
1070func (c *stringAscendingBatchCursor) nextCache() {
1071	if c.cache.pos < len(c.cache.values) {
1072		c.cache.pos++
1073	}
1074}
1075
1076// peekTSM returns the current time/value from tsm.
1077func (c *stringAscendingBatchCursor) peekTSM() (t int64, v string) {
1078	if c.tsm.pos >= len(c.tsm.values) {
1079		return tsdb.EOF, ""
1080	}
1081
1082	item := c.tsm.values[c.tsm.pos]
1083	return item.UnixNano(), item.value
1084}
1085
1086// nextTSM returns the next value from the TSM files.
1087func (c *stringAscendingBatchCursor) nextTSM() {
1088	c.tsm.pos++
1089	if c.tsm.pos >= len(c.tsm.values) {
1090		c.tsm.keyCursor.Next()
1091		c.tsm.values, _ = c.tsm.keyCursor.ReadStringBlock(&c.tsm.buf)
1092		c.tsm.pos = 0
1093	}
1094}
1095
1096type stringDescendingBatchCursor struct {
1097	cache struct {
1098		values Values
1099		pos    int
1100	}
1101
1102	tsm struct {
1103		buf       []StringValue
1104		values    []StringValue
1105		pos       int
1106		keyCursor *KeyCursor
1107	}
1108
1109	end int64
1110	t   []int64
1111	v   []string
1112}
1113
1114func newStringDescendingBatchCursor() *stringDescendingBatchCursor {
1115	return &stringDescendingBatchCursor{
1116		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
1117		v: make([]string, tsdb.DefaultMaxPointsPerBlock),
1118	}
1119}
1120
1121func (c *stringDescendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
1122	c.end = end
1123	c.cache.values = cacheValues
1124	if len(c.cache.values) > 0 {
1125		c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
1126			return c.cache.values[i].UnixNano() >= seek
1127		})
1128		if c.cache.pos == len(c.cache.values) {
1129			c.cache.pos--
1130		} else if t, _ := c.peekCache(); t != seek {
1131			c.cache.pos--
1132		}
1133	} else {
1134		c.cache.pos = -1
1135	}
1136
1137	c.tsm.keyCursor = tsmKeyCursor
1138	c.tsm.values, _ = c.tsm.keyCursor.ReadStringBlock(&c.tsm.buf)
1139	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
1140		return c.tsm.values[i].UnixNano() >= seek
1141	})
1142	if len(c.tsm.values) > 0 {
1143		if c.tsm.pos == len(c.tsm.values) {
1144			c.tsm.pos--
1145		} else if t, _ := c.peekTSM(); t != seek {
1146			c.tsm.pos--
1147		}
1148	} else {
1149		c.tsm.pos = -1
1150	}
1151}
1152
1153func (c *stringDescendingBatchCursor) Err() error { return nil }
1154
1155// close closes the cursor and any dependent cursors.
1156func (c *stringDescendingBatchCursor) Close() {
1157	c.tsm.keyCursor.Close()
1158	c.tsm.keyCursor = nil
1159	c.cache.values = nil
1160	c.tsm.values = nil
1161}
1162
1163// nextString returns the next key/value for the cursor.
1164func (c *stringDescendingBatchCursor) Next() ([]int64, []string) {
1165	var ckey, tkey int64
1166	var cvalue, tvalue string
1167
1168	pos := 0
1169	for ; pos < cap(c.t); pos++ {
1170		tkey, tvalue = c.peekTSM()
1171
1172		if c.cache.pos >= 0 {
1173			ckey, cvalue = c.peekCache()
1174
1175			var cache, tsm bool
1176
1177			// Both cache and tsm files have the same key, cache takes precedence.
1178			if ckey == tkey {
1179				cache, tsm = true, true
1180				tkey = ckey
1181				tvalue = cvalue
1182			} else if ckey > tkey || tkey == tsdb.EOF {
1183				// Buffered cache key succeeds that in TSM file.
1184				cache = true
1185				tkey = ckey
1186				tvalue = cvalue
1187			} else {
1188				// Buffered TSM key succeeds that in cache.
1189				tsm = true
1190			}
1191
1192			if cache {
1193				c.nextCache()
1194			}
1195
1196			if tsm {
1197				c.nextTSM()
1198			}
1199		} else {
1200			if tkey == tsdb.EOF {
1201				break
1202			}
1203			c.nextTSM()
1204		}
1205
1206		c.t[pos] = tkey
1207		c.v[pos] = tvalue
1208	}
1209
1210	// strip out remaining points
1211	if pos > 0 && c.t[pos-1] < c.end {
1212		pos -= 2
1213		for pos >= 0 && c.t[pos] < c.end {
1214			pos--
1215		}
1216		pos++
1217	}
1218
1219	return c.t[:pos], c.v[:pos]
1220}
1221
1222// peekCache returns the current time/value from the cache.
1223func (c *stringDescendingBatchCursor) peekCache() (t int64, v string) {
1224	item := c.cache.values[c.cache.pos]
1225	return item.UnixNano(), item.(StringValue).value
1226}
1227
1228// nextCache returns the next value from the cache.
1229func (c *stringDescendingBatchCursor) nextCache() {
1230	if c.cache.pos >= 0 {
1231		c.cache.pos--
1232	}
1233}
1234
1235// peekTSM returns the current time/value from tsm.
1236func (c *stringDescendingBatchCursor) peekTSM() (t int64, v string) {
1237	if c.tsm.pos < 0 {
1238		return tsdb.EOF, ""
1239	}
1240
1241	item := c.tsm.values[c.tsm.pos]
1242	return item.UnixNano(), item.value
1243}
1244
1245// nextTSM returns the next value from the TSM files.
1246func (c *stringDescendingBatchCursor) nextTSM() {
1247	c.tsm.pos--
1248	if c.tsm.pos < 0 {
1249		c.tsm.keyCursor.Next()
1250		c.tsm.values, _ = c.tsm.keyCursor.ReadStringBlock(&c.tsm.buf)
1251		c.tsm.pos = len(c.tsm.values) - 1
1252	}
1253}
1254
1255type booleanAscendingBatchCursor struct {
1256	cache struct {
1257		values Values
1258		pos    int
1259	}
1260
1261	tsm struct {
1262		buf       []BooleanValue
1263		values    []BooleanValue
1264		pos       int
1265		keyCursor *KeyCursor
1266	}
1267
1268	end int64
1269	t   []int64
1270	v   []bool
1271}
1272
1273func newBooleanAscendingBatchCursor() *booleanAscendingBatchCursor {
1274	return &booleanAscendingBatchCursor{
1275		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
1276		v: make([]bool, tsdb.DefaultMaxPointsPerBlock),
1277	}
1278}
1279
1280func (c *booleanAscendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
1281	c.end = end
1282	c.cache.values = cacheValues
1283	c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
1284		return c.cache.values[i].UnixNano() >= seek
1285	})
1286
1287	c.tsm.keyCursor = tsmKeyCursor
1288	c.tsm.values, _ = c.tsm.keyCursor.ReadBooleanBlock(&c.tsm.buf)
1289	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
1290		return c.tsm.values[i].UnixNano() >= seek
1291	})
1292}
1293
1294func (c *booleanAscendingBatchCursor) Err() error { return nil }
1295
1296// close closes the cursor and any dependent cursors.
1297func (c *booleanAscendingBatchCursor) Close() {
1298	c.tsm.keyCursor.Close()
1299	c.tsm.keyCursor = nil
1300	c.cache.values = nil
1301	c.tsm.values = nil
1302}
1303
1304// Next returns the next key/value for the cursor.
1305func (c *booleanAscendingBatchCursor) Next() ([]int64, []bool) {
1306	var ckey, tkey int64
1307	var cvalue, tvalue bool
1308
1309	pos := 0
1310	for ; pos < cap(c.t); pos++ {
1311		tkey, tvalue = c.peekTSM()
1312
1313		if c.cache.pos < len(c.cache.values) {
1314			ckey, cvalue = c.peekCache()
1315
1316			var cache, tsm bool
1317
1318			// Both cache and tsm files have the same key, cache takes precedence.
1319			if ckey == tkey {
1320				cache, tsm = true, true
1321				tkey = ckey
1322				tvalue = cvalue
1323			} else if ckey < tkey || tkey == tsdb.EOF {
1324				// Buffered cache key precedes that in TSM file.
1325				cache = true
1326				tkey = ckey
1327				tvalue = cvalue
1328			} else {
1329				// Buffered TSM key precedes that in cache.
1330				tsm = true
1331			}
1332
1333			if cache {
1334				c.nextCache()
1335			}
1336
1337			if tsm {
1338				c.nextTSM()
1339			}
1340		} else {
1341			if tkey == tsdb.EOF {
1342				break
1343			}
1344			c.nextTSM()
1345		}
1346
1347		c.t[pos] = tkey
1348		c.v[pos] = tvalue
1349	}
1350
1351	if pos > 0 && c.t[pos-1] > c.end {
1352		pos -= 2
1353		for pos >= 0 && c.t[pos] > c.end {
1354			pos--
1355		}
1356		pos++
1357	}
1358
1359	return c.t[:pos], c.v[:pos]
1360}
1361
1362// peekCache returns the current time/value from the cache.
1363func (c *booleanAscendingBatchCursor) peekCache() (t int64, v bool) {
1364	item := c.cache.values[c.cache.pos]
1365	return item.UnixNano(), item.(BooleanValue).value
1366}
1367
1368// nextCache returns the next value from the cache.
1369func (c *booleanAscendingBatchCursor) nextCache() {
1370	if c.cache.pos < len(c.cache.values) {
1371		c.cache.pos++
1372	}
1373}
1374
1375// peekTSM returns the current time/value from tsm.
1376func (c *booleanAscendingBatchCursor) peekTSM() (t int64, v bool) {
1377	if c.tsm.pos >= len(c.tsm.values) {
1378		return tsdb.EOF, false
1379	}
1380
1381	item := c.tsm.values[c.tsm.pos]
1382	return item.UnixNano(), item.value
1383}
1384
1385// nextTSM returns the next value from the TSM files.
1386func (c *booleanAscendingBatchCursor) nextTSM() {
1387	c.tsm.pos++
1388	if c.tsm.pos >= len(c.tsm.values) {
1389		c.tsm.keyCursor.Next()
1390		c.tsm.values, _ = c.tsm.keyCursor.ReadBooleanBlock(&c.tsm.buf)
1391		c.tsm.pos = 0
1392	}
1393}
1394
1395type booleanDescendingBatchCursor struct {
1396	cache struct {
1397		values Values
1398		pos    int
1399	}
1400
1401	tsm struct {
1402		buf       []BooleanValue
1403		values    []BooleanValue
1404		pos       int
1405		keyCursor *KeyCursor
1406	}
1407
1408	end int64
1409	t   []int64
1410	v   []bool
1411}
1412
1413func newBooleanDescendingBatchCursor() *booleanDescendingBatchCursor {
1414	return &booleanDescendingBatchCursor{
1415		t: make([]int64, tsdb.DefaultMaxPointsPerBlock),
1416		v: make([]bool, tsdb.DefaultMaxPointsPerBlock),
1417	}
1418}
1419
1420func (c *booleanDescendingBatchCursor) reset(seek, end int64, cacheValues Values, tsmKeyCursor *KeyCursor) {
1421	c.end = end
1422	c.cache.values = cacheValues
1423	if len(c.cache.values) > 0 {
1424		c.cache.pos = sort.Search(len(c.cache.values), func(i int) bool {
1425			return c.cache.values[i].UnixNano() >= seek
1426		})
1427		if c.cache.pos == len(c.cache.values) {
1428			c.cache.pos--
1429		} else if t, _ := c.peekCache(); t != seek {
1430			c.cache.pos--
1431		}
1432	} else {
1433		c.cache.pos = -1
1434	}
1435
1436	c.tsm.keyCursor = tsmKeyCursor
1437	c.tsm.values, _ = c.tsm.keyCursor.ReadBooleanBlock(&c.tsm.buf)
1438	c.tsm.pos = sort.Search(len(c.tsm.values), func(i int) bool {
1439		return c.tsm.values[i].UnixNano() >= seek
1440	})
1441	if len(c.tsm.values) > 0 {
1442		if c.tsm.pos == len(c.tsm.values) {
1443			c.tsm.pos--
1444		} else if t, _ := c.peekTSM(); t != seek {
1445			c.tsm.pos--
1446		}
1447	} else {
1448		c.tsm.pos = -1
1449	}
1450}
1451
1452func (c *booleanDescendingBatchCursor) Err() error { return nil }
1453
1454// close closes the cursor and any dependent cursors.
1455func (c *booleanDescendingBatchCursor) Close() {
1456	c.tsm.keyCursor.Close()
1457	c.tsm.keyCursor = nil
1458	c.cache.values = nil
1459	c.tsm.values = nil
1460}
1461
1462// nextBoolean returns the next key/value for the cursor.
1463func (c *booleanDescendingBatchCursor) Next() ([]int64, []bool) {
1464	var ckey, tkey int64
1465	var cvalue, tvalue bool
1466
1467	pos := 0
1468	for ; pos < cap(c.t); pos++ {
1469		tkey, tvalue = c.peekTSM()
1470
1471		if c.cache.pos >= 0 {
1472			ckey, cvalue = c.peekCache()
1473
1474			var cache, tsm bool
1475
1476			// Both cache and tsm files have the same key, cache takes precedence.
1477			if ckey == tkey {
1478				cache, tsm = true, true
1479				tkey = ckey
1480				tvalue = cvalue
1481			} else if ckey > tkey || tkey == tsdb.EOF {
1482				// Buffered cache key succeeds that in TSM file.
1483				cache = true
1484				tkey = ckey
1485				tvalue = cvalue
1486			} else {
1487				// Buffered TSM key succeeds that in cache.
1488				tsm = true
1489			}
1490
1491			if cache {
1492				c.nextCache()
1493			}
1494
1495			if tsm {
1496				c.nextTSM()
1497			}
1498		} else {
1499			if tkey == tsdb.EOF {
1500				break
1501			}
1502			c.nextTSM()
1503		}
1504
1505		c.t[pos] = tkey
1506		c.v[pos] = tvalue
1507	}
1508
1509	// strip out remaining points
1510	if pos > 0 && c.t[pos-1] < c.end {
1511		pos -= 2
1512		for pos >= 0 && c.t[pos] < c.end {
1513			pos--
1514		}
1515		pos++
1516	}
1517
1518	return c.t[:pos], c.v[:pos]
1519}
1520
1521// peekCache returns the current time/value from the cache.
1522func (c *booleanDescendingBatchCursor) peekCache() (t int64, v bool) {
1523	item := c.cache.values[c.cache.pos]
1524	return item.UnixNano(), item.(BooleanValue).value
1525}
1526
1527// nextCache returns the next value from the cache.
1528func (c *booleanDescendingBatchCursor) nextCache() {
1529	if c.cache.pos >= 0 {
1530		c.cache.pos--
1531	}
1532}
1533
1534// peekTSM returns the current time/value from tsm.
1535func (c *booleanDescendingBatchCursor) peekTSM() (t int64, v bool) {
1536	if c.tsm.pos < 0 {
1537		return tsdb.EOF, false
1538	}
1539
1540	item := c.tsm.values[c.tsm.pos]
1541	return item.UnixNano(), item.value
1542}
1543
1544// nextTSM returns the next value from the TSM files.
1545func (c *booleanDescendingBatchCursor) nextTSM() {
1546	c.tsm.pos--
1547	if c.tsm.pos < 0 {
1548		c.tsm.keyCursor.Next()
1549		c.tsm.values, _ = c.tsm.keyCursor.ReadBooleanBlock(&c.tsm.buf)
1550		c.tsm.pos = len(c.tsm.values) - 1
1551	}
1552}
1553