928 lines
28 KiB
Go
928 lines
28 KiB
Go
// Code generated by file_store.gen.go.tmpl. DO NOT EDIT.
|
|
|
|
package tsm1
|
|
|
|
import (
|
|
"github.com/influxdata/influxdb/tsdb"
|
|
)
|
|
|
|
// ReadFloatArrayBlock reads the next block as a set of float values.
|
|
func (c *KeyCursor) ReadFloatArrayBlock(values *tsdb.FloatArray) (*tsdb.FloatArray, error) {
|
|
LOOP:
|
|
// No matching blocks to decode
|
|
if len(c.current) == 0 {
|
|
values.Timestamps = values.Timestamps[:0]
|
|
values.Values = values.Values[:0]
|
|
return values, nil
|
|
}
|
|
|
|
// First block is the oldest block containing the points we're searching for.
|
|
first := c.current[0]
|
|
err := first.r.ReadFloatArrayBlockAt(&first.entry, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(floatBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(floatBlocksSizeCounter).Add(int64(first.entry.Size))
|
|
}
|
|
|
|
// Remove values we already read
|
|
values.Exclude(first.readMin, first.readMax)
|
|
|
|
// Remove any tombstones
|
|
c.trbuf = first.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
excludeTombstonesFloatArray(c.trbuf, values)
|
|
// If there are no values in this first block (all tombstoned or previously read) and
|
|
// we have more potential blocks too search. Try again.
|
|
if values.Len() == 0 && len(c.current) > 0 {
|
|
c.current = c.current[1:]
|
|
goto LOOP
|
|
}
|
|
|
|
// Only one block with this key and time range so return it
|
|
if len(c.current) == 1 {
|
|
if values.Len() > 0 {
|
|
first.markRead(values.MinTime(), values.MaxTime())
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// Use the current block time range as our overlapping window
|
|
minT, maxT := first.readMin, first.readMax
|
|
if values.Len() > 0 {
|
|
minT, maxT = values.MinTime(), values.MaxTime()
|
|
}
|
|
if c.ascending {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the min time range to ensure values are returned in ascending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MinTime < minT && !cur.read() {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MaxTime > maxT {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.FloatArray{}
|
|
err := cur.r.ReadFloatArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(floatBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(floatBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesFloatArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
if v.Len() > 0 {
|
|
// Only use values in the overlapping window
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
values.Merge(v)
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
|
|
} else {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the max time range to ensure values are returned in descending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MaxTime > maxT && !cur.read() {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MinTime < minT {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.FloatArray{}
|
|
err := cur.r.ReadFloatArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(floatBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(floatBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesFloatArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
// If the block we decoded should have all of it's values included, mark it as read so we
|
|
// don't use it again.
|
|
if v.Len() > 0 {
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
v.Merge(values)
|
|
*values = *v
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
}
|
|
|
|
first.markRead(minT, maxT)
|
|
|
|
return values, err
|
|
}
|
|
|
|
func excludeTombstonesFloatArray(t []TimeRange, values *tsdb.FloatArray) {
|
|
for i := range t {
|
|
values.Exclude(t[i].Min, t[i].Max)
|
|
}
|
|
}
|
|
|
|
// ReadIntegerArrayBlock reads the next block as a set of integer values.
|
|
func (c *KeyCursor) ReadIntegerArrayBlock(values *tsdb.IntegerArray) (*tsdb.IntegerArray, error) {
|
|
LOOP:
|
|
// No matching blocks to decode
|
|
if len(c.current) == 0 {
|
|
values.Timestamps = values.Timestamps[:0]
|
|
values.Values = values.Values[:0]
|
|
return values, nil
|
|
}
|
|
|
|
// First block is the oldest block containing the points we're searching for.
|
|
first := c.current[0]
|
|
err := first.r.ReadIntegerArrayBlockAt(&first.entry, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(integerBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(integerBlocksSizeCounter).Add(int64(first.entry.Size))
|
|
}
|
|
|
|
// Remove values we already read
|
|
values.Exclude(first.readMin, first.readMax)
|
|
|
|
// Remove any tombstones
|
|
c.trbuf = first.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
excludeTombstonesIntegerArray(c.trbuf, values)
|
|
// If there are no values in this first block (all tombstoned or previously read) and
|
|
// we have more potential blocks too search. Try again.
|
|
if values.Len() == 0 && len(c.current) > 0 {
|
|
c.current = c.current[1:]
|
|
goto LOOP
|
|
}
|
|
|
|
// Only one block with this key and time range so return it
|
|
if len(c.current) == 1 {
|
|
if values.Len() > 0 {
|
|
first.markRead(values.MinTime(), values.MaxTime())
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// Use the current block time range as our overlapping window
|
|
minT, maxT := first.readMin, first.readMax
|
|
if values.Len() > 0 {
|
|
minT, maxT = values.MinTime(), values.MaxTime()
|
|
}
|
|
if c.ascending {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the min time range to ensure values are returned in ascending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MinTime < minT && !cur.read() {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MaxTime > maxT {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.IntegerArray{}
|
|
err := cur.r.ReadIntegerArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(integerBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(integerBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesIntegerArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
if v.Len() > 0 {
|
|
// Only use values in the overlapping window
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
values.Merge(v)
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
|
|
} else {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the max time range to ensure values are returned in descending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MaxTime > maxT && !cur.read() {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MinTime < minT {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.IntegerArray{}
|
|
err := cur.r.ReadIntegerArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(integerBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(integerBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesIntegerArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
// If the block we decoded should have all of it's values included, mark it as read so we
|
|
// don't use it again.
|
|
if v.Len() > 0 {
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
v.Merge(values)
|
|
*values = *v
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
}
|
|
|
|
first.markRead(minT, maxT)
|
|
|
|
return values, err
|
|
}
|
|
|
|
func excludeTombstonesIntegerArray(t []TimeRange, values *tsdb.IntegerArray) {
|
|
for i := range t {
|
|
values.Exclude(t[i].Min, t[i].Max)
|
|
}
|
|
}
|
|
|
|
// ReadUnsignedArrayBlock reads the next block as a set of unsigned values.
|
|
func (c *KeyCursor) ReadUnsignedArrayBlock(values *tsdb.UnsignedArray) (*tsdb.UnsignedArray, error) {
|
|
LOOP:
|
|
// No matching blocks to decode
|
|
if len(c.current) == 0 {
|
|
values.Timestamps = values.Timestamps[:0]
|
|
values.Values = values.Values[:0]
|
|
return values, nil
|
|
}
|
|
|
|
// First block is the oldest block containing the points we're searching for.
|
|
first := c.current[0]
|
|
err := first.r.ReadUnsignedArrayBlockAt(&first.entry, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(unsignedBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(unsignedBlocksSizeCounter).Add(int64(first.entry.Size))
|
|
}
|
|
|
|
// Remove values we already read
|
|
values.Exclude(first.readMin, first.readMax)
|
|
|
|
// Remove any tombstones
|
|
c.trbuf = first.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
excludeTombstonesUnsignedArray(c.trbuf, values)
|
|
// If there are no values in this first block (all tombstoned or previously read) and
|
|
// we have more potential blocks too search. Try again.
|
|
if values.Len() == 0 && len(c.current) > 0 {
|
|
c.current = c.current[1:]
|
|
goto LOOP
|
|
}
|
|
|
|
// Only one block with this key and time range so return it
|
|
if len(c.current) == 1 {
|
|
if values.Len() > 0 {
|
|
first.markRead(values.MinTime(), values.MaxTime())
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// Use the current block time range as our overlapping window
|
|
minT, maxT := first.readMin, first.readMax
|
|
if values.Len() > 0 {
|
|
minT, maxT = values.MinTime(), values.MaxTime()
|
|
}
|
|
if c.ascending {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the min time range to ensure values are returned in ascending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MinTime < minT && !cur.read() {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MaxTime > maxT {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.UnsignedArray{}
|
|
err := cur.r.ReadUnsignedArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(unsignedBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(unsignedBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesUnsignedArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
if v.Len() > 0 {
|
|
// Only use values in the overlapping window
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
values.Merge(v)
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
|
|
} else {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the max time range to ensure values are returned in descending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MaxTime > maxT && !cur.read() {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MinTime < minT {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.UnsignedArray{}
|
|
err := cur.r.ReadUnsignedArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(unsignedBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(unsignedBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesUnsignedArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
// If the block we decoded should have all of it's values included, mark it as read so we
|
|
// don't use it again.
|
|
if v.Len() > 0 {
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
v.Merge(values)
|
|
*values = *v
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
}
|
|
|
|
first.markRead(minT, maxT)
|
|
|
|
return values, err
|
|
}
|
|
|
|
func excludeTombstonesUnsignedArray(t []TimeRange, values *tsdb.UnsignedArray) {
|
|
for i := range t {
|
|
values.Exclude(t[i].Min, t[i].Max)
|
|
}
|
|
}
|
|
|
|
// ReadStringArrayBlock reads the next block as a set of string values.
|
|
func (c *KeyCursor) ReadStringArrayBlock(values *tsdb.StringArray) (*tsdb.StringArray, error) {
|
|
LOOP:
|
|
// No matching blocks to decode
|
|
if len(c.current) == 0 {
|
|
values.Timestamps = values.Timestamps[:0]
|
|
values.Values = values.Values[:0]
|
|
return values, nil
|
|
}
|
|
|
|
// First block is the oldest block containing the points we're searching for.
|
|
first := c.current[0]
|
|
err := first.r.ReadStringArrayBlockAt(&first.entry, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(stringBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(stringBlocksSizeCounter).Add(int64(first.entry.Size))
|
|
}
|
|
|
|
// Remove values we already read
|
|
values.Exclude(first.readMin, first.readMax)
|
|
|
|
// Remove any tombstones
|
|
c.trbuf = first.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
excludeTombstonesStringArray(c.trbuf, values)
|
|
// If there are no values in this first block (all tombstoned or previously read) and
|
|
// we have more potential blocks too search. Try again.
|
|
if values.Len() == 0 && len(c.current) > 0 {
|
|
c.current = c.current[1:]
|
|
goto LOOP
|
|
}
|
|
|
|
// Only one block with this key and time range so return it
|
|
if len(c.current) == 1 {
|
|
if values.Len() > 0 {
|
|
first.markRead(values.MinTime(), values.MaxTime())
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// Use the current block time range as our overlapping window
|
|
minT, maxT := first.readMin, first.readMax
|
|
if values.Len() > 0 {
|
|
minT, maxT = values.MinTime(), values.MaxTime()
|
|
}
|
|
if c.ascending {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the min time range to ensure values are returned in ascending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MinTime < minT && !cur.read() {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MaxTime > maxT {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.StringArray{}
|
|
err := cur.r.ReadStringArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(stringBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(stringBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesStringArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
if v.Len() > 0 {
|
|
// Only use values in the overlapping window
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
values.Merge(v)
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
|
|
} else {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the max time range to ensure values are returned in descending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MaxTime > maxT && !cur.read() {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MinTime < minT {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.StringArray{}
|
|
err := cur.r.ReadStringArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(stringBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(stringBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesStringArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
// If the block we decoded should have all of it's values included, mark it as read so we
|
|
// don't use it again.
|
|
if v.Len() > 0 {
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
v.Merge(values)
|
|
*values = *v
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
}
|
|
|
|
first.markRead(minT, maxT)
|
|
|
|
return values, err
|
|
}
|
|
|
|
func excludeTombstonesStringArray(t []TimeRange, values *tsdb.StringArray) {
|
|
for i := range t {
|
|
values.Exclude(t[i].Min, t[i].Max)
|
|
}
|
|
}
|
|
|
|
// ReadBooleanArrayBlock reads the next block as a set of boolean values.
|
|
func (c *KeyCursor) ReadBooleanArrayBlock(values *tsdb.BooleanArray) (*tsdb.BooleanArray, error) {
|
|
LOOP:
|
|
// No matching blocks to decode
|
|
if len(c.current) == 0 {
|
|
values.Timestamps = values.Timestamps[:0]
|
|
values.Values = values.Values[:0]
|
|
return values, nil
|
|
}
|
|
|
|
// First block is the oldest block containing the points we're searching for.
|
|
first := c.current[0]
|
|
err := first.r.ReadBooleanArrayBlockAt(&first.entry, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(booleanBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(booleanBlocksSizeCounter).Add(int64(first.entry.Size))
|
|
}
|
|
|
|
// Remove values we already read
|
|
values.Exclude(first.readMin, first.readMax)
|
|
|
|
// Remove any tombstones
|
|
c.trbuf = first.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
excludeTombstonesBooleanArray(c.trbuf, values)
|
|
// If there are no values in this first block (all tombstoned or previously read) and
|
|
// we have more potential blocks too search. Try again.
|
|
if values.Len() == 0 && len(c.current) > 0 {
|
|
c.current = c.current[1:]
|
|
goto LOOP
|
|
}
|
|
|
|
// Only one block with this key and time range so return it
|
|
if len(c.current) == 1 {
|
|
if values.Len() > 0 {
|
|
first.markRead(values.MinTime(), values.MaxTime())
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// Use the current block time range as our overlapping window
|
|
minT, maxT := first.readMin, first.readMax
|
|
if values.Len() > 0 {
|
|
minT, maxT = values.MinTime(), values.MaxTime()
|
|
}
|
|
if c.ascending {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the min time range to ensure values are returned in ascending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MinTime < minT && !cur.read() {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MaxTime > maxT {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.BooleanArray{}
|
|
err := cur.r.ReadBooleanArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(booleanBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(booleanBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesBooleanArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
if v.Len() > 0 {
|
|
// Only use values in the overlapping window
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
values.Merge(v)
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
|
|
} else {
|
|
// Blocks are ordered by generation, we may have values in the past in later blocks, if so,
|
|
// expand the window to include the max time range to ensure values are returned in descending
|
|
// order
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.MaxTime > maxT && !cur.read() {
|
|
maxT = cur.entry.MaxTime
|
|
}
|
|
}
|
|
|
|
// Find first block that overlaps our window
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
if cur.entry.OverlapsTimeRange(minT, maxT) && !cur.read() {
|
|
// Shrink our window so it's the intersection of the first overlapping block and the
|
|
// first block. We do this to minimize the region that overlaps and needs to
|
|
// be merged.
|
|
if cur.entry.MinTime < minT {
|
|
minT = cur.entry.MinTime
|
|
}
|
|
values.Include(minT, maxT)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Search the remaining blocks that overlap our window and append their values so we can
|
|
// merge them.
|
|
for i := 1; i < len(c.current); i++ {
|
|
cur := c.current[i]
|
|
// Skip this block if it doesn't contain points we looking for or they have already been read
|
|
if !cur.entry.OverlapsTimeRange(minT, maxT) || cur.read() {
|
|
cur.markRead(minT, maxT)
|
|
continue
|
|
}
|
|
|
|
v := &tsdb.BooleanArray{}
|
|
err := cur.r.ReadBooleanArrayBlockAt(&cur.entry, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c.col != nil {
|
|
c.col.GetCounter(booleanBlocksDecodedCounter).Add(1)
|
|
c.col.GetCounter(booleanBlocksSizeCounter).Add(int64(cur.entry.Size))
|
|
}
|
|
c.trbuf = cur.r.TombstoneRange(c.key, c.trbuf[:0])
|
|
// Remove any tombstoned values
|
|
excludeTombstonesBooleanArray(c.trbuf, v)
|
|
|
|
// Remove values we already read
|
|
v.Exclude(cur.readMin, cur.readMax)
|
|
|
|
// If the block we decoded should have all of it's values included, mark it as read so we
|
|
// don't use it again.
|
|
if v.Len() > 0 {
|
|
v.Include(minT, maxT)
|
|
// Merge the remaining values with the existing
|
|
v.Merge(values)
|
|
*values = *v
|
|
}
|
|
cur.markRead(minT, maxT)
|
|
}
|
|
}
|
|
|
|
first.markRead(minT, maxT)
|
|
|
|
return values, err
|
|
}
|
|
|
|
func excludeTombstonesBooleanArray(t []TimeRange, values *tsdb.BooleanArray) {
|
|
for i := range t {
|
|
values.Exclude(t[i].Min, t[i].Max)
|
|
}
|
|
}
|