mirror of
https://github.com/Oxalide/vsphere-influxdb-go.git
synced 2023-10-10 13:36:51 +02:00
819 lines
20 KiB
Go
819 lines
20 KiB
Go
|
package tsi1
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/binary"
|
||
|
"encoding/hex"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"os"
|
||
|
|
||
|
"github.com/influxdata/influxdb/influxql"
|
||
|
"github.com/influxdata/influxdb/models"
|
||
|
)
|
||
|
|
||
|
// LoadFactor is the fill percent for RHH indexes.
|
||
|
const LoadFactor = 80
|
||
|
|
||
|
// MeasurementElem represents a generic measurement element.
|
||
|
type MeasurementElem interface {
|
||
|
Name() []byte
|
||
|
Deleted() bool
|
||
|
}
|
||
|
|
||
|
// MeasurementElems represents a list of MeasurementElem.
|
||
|
type MeasurementElems []MeasurementElem
|
||
|
|
||
|
func (a MeasurementElems) Len() int { return len(a) }
|
||
|
func (a MeasurementElems) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||
|
func (a MeasurementElems) Less(i, j int) bool { return bytes.Compare(a[i].Name(), a[j].Name()) == -1 }
|
||
|
|
||
|
// MeasurementIterator represents a iterator over a list of measurements.
|
||
|
type MeasurementIterator interface {
|
||
|
Next() MeasurementElem
|
||
|
}
|
||
|
|
||
|
// MergeMeasurementIterators returns an iterator that merges a set of iterators.
|
||
|
// Iterators that are first in the list take precendence and a deletion by those
|
||
|
// early iterators will invalidate elements by later iterators.
|
||
|
func MergeMeasurementIterators(itrs ...MeasurementIterator) MeasurementIterator {
|
||
|
if len(itrs) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return &measurementMergeIterator{
|
||
|
e: make(measurementMergeElem, 0, len(itrs)),
|
||
|
buf: make([]MeasurementElem, len(itrs)),
|
||
|
itrs: itrs,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type measurementMergeIterator struct {
|
||
|
e measurementMergeElem
|
||
|
buf []MeasurementElem
|
||
|
itrs []MeasurementIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the element with the next lowest name across the iterators.
|
||
|
//
|
||
|
// If multiple iterators contain the same name then the first is returned
|
||
|
// and the remaining ones are skipped.
|
||
|
func (itr *measurementMergeIterator) Next() MeasurementElem {
|
||
|
// Find next lowest name amongst the buffers.
|
||
|
var name []byte
|
||
|
for i, buf := range itr.buf {
|
||
|
// Fill buffer if empty.
|
||
|
if buf == nil {
|
||
|
if buf = itr.itrs[i].Next(); buf != nil {
|
||
|
itr.buf[i] = buf
|
||
|
} else {
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Find next lowest name.
|
||
|
if name == nil || bytes.Compare(itr.buf[i].Name(), name) == -1 {
|
||
|
name = itr.buf[i].Name()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return nil if no elements remaining.
|
||
|
if name == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Merge all elements together and clear buffers.
|
||
|
itr.e = itr.e[:0]
|
||
|
for i, buf := range itr.buf {
|
||
|
if buf == nil || !bytes.Equal(buf.Name(), name) {
|
||
|
continue
|
||
|
}
|
||
|
itr.e = append(itr.e, buf)
|
||
|
itr.buf[i] = nil
|
||
|
}
|
||
|
return itr.e
|
||
|
}
|
||
|
|
||
|
// measurementMergeElem represents a merged measurement element.
|
||
|
type measurementMergeElem []MeasurementElem
|
||
|
|
||
|
// Name returns the name of the first element.
|
||
|
func (p measurementMergeElem) Name() []byte {
|
||
|
if len(p) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return p[0].Name()
|
||
|
}
|
||
|
|
||
|
// Deleted returns the deleted flag of the first element.
|
||
|
func (p measurementMergeElem) Deleted() bool {
|
||
|
if len(p) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
return p[0].Deleted()
|
||
|
}
|
||
|
|
||
|
// filterUndeletedMeasurementIterator returns all measurements which are not deleted.
|
||
|
type filterUndeletedMeasurementIterator struct {
|
||
|
itr MeasurementIterator
|
||
|
}
|
||
|
|
||
|
// FilterUndeletedMeasurementIterator returns an iterator which filters all deleted measurement.
|
||
|
func FilterUndeletedMeasurementIterator(itr MeasurementIterator) MeasurementIterator {
|
||
|
if itr == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return &filterUndeletedMeasurementIterator{itr: itr}
|
||
|
}
|
||
|
|
||
|
func (itr *filterUndeletedMeasurementIterator) Next() MeasurementElem {
|
||
|
for {
|
||
|
e := itr.itr.Next()
|
||
|
if e == nil {
|
||
|
return nil
|
||
|
} else if e.Deleted() {
|
||
|
continue
|
||
|
}
|
||
|
return e
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TagKeyElem represents a generic tag key element.
|
||
|
type TagKeyElem interface {
|
||
|
Key() []byte
|
||
|
Deleted() bool
|
||
|
TagValueIterator() TagValueIterator
|
||
|
}
|
||
|
|
||
|
// TagKeyIterator represents a iterator over a list of tag keys.
|
||
|
type TagKeyIterator interface {
|
||
|
Next() TagKeyElem
|
||
|
}
|
||
|
|
||
|
// MergeTagKeyIterators returns an iterator that merges a set of iterators.
|
||
|
// Iterators that are first in the list take precendence and a deletion by those
|
||
|
// early iterators will invalidate elements by later iterators.
|
||
|
func MergeTagKeyIterators(itrs ...TagKeyIterator) TagKeyIterator {
|
||
|
if len(itrs) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return &tagKeyMergeIterator{
|
||
|
e: make(tagKeyMergeElem, 0, len(itrs)),
|
||
|
buf: make([]TagKeyElem, len(itrs)),
|
||
|
itrs: itrs,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type tagKeyMergeIterator struct {
|
||
|
e tagKeyMergeElem
|
||
|
buf []TagKeyElem
|
||
|
itrs []TagKeyIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the element with the next lowest key across the iterators.
|
||
|
//
|
||
|
// If multiple iterators contain the same key then the first is returned
|
||
|
// and the remaining ones are skipped.
|
||
|
func (itr *tagKeyMergeIterator) Next() TagKeyElem {
|
||
|
// Find next lowest key amongst the buffers.
|
||
|
var key []byte
|
||
|
for i, buf := range itr.buf {
|
||
|
// Fill buffer.
|
||
|
if buf == nil {
|
||
|
if buf = itr.itrs[i].Next(); buf != nil {
|
||
|
itr.buf[i] = buf
|
||
|
} else {
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Find next lowest key.
|
||
|
if key == nil || bytes.Compare(buf.Key(), key) == -1 {
|
||
|
key = buf.Key()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return nil if no elements remaining.
|
||
|
if key == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Merge elements together & clear buffer.
|
||
|
itr.e = itr.e[:0]
|
||
|
for i, buf := range itr.buf {
|
||
|
if buf == nil || !bytes.Equal(buf.Key(), key) {
|
||
|
continue
|
||
|
}
|
||
|
itr.e = append(itr.e, buf)
|
||
|
itr.buf[i] = nil
|
||
|
}
|
||
|
|
||
|
return itr.e
|
||
|
}
|
||
|
|
||
|
// tagKeyMergeElem represents a merged tag key element.
|
||
|
type tagKeyMergeElem []TagKeyElem
|
||
|
|
||
|
// Key returns the key of the first element.
|
||
|
func (p tagKeyMergeElem) Key() []byte {
|
||
|
if len(p) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return p[0].Key()
|
||
|
}
|
||
|
|
||
|
// Deleted returns the deleted flag of the first element.
|
||
|
func (p tagKeyMergeElem) Deleted() bool {
|
||
|
if len(p) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
return p[0].Deleted()
|
||
|
}
|
||
|
|
||
|
// TagValueIterator returns a merge iterator for all elements until a tombstone occurs.
|
||
|
func (p tagKeyMergeElem) TagValueIterator() TagValueIterator {
|
||
|
if len(p) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
a := make([]TagValueIterator, 0, len(p))
|
||
|
for _, e := range p {
|
||
|
itr := e.TagValueIterator()
|
||
|
|
||
|
a = append(a, itr)
|
||
|
if e.Deleted() {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return MergeTagValueIterators(a...)
|
||
|
}
|
||
|
|
||
|
// TagValueElem represents a generic tag value element.
|
||
|
type TagValueElem interface {
|
||
|
Value() []byte
|
||
|
Deleted() bool
|
||
|
}
|
||
|
|
||
|
// TagValueIterator represents a iterator over a list of tag values.
|
||
|
type TagValueIterator interface {
|
||
|
Next() TagValueElem
|
||
|
}
|
||
|
|
||
|
// MergeTagValueIterators returns an iterator that merges a set of iterators.
|
||
|
// Iterators that are first in the list take precendence and a deletion by those
|
||
|
// early iterators will invalidate elements by later iterators.
|
||
|
func MergeTagValueIterators(itrs ...TagValueIterator) TagValueIterator {
|
||
|
if len(itrs) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return &tagValueMergeIterator{
|
||
|
e: make(tagValueMergeElem, 0, len(itrs)),
|
||
|
buf: make([]TagValueElem, len(itrs)),
|
||
|
itrs: itrs,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type tagValueMergeIterator struct {
|
||
|
e tagValueMergeElem
|
||
|
buf []TagValueElem
|
||
|
itrs []TagValueIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the element with the next lowest value across the iterators.
|
||
|
//
|
||
|
// If multiple iterators contain the same value then the first is returned
|
||
|
// and the remaining ones are skipped.
|
||
|
func (itr *tagValueMergeIterator) Next() TagValueElem {
|
||
|
// Find next lowest value amongst the buffers.
|
||
|
var value []byte
|
||
|
for i, buf := range itr.buf {
|
||
|
// Fill buffer.
|
||
|
if buf == nil {
|
||
|
if buf = itr.itrs[i].Next(); buf != nil {
|
||
|
itr.buf[i] = buf
|
||
|
} else {
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Find next lowest value.
|
||
|
if value == nil || bytes.Compare(buf.Value(), value) == -1 {
|
||
|
value = buf.Value()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return nil if no elements remaining.
|
||
|
if value == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Merge elements and clear buffers.
|
||
|
itr.e = itr.e[:0]
|
||
|
for i, buf := range itr.buf {
|
||
|
if buf == nil || !bytes.Equal(buf.Value(), value) {
|
||
|
continue
|
||
|
}
|
||
|
itr.e = append(itr.e, buf)
|
||
|
itr.buf[i] = nil
|
||
|
}
|
||
|
return itr.e
|
||
|
}
|
||
|
|
||
|
// tagValueMergeElem represents a merged tag value element.
|
||
|
type tagValueMergeElem []TagValueElem
|
||
|
|
||
|
// Name returns the value of the first element.
|
||
|
func (p tagValueMergeElem) Value() []byte {
|
||
|
if len(p) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return p[0].Value()
|
||
|
}
|
||
|
|
||
|
// Deleted returns the deleted flag of the first element.
|
||
|
func (p tagValueMergeElem) Deleted() bool {
|
||
|
if len(p) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
return p[0].Deleted()
|
||
|
}
|
||
|
|
||
|
// SeriesElem represents a generic series element.
|
||
|
type SeriesElem interface {
|
||
|
Name() []byte
|
||
|
Tags() models.Tags
|
||
|
Deleted() bool
|
||
|
|
||
|
// InfluxQL expression associated with series during filtering.
|
||
|
Expr() influxql.Expr
|
||
|
}
|
||
|
|
||
|
// SeriesElemKey encodes e as a series key.
|
||
|
func SeriesElemKey(e SeriesElem) []byte {
|
||
|
name, tags := e.Name(), e.Tags()
|
||
|
|
||
|
// TODO: Precompute allocation size.
|
||
|
// FIXME: Handle escaping.
|
||
|
|
||
|
var buf []byte
|
||
|
buf = append(buf, name...)
|
||
|
for _, t := range tags {
|
||
|
buf = append(buf, ',')
|
||
|
buf = append(buf, t.Key...)
|
||
|
buf = append(buf, '=')
|
||
|
buf = append(buf, t.Value...)
|
||
|
}
|
||
|
return buf
|
||
|
}
|
||
|
|
||
|
// CompareSeriesElem returns -1 if a < b, 1 if a > b, and 0 if equal.
|
||
|
func CompareSeriesElem(a, b SeriesElem) int {
|
||
|
if cmp := bytes.Compare(a.Name(), b.Name()); cmp != 0 {
|
||
|
return cmp
|
||
|
}
|
||
|
return models.CompareTags(a.Tags(), b.Tags())
|
||
|
}
|
||
|
|
||
|
// seriesElem represents an in-memory implementation of SeriesElem.
|
||
|
type seriesElem struct {
|
||
|
name []byte
|
||
|
tags models.Tags
|
||
|
deleted bool
|
||
|
}
|
||
|
|
||
|
func (e *seriesElem) Name() []byte { return e.name }
|
||
|
func (e *seriesElem) Tags() models.Tags { return e.tags }
|
||
|
func (e *seriesElem) Deleted() bool { return e.deleted }
|
||
|
func (e *seriesElem) Expr() influxql.Expr { return nil }
|
||
|
|
||
|
// SeriesIterator represents a iterator over a list of series.
|
||
|
type SeriesIterator interface {
|
||
|
Next() SeriesElem
|
||
|
}
|
||
|
|
||
|
// MergeSeriesIterators returns an iterator that merges a set of iterators.
|
||
|
// Iterators that are first in the list take precendence and a deletion by those
|
||
|
// early iterators will invalidate elements by later iterators.
|
||
|
func MergeSeriesIterators(itrs ...SeriesIterator) SeriesIterator {
|
||
|
if n := len(itrs); n == 0 {
|
||
|
return nil
|
||
|
} else if n == 1 {
|
||
|
return itrs[0]
|
||
|
}
|
||
|
|
||
|
return &seriesMergeIterator{
|
||
|
buf: make([]SeriesElem, len(itrs)),
|
||
|
itrs: itrs,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// seriesMergeIterator is an iterator that merges multiple iterators together.
|
||
|
type seriesMergeIterator struct {
|
||
|
buf []SeriesElem
|
||
|
itrs []SeriesIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the element with the next lowest name/tags across the iterators.
|
||
|
//
|
||
|
// If multiple iterators contain the same name/tags then the first is returned
|
||
|
// and the remaining ones are skipped.
|
||
|
func (itr *seriesMergeIterator) Next() SeriesElem {
|
||
|
// Find next lowest name/tags amongst the buffers.
|
||
|
var name []byte
|
||
|
var tags models.Tags
|
||
|
for i, buf := range itr.buf {
|
||
|
// Fill buffer.
|
||
|
if buf == nil {
|
||
|
if buf = itr.itrs[i].Next(); buf != nil {
|
||
|
itr.buf[i] = buf
|
||
|
} else {
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If the name is not set the pick the first non-empty name.
|
||
|
if name == nil {
|
||
|
name, tags = buf.Name(), buf.Tags()
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Set name/tags if they are lower than what has been seen.
|
||
|
if cmp := bytes.Compare(buf.Name(), name); cmp == -1 || (cmp == 0 && models.CompareTags(buf.Tags(), tags) == -1) {
|
||
|
name, tags = buf.Name(), buf.Tags()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return nil if no elements remaining.
|
||
|
if name == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Refill buffer.
|
||
|
var e SeriesElem
|
||
|
for i, buf := range itr.buf {
|
||
|
if buf == nil || !bytes.Equal(buf.Name(), name) || models.CompareTags(buf.Tags(), tags) != 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Copy first matching buffer to the return buffer.
|
||
|
if e == nil {
|
||
|
e = buf
|
||
|
}
|
||
|
|
||
|
// Clear buffer.
|
||
|
itr.buf[i] = nil
|
||
|
}
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// IntersectSeriesIterators returns an iterator that only returns series which
|
||
|
// occur in both iterators. If both series have associated expressions then
|
||
|
// they are combined together.
|
||
|
func IntersectSeriesIterators(itr0, itr1 SeriesIterator) SeriesIterator {
|
||
|
if itr0 == nil || itr1 == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return &seriesIntersectIterator{itrs: [2]SeriesIterator{itr0, itr1}}
|
||
|
}
|
||
|
|
||
|
// seriesIntersectIterator is an iterator that merges two iterators together.
|
||
|
type seriesIntersectIterator struct {
|
||
|
e seriesExprElem
|
||
|
buf [2]SeriesElem
|
||
|
itrs [2]SeriesIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the next element which occurs in both iterators.
|
||
|
func (itr *seriesIntersectIterator) Next() (e SeriesElem) {
|
||
|
for {
|
||
|
// Fill buffers.
|
||
|
if itr.buf[0] == nil {
|
||
|
itr.buf[0] = itr.itrs[0].Next()
|
||
|
}
|
||
|
if itr.buf[1] == nil {
|
||
|
itr.buf[1] = itr.itrs[1].Next()
|
||
|
}
|
||
|
|
||
|
// Exit if either buffer is still empty.
|
||
|
if itr.buf[0] == nil || itr.buf[1] == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Skip if both series are not equal.
|
||
|
if cmp := CompareSeriesElem(itr.buf[0], itr.buf[1]); cmp == -1 {
|
||
|
itr.buf[0] = nil
|
||
|
continue
|
||
|
} else if cmp == 1 {
|
||
|
itr.buf[1] = nil
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Merge series together if equal.
|
||
|
itr.e.SeriesElem = itr.buf[0]
|
||
|
|
||
|
// Attach expression.
|
||
|
expr0 := itr.buf[0].Expr()
|
||
|
expr1 := itr.buf[1].Expr()
|
||
|
if expr0 == nil {
|
||
|
itr.e.expr = expr1
|
||
|
} else if expr1 == nil {
|
||
|
itr.e.expr = expr0
|
||
|
} else {
|
||
|
itr.e.expr = influxql.Reduce(&influxql.BinaryExpr{
|
||
|
Op: influxql.AND,
|
||
|
LHS: expr0,
|
||
|
RHS: expr1,
|
||
|
}, nil)
|
||
|
}
|
||
|
|
||
|
itr.buf[0], itr.buf[1] = nil, nil
|
||
|
return &itr.e
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// UnionSeriesIterators returns an iterator that returns series from both
|
||
|
// both iterators. If both series have associated expressions then they are
|
||
|
// combined together.
|
||
|
func UnionSeriesIterators(itr0, itr1 SeriesIterator) SeriesIterator {
|
||
|
// Return other iterator if either one is nil.
|
||
|
if itr0 == nil {
|
||
|
return itr1
|
||
|
} else if itr1 == nil {
|
||
|
return itr0
|
||
|
}
|
||
|
|
||
|
return &seriesUnionIterator{itrs: [2]SeriesIterator{itr0, itr1}}
|
||
|
}
|
||
|
|
||
|
// seriesUnionIterator is an iterator that unions two iterators together.
|
||
|
type seriesUnionIterator struct {
|
||
|
e seriesExprElem
|
||
|
buf [2]SeriesElem
|
||
|
itrs [2]SeriesIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the next element which occurs in both iterators.
|
||
|
func (itr *seriesUnionIterator) Next() (e SeriesElem) {
|
||
|
// Fill buffers.
|
||
|
if itr.buf[0] == nil {
|
||
|
itr.buf[0] = itr.itrs[0].Next()
|
||
|
}
|
||
|
if itr.buf[1] == nil {
|
||
|
itr.buf[1] = itr.itrs[1].Next()
|
||
|
}
|
||
|
|
||
|
// Return the other iterator if either one is empty.
|
||
|
if itr.buf[0] == nil {
|
||
|
e, itr.buf[1] = itr.buf[1], nil
|
||
|
return e
|
||
|
} else if itr.buf[1] == nil {
|
||
|
e, itr.buf[0] = itr.buf[0], nil
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// Return lesser series.
|
||
|
if cmp := CompareSeriesElem(itr.buf[0], itr.buf[1]); cmp == -1 {
|
||
|
e, itr.buf[0] = itr.buf[0], nil
|
||
|
return e
|
||
|
} else if cmp == 1 {
|
||
|
e, itr.buf[1] = itr.buf[1], nil
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// Attach element.
|
||
|
itr.e.SeriesElem = itr.buf[0]
|
||
|
|
||
|
// Attach expression.
|
||
|
expr0 := itr.buf[0].Expr()
|
||
|
expr1 := itr.buf[1].Expr()
|
||
|
if expr0 != nil && expr1 != nil {
|
||
|
itr.e.expr = influxql.Reduce(&influxql.BinaryExpr{
|
||
|
Op: influxql.OR,
|
||
|
LHS: expr0,
|
||
|
RHS: expr1,
|
||
|
}, nil)
|
||
|
} else {
|
||
|
itr.e.expr = nil
|
||
|
}
|
||
|
|
||
|
itr.buf[0], itr.buf[1] = nil, nil
|
||
|
return &itr.e
|
||
|
}
|
||
|
|
||
|
// DifferenceSeriesIterators returns an iterator that only returns series which
|
||
|
// occur the first iterator but not the second iterator.
|
||
|
func DifferenceSeriesIterators(itr0, itr1 SeriesIterator) SeriesIterator {
|
||
|
if itr0 != nil && itr1 == nil {
|
||
|
return itr0
|
||
|
} else if itr0 == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return &seriesDifferenceIterator{itrs: [2]SeriesIterator{itr0, itr1}}
|
||
|
}
|
||
|
|
||
|
// seriesDifferenceIterator is an iterator that merges two iterators together.
|
||
|
type seriesDifferenceIterator struct {
|
||
|
buf [2]SeriesElem
|
||
|
itrs [2]SeriesIterator
|
||
|
}
|
||
|
|
||
|
// Next returns the next element which occurs only in the first iterator.
|
||
|
func (itr *seriesDifferenceIterator) Next() (e SeriesElem) {
|
||
|
for {
|
||
|
// Fill buffers.
|
||
|
if itr.buf[0] == nil {
|
||
|
itr.buf[0] = itr.itrs[0].Next()
|
||
|
}
|
||
|
if itr.buf[1] == nil {
|
||
|
itr.buf[1] = itr.itrs[1].Next()
|
||
|
}
|
||
|
|
||
|
// Exit if first buffer is still empty.
|
||
|
if itr.buf[0] == nil {
|
||
|
return nil
|
||
|
} else if itr.buf[1] == nil {
|
||
|
e, itr.buf[0] = itr.buf[0], nil
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// Return first series if it's less.
|
||
|
// If second series is less then skip it.
|
||
|
// If both series are equal then skip both.
|
||
|
if cmp := CompareSeriesElem(itr.buf[0], itr.buf[1]); cmp == -1 {
|
||
|
e, itr.buf[0] = itr.buf[0], nil
|
||
|
return e
|
||
|
} else if cmp == 1 {
|
||
|
itr.buf[1] = nil
|
||
|
continue
|
||
|
} else {
|
||
|
itr.buf[0], itr.buf[1] = nil, nil
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// filterUndeletedSeriesIterator returns all series which are not deleted.
|
||
|
type filterUndeletedSeriesIterator struct {
|
||
|
itr SeriesIterator
|
||
|
}
|
||
|
|
||
|
// FilterUndeletedSeriesIterator returns an iterator which filters all deleted series.
|
||
|
func FilterUndeletedSeriesIterator(itr SeriesIterator) SeriesIterator {
|
||
|
if itr == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return &filterUndeletedSeriesIterator{itr: itr}
|
||
|
}
|
||
|
|
||
|
func (itr *filterUndeletedSeriesIterator) Next() SeriesElem {
|
||
|
for {
|
||
|
e := itr.itr.Next()
|
||
|
if e == nil {
|
||
|
return nil
|
||
|
} else if e.Deleted() {
|
||
|
continue
|
||
|
}
|
||
|
return e
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// seriesExprElem holds a series and its associated filter expression.
|
||
|
type seriesExprElem struct {
|
||
|
SeriesElem
|
||
|
expr influxql.Expr
|
||
|
}
|
||
|
|
||
|
// Expr returns the associated expression.
|
||
|
func (e *seriesExprElem) Expr() influxql.Expr { return e.expr }
|
||
|
|
||
|
// seriesExprIterator is an iterator that attaches an associated expression.
|
||
|
type seriesExprIterator struct {
|
||
|
itr SeriesIterator
|
||
|
e seriesExprElem
|
||
|
}
|
||
|
|
||
|
// newSeriesExprIterator returns a new instance of seriesExprIterator.
|
||
|
func newSeriesExprIterator(itr SeriesIterator, expr influxql.Expr) SeriesIterator {
|
||
|
if itr == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return &seriesExprIterator{
|
||
|
itr: itr,
|
||
|
e: seriesExprElem{
|
||
|
expr: expr,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Next returns the next element in the iterator.
|
||
|
func (itr *seriesExprIterator) Next() SeriesElem {
|
||
|
itr.e.SeriesElem = itr.itr.Next()
|
||
|
if itr.e.SeriesElem == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return &itr.e
|
||
|
}
|
||
|
|
||
|
// seriesIDIterator represents a iterator over a list of series ids.
|
||
|
type seriesIDIterator interface {
|
||
|
next() uint32
|
||
|
}
|
||
|
|
||
|
// writeTo writes write v into w. Updates n.
|
||
|
func writeTo(w io.Writer, v []byte, n *int64) error {
|
||
|
nn, err := w.Write(v)
|
||
|
*n += int64(nn)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// writeUint8To writes write v into w. Updates n.
|
||
|
func writeUint8To(w io.Writer, v uint8, n *int64) error {
|
||
|
nn, err := w.Write([]byte{v})
|
||
|
*n += int64(nn)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// writeUint16To writes write v into w using big endian encoding. Updates n.
|
||
|
func writeUint16To(w io.Writer, v uint16, n *int64) error {
|
||
|
var buf [2]byte
|
||
|
binary.BigEndian.PutUint16(buf[:], v)
|
||
|
nn, err := w.Write(buf[:])
|
||
|
*n += int64(nn)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// writeUint32To writes write v into w using big endian encoding. Updates n.
|
||
|
func writeUint32To(w io.Writer, v uint32, n *int64) error {
|
||
|
var buf [4]byte
|
||
|
binary.BigEndian.PutUint32(buf[:], v)
|
||
|
nn, err := w.Write(buf[:])
|
||
|
*n += int64(nn)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// writeUint64To writes write v into w using big endian encoding. Updates n.
|
||
|
func writeUint64To(w io.Writer, v uint64, n *int64) error {
|
||
|
var buf [8]byte
|
||
|
binary.BigEndian.PutUint64(buf[:], v)
|
||
|
nn, err := w.Write(buf[:])
|
||
|
*n += int64(nn)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// writeUvarintTo writes write v into w using variable length encoding. Updates n.
|
||
|
func writeUvarintTo(w io.Writer, v uint64, n *int64) error {
|
||
|
var buf [binary.MaxVarintLen64]byte
|
||
|
i := binary.PutUvarint(buf[:], v)
|
||
|
nn, err := w.Write(buf[:i])
|
||
|
*n += int64(nn)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
type uint32Slice []uint32
|
||
|
|
||
|
func (a uint32Slice) Len() int { return len(a) }
|
||
|
func (a uint32Slice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||
|
func (a uint32Slice) Less(i, j int) bool { return a[i] < a[j] }
|
||
|
|
||
|
type uint64Slice []uint64
|
||
|
|
||
|
func (a uint64Slice) Len() int { return len(a) }
|
||
|
func (a uint64Slice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||
|
func (a uint64Slice) Less(i, j int) bool { return a[i] < a[j] }
|
||
|
|
||
|
type byteSlices [][]byte
|
||
|
|
||
|
func (a byteSlices) Len() int { return len(a) }
|
||
|
func (a byteSlices) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||
|
func (a byteSlices) Less(i, j int) bool { return bytes.Compare(a[i], a[j]) == -1 }
|
||
|
|
||
|
// copyBytes returns a copy of b.
|
||
|
func copyBytes(b []byte) []byte {
|
||
|
if b == nil {
|
||
|
return nil
|
||
|
}
|
||
|
buf := make([]byte, len(b))
|
||
|
copy(buf, b)
|
||
|
return buf
|
||
|
}
|
||
|
|
||
|
// assert will panic with a given formatted message if the given condition is false.
|
||
|
func assert(condition bool, msg string, v ...interface{}) {
|
||
|
if !condition {
|
||
|
panic(fmt.Sprintf("assert failed: "+msg, v...))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type byTagKey []*influxql.TagSet
|
||
|
|
||
|
func (t byTagKey) Len() int { return len(t) }
|
||
|
func (t byTagKey) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) < 0 }
|
||
|
func (t byTagKey) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
|
||
|
|
||
|
// hexdump is a helper for dumping binary data to stderr.
|
||
|
func hexdump(data []byte) { os.Stderr.Write([]byte(hex.Dump(data))) }
|