mirror of
https://github.com/Oxalide/vsphere-influxdb-go.git
synced 2023-10-10 13:36:51 +02:00
224 lines
5.8 KiB
Cheetah
224 lines
5.8 KiB
Cheetah
package tsm1
|
|
|
|
import (
|
|
"runtime"
|
|
)
|
|
|
|
{{range .}}
|
|
|
|
// merge combines the next set of blocks into merged blocks.
|
|
func (k *tsmKeyIterator) merge{{.Name}}() {
|
|
// No blocks left, or pending merged values, we're done
|
|
if len(k.blocks) == 0 && len(k.merged) == 0 && len(k.merged{{.Name}}Values) == 0 {
|
|
return
|
|
}
|
|
|
|
dedup := len(k.merged{{.Name}}Values) != 0
|
|
if len(k.blocks) > 0 && !dedup {
|
|
// If we have more than one block or any partially tombstoned blocks, we many need to dedup
|
|
dedup = len(k.blocks[0].tombstones) > 0 || k.blocks[0].partiallyRead()
|
|
|
|
// Quickly scan each block to see if any overlap with the prior block, if they overlap then
|
|
// we need to dedup as there may be duplicate points now
|
|
for i := 1; !dedup && i < len(k.blocks); i++ {
|
|
if k.blocks[i].partiallyRead() {
|
|
dedup = true
|
|
break
|
|
}
|
|
|
|
if k.blocks[i].minTime <= k.blocks[i-1].maxTime || len(k.blocks[i].tombstones) > 0 {
|
|
dedup = true
|
|
break
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
k.merged = k.combine{{.Name}}(dedup)
|
|
}
|
|
|
|
// combine returns a new set of blocks using the current blocks in the buffers. If dedup
|
|
// is true, all the blocks will be decoded, dedup and sorted in in order. If dedup is false,
|
|
// only blocks that are smaller than the chunk size will be decoded and combined.
|
|
func (k *tsmKeyIterator) combine{{.Name}}(dedup bool) blocks {
|
|
if dedup {
|
|
for len(k.merged{{.Name}}Values) < k.size && len(k.blocks) > 0 {
|
|
for len(k.blocks) > 0 && k.blocks[0].read() {
|
|
k.blocks = k.blocks[1:]
|
|
}
|
|
|
|
if len(k.blocks) == 0 {
|
|
break
|
|
}
|
|
first := k.blocks[0]
|
|
minTime := first.minTime
|
|
maxTime := first.maxTime
|
|
|
|
// Adjust the min time to the start of any overlapping blocks.
|
|
for i := 0; i < len(k.blocks); i++ {
|
|
if k.blocks[i].overlapsTimeRange(minTime, maxTime) && !k.blocks[i].read() {
|
|
if k.blocks[i].minTime < minTime {
|
|
minTime = k.blocks[i].minTime
|
|
}
|
|
if k.blocks[i].maxTime > minTime && k.blocks[i].maxTime < maxTime {
|
|
maxTime = k.blocks[i].maxTime
|
|
}
|
|
}
|
|
}
|
|
|
|
// We have some overlapping blocks so decode all, append in order and then dedup
|
|
for i := 0; i < len(k.blocks); i++ {
|
|
if !k.blocks[i].overlapsTimeRange(minTime, maxTime) || k.blocks[i].read() {
|
|
continue
|
|
}
|
|
|
|
v, err := Decode{{.Name}}Block(k.blocks[i].b, &[]{{.Name}}Value{})
|
|
if err != nil {
|
|
k.err = err
|
|
return nil
|
|
}
|
|
|
|
// Remove values we already read
|
|
v = {{.Name}}Values(v).Exclude(k.blocks[i].readMin, k.blocks[i].readMax)
|
|
|
|
// Filter out only the values for overlapping block
|
|
v = {{.Name}}Values(v).Include(minTime, maxTime)
|
|
if len(v) > 0 {
|
|
// Record that we read a subset of the block
|
|
k.blocks[i].markRead(v[0].UnixNano(), v[len(v)-1].UnixNano())
|
|
}
|
|
|
|
// Apply each tombstone to the block
|
|
for _, ts := range k.blocks[i].tombstones {
|
|
v = {{.Name}}Values(v).Exclude(ts.Min, ts.Max)
|
|
}
|
|
|
|
k.merged{{.Name}}Values = k.merged{{.Name}}Values.Merge(v)
|
|
|
|
// Allow other goroutines to run
|
|
runtime.Gosched()
|
|
|
|
}
|
|
}
|
|
|
|
// Since we combined multiple blocks, we could have more values than we should put into
|
|
// a single block. We need to chunk them up into groups and re-encode them.
|
|
return k.chunk{{.Name}}(nil)
|
|
} else {
|
|
var chunked blocks
|
|
var i int
|
|
|
|
for i < len(k.blocks) {
|
|
|
|
// skip this block if it's values were already read
|
|
if k.blocks[i].read() {
|
|
i++
|
|
continue
|
|
}
|
|
// If we this block is already full, just add it as is
|
|
if BlockCount(k.blocks[i].b) >= k.size {
|
|
chunked = append(chunked, k.blocks[i])
|
|
} else {
|
|
break
|
|
}
|
|
i++
|
|
// Allow other goroutines to run
|
|
runtime.Gosched()
|
|
}
|
|
|
|
if k.fast {
|
|
for i < len(k.blocks) {
|
|
// skip this block if it's values were already read
|
|
if k.blocks[i].read() {
|
|
i++
|
|
continue
|
|
}
|
|
|
|
chunked = append(chunked, k.blocks[i])
|
|
i++
|
|
// Allow other goroutines to run
|
|
runtime.Gosched()
|
|
}
|
|
}
|
|
|
|
// If we only have 1 blocks left, just append it as is and avoid decoding/recoding
|
|
if i == len(k.blocks)-1 {
|
|
if !k.blocks[i].read() {
|
|
chunked = append(chunked, k.blocks[i])
|
|
}
|
|
i++
|
|
}
|
|
|
|
// The remaining blocks can be combined and we know that they do not overlap and
|
|
// so we can just append each, sort and re-encode.
|
|
for i < len(k.blocks) && len(k.merged{{.Name}}Values) < k.size {
|
|
if k.blocks[i].read() {
|
|
i++
|
|
continue
|
|
}
|
|
|
|
v, err := Decode{{.Name}}Block(k.blocks[i].b, &[]{{.Name}}Value{})
|
|
if err != nil {
|
|
k.err = err
|
|
return nil
|
|
}
|
|
|
|
// Apply each tombstone to the block
|
|
for _, ts := range k.blocks[i].tombstones {
|
|
v = {{.Name}}Values(v).Exclude(ts.Min, ts.Max)
|
|
}
|
|
|
|
k.blocks[i].markRead(k.blocks[i].minTime, k.blocks[i].maxTime)
|
|
|
|
k.merged{{.Name}}Values = k.merged{{.Name}}Values.Merge(v)
|
|
i++
|
|
// Allow other goroutines to run
|
|
runtime.Gosched()
|
|
}
|
|
|
|
k.blocks = k.blocks[i:]
|
|
|
|
return k.chunk{{.Name}}(chunked)
|
|
}
|
|
}
|
|
|
|
func (k *tsmKeyIterator) chunk{{.Name}}(dst blocks) blocks {
|
|
if len(k.merged{{.Name}}Values) > k.size {
|
|
values := k.merged{{.Name}}Values[:k.size]
|
|
cb, err := {{.Name}}Values(values).Encode(nil)
|
|
if err != nil {
|
|
k.err = err
|
|
return nil
|
|
}
|
|
|
|
dst = append(dst, &block{
|
|
minTime: values[0].UnixNano(),
|
|
maxTime: values[len(values)-1].UnixNano(),
|
|
key: k.key,
|
|
b: cb,
|
|
})
|
|
k.merged{{.Name}}Values = k.merged{{.Name}}Values[k.size:]
|
|
return dst
|
|
}
|
|
|
|
// Re-encode the remaining values into the last block
|
|
if len(k.merged{{.Name}}Values) > 0 {
|
|
cb, err := {{.Name}}Values(k.merged{{.Name}}Values).Encode(nil)
|
|
if err != nil {
|
|
k.err = err
|
|
return nil
|
|
}
|
|
|
|
dst = append(dst, &block{
|
|
minTime: k.merged{{.Name}}Values[0].UnixNano(),
|
|
maxTime: k.merged{{.Name}}Values[len(k.merged{{.Name}}Values)-1].UnixNano(),
|
|
key: k.key,
|
|
b: cb,
|
|
})
|
|
k.merged{{.Name}}Values = k.merged{{.Name}}Values[:0]
|
|
}
|
|
return dst
|
|
}
|
|
|
|
{{ end }}
|