| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | package tsdb | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/fabxc/tsdb/chunks" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | // Matcher matches a string.
 | 
					
						
							|  |  |  | type Matcher interface { | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	Name() string | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | 	// Match returns true if the matcher applies to the string value.
 | 
					
						
							|  |  |  | 	Match(v string) bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | type equalMatcher struct { | 
					
						
							|  |  |  | 	name  string | 
					
						
							|  |  |  | 	value string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func MatchEquals(n, v string) Matcher { | 
					
						
							|  |  |  | 	return &equalMatcher{name: n, value: v} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (m *equalMatcher) Name() string        { return m.name } | 
					
						
							|  |  |  | func (m *equalMatcher) Match(v string) bool { return v == m.value } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | // Querier provides querying access over time series data of a fixed
 | 
					
						
							|  |  |  | // time range.
 | 
					
						
							|  |  |  | type Querier interface { | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	// Select returns a set of series that matches the given label matchers.
 | 
					
						
							|  |  |  | 	Select(...Matcher) SeriesSet | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// LabelValues returns all potential values for a label name.
 | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 	LabelValues(string) ([]string, error) | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | 	// LabelValuesFor returns all potential values for a label name.
 | 
					
						
							|  |  |  | 	// under the constraint of another label.
 | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 	LabelValuesFor(string, Label) ([]string, error) | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Close releases the resources of the Querier.
 | 
					
						
							|  |  |  | 	Close() error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Series represents a single time series.
 | 
					
						
							|  |  |  | type Series interface { | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 	// Labels returns the complete set of labels identifying the series.
 | 
					
						
							|  |  |  | 	Labels() Labels | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | 	// Iterator returns a new iterator of the data of the series.
 | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 	Iterator() SeriesIterator | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Ref() uint32
 | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // querier merges query results from a set of shard querieres.
 | 
					
						
							|  |  |  | type querier struct { | 
					
						
							|  |  |  | 	mint, maxt int64 | 
					
						
							|  |  |  | 	shards     []Querier | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Querier returns a new querier over the database for the given
 | 
					
						
							|  |  |  | // time range.
 | 
					
						
							|  |  |  | func (db *DB) Querier(mint, maxt int64) Querier { | 
					
						
							|  |  |  | 	q := &querier{ | 
					
						
							|  |  |  | 		mint: mint, | 
					
						
							|  |  |  | 		maxt: maxt, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, s := range db.shards { | 
					
						
							|  |  |  | 		q.shards = append(q.shards, s.Querier(mint, maxt)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return q | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | func (q *querier) Select(ms ...Matcher) SeriesSet { | 
					
						
							|  |  |  | 	// We gather the non-overlapping series from every shard and simply
 | 
					
						
							|  |  |  | 	// return their union.
 | 
					
						
							|  |  |  | 	r := &mergedSeriesSet{} | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	for _, s := range q.shards { | 
					
						
							|  |  |  | 		r.sets = append(r.sets, s.Select(ms...)) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	if len(r.sets) == 0 { | 
					
						
							|  |  |  | 		return nopSeriesSet{} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	return r | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *querier) LabelValues(string) ([]string, error) { | 
					
						
							|  |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *querier) LabelValuesFor(string, Label) ([]string, error) { | 
					
						
							|  |  |  | 	return nil, fmt.Errorf("not implemented") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *querier) Close() error { | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // shardQuerier aggregates querying results from time blocks within
 | 
					
						
							|  |  |  | // a single shard.
 | 
					
						
							|  |  |  | type shardQuerier struct { | 
					
						
							|  |  |  | 	blocks []Querier | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Querier returns a new querier over the data shard for the given
 | 
					
						
							|  |  |  | // time range.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 15:36:09 +08:00
										 |  |  | func (s *Shard) Querier(mint, maxt int64) Querier { | 
					
						
							| 
									
										
										
										
											2016-12-15 23:14:33 +08:00
										 |  |  | 	blocks := s.blocksForInterval(mint, maxt) | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sq := &shardQuerier{ | 
					
						
							|  |  |  | 		blocks: make([]Querier, 0, len(blocks)), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, b := range blocks { | 
					
						
							|  |  |  | 		sq.blocks = append(sq.blocks, b.Querier(mint, maxt)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sq | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (q *shardQuerier) LabelValues(string) ([]string, error) { | 
					
						
							|  |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *shardQuerier) LabelValuesFor(string, Label) ([]string, error) { | 
					
						
							|  |  |  | 	return nil, fmt.Errorf("not implemented") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *shardQuerier) Close() error { | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // blockQuerier provides querying access to a single block database.
 | 
					
						
							|  |  |  | type blockQuerier struct { | 
					
						
							|  |  |  | 	index  IndexReader | 
					
						
							|  |  |  | 	series SeriesReader | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mint, maxt int64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newBlockQuerier(ix IndexReader, s SeriesReader, mint, maxt int64) *blockQuerier { | 
					
						
							|  |  |  | 	return &blockQuerier{ | 
					
						
							|  |  |  | 		mint:   mint, | 
					
						
							|  |  |  | 		maxt:   maxt, | 
					
						
							|  |  |  | 		index:  ix, | 
					
						
							|  |  |  | 		series: s, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *blockQuerier) Select(ms ...Matcher) SeriesSet { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 	var its []Postings | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	for _, m := range ms { | 
					
						
							|  |  |  | 		its = append(its, q.selectSingle(m)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO(fabxc): pass down time range so the series iterator
 | 
					
						
							|  |  |  | 	// can be instantiated with it?
 | 
					
						
							|  |  |  | 	return &blockSeriesSet{ | 
					
						
							|  |  |  | 		index: q.index, | 
					
						
							|  |  |  | 		it:    Intersect(its...), | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 		mint:  q.mint, | 
					
						
							|  |  |  | 		maxt:  q.maxt, | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | func (q *blockQuerier) selectSingle(m Matcher) Postings { | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	tpls, err := q.index.LabelValues(m.Name()) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 		return errPostings{err: err} | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// TODO(fabxc): use interface upgrading to provide fast solution
 | 
					
						
							|  |  |  | 	// for equality and prefix matches. Tuples are lexicographically sorted.
 | 
					
						
							|  |  |  | 	var res []string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < tpls.Len(); i++ { | 
					
						
							|  |  |  | 		vals, err := tpls.At(i) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 			return errPostings{err: err} | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if m.Match(vals[0]) { | 
					
						
							|  |  |  | 			res = append(res, vals[0]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(res) == 0 { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 		return errPostings{err: nil} | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 	var rit []Postings | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for _, v := range res { | 
					
						
							|  |  |  | 		it, err := q.index.Postings(m.Name(), v) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 			return errPostings{err: err} | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		rit = append(rit, it) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Intersect(rit...) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *blockQuerier) LabelValues(name string) ([]string, error) { | 
					
						
							|  |  |  | 	tpls, err := q.index.LabelValues(name) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	res := make([]string, 0, tpls.Len()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < tpls.Len(); i++ { | 
					
						
							|  |  |  | 		vals, err := tpls.At(i) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		res = append(res, vals[0]) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *blockQuerier) LabelValuesFor(string, Label) ([]string, error) { | 
					
						
							|  |  |  | 	return nil, fmt.Errorf("not implemented") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q *blockQuerier) Close() error { | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SeriesSet contains a set of series.
 | 
					
						
							|  |  |  | type SeriesSet interface { | 
					
						
							|  |  |  | 	Next() bool | 
					
						
							|  |  |  | 	Series() Series | 
					
						
							|  |  |  | 	Err() error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type nopSeriesSet struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (nopSeriesSet) Next() bool     { return false } | 
					
						
							|  |  |  | func (nopSeriesSet) Series() Series { return nil } | 
					
						
							|  |  |  | func (nopSeriesSet) Err() error     { return nil } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | type mergedSeriesSet struct { | 
					
						
							|  |  |  | 	sets []SeriesSet | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	cur int | 
					
						
							|  |  |  | 	err error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *mergedSeriesSet) Series() Series { return s.sets[s.cur].Series() } | 
					
						
							|  |  |  | func (s *mergedSeriesSet) Err() error     { return s.sets[s.cur].Err() } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *mergedSeriesSet) Next() bool { | 
					
						
							|  |  |  | 	// TODO(fabxc): We just emit the sets one after one. They are each
 | 
					
						
							|  |  |  | 	// lexicographically sorted. Should we emit their union sorted too?
 | 
					
						
							|  |  |  | 	if s.sets[s.cur].Next() { | 
					
						
							|  |  |  | 		return true | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	if s.cur == len(s.sets)-1 { | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	s.cur++ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	return s.Next() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (q *shardQuerier) Select(ms ...Matcher) SeriesSet { | 
					
						
							|  |  |  | 	// Sets from different blocks have no time overlap. The reference numbers
 | 
					
						
							|  |  |  | 	// they emit point to series sorted in lexicographic order.
 | 
					
						
							|  |  |  | 	// We can fully connect partial series by simply comparing with the previous
 | 
					
						
							|  |  |  | 	// label set.
 | 
					
						
							|  |  |  | 	if len(q.blocks) == 0 { | 
					
						
							|  |  |  | 		return nopSeriesSet{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	r := q.blocks[0].Select(ms...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range q.blocks[1:] { | 
					
						
							|  |  |  | 		r = &shardSeriesSet{a: r, b: s.Select(ms...)} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | type shardSeriesSet struct { | 
					
						
							|  |  |  | 	a, b SeriesSet | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cur    Series | 
					
						
							|  |  |  | 	as, bs Series // peek ahead of each set
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newShardSeriesSet(a, b SeriesSet) *shardSeriesSet { | 
					
						
							|  |  |  | 	s := &shardSeriesSet{a: a, b: b} | 
					
						
							|  |  |  | 	// Initialize first elements of both sets as Next() needs
 | 
					
						
							|  |  |  | 	// one element look-ahead.
 | 
					
						
							|  |  |  | 	s.advanceA() | 
					
						
							|  |  |  | 	s.advanceB() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return s | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // compareLabels compares the two label sets.
 | 
					
						
							|  |  |  | // The result will be 0 if a==b, <0 if a < b, and >0 if a > b.
 | 
					
						
							|  |  |  | func compareLabels(a, b Labels) int { | 
					
						
							|  |  |  | 	l := len(a) | 
					
						
							|  |  |  | 	if len(b) < l { | 
					
						
							|  |  |  | 		l = len(b) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < l; i++ { | 
					
						
							|  |  |  | 		if d := strings.Compare(a[i].Name, b[i].Name); d != 0 { | 
					
						
							|  |  |  | 			return d | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// If all labels so far were in common, the set with fewer labels comes first.
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:47:05 +08:00
										 |  |  | 	return len(a) - len(b) | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *shardSeriesSet) Series() Series { | 
					
						
							|  |  |  | 	return s.cur | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | func (s *shardSeriesSet) Err() error { | 
					
						
							|  |  |  | 	if s.a.Err() != nil { | 
					
						
							|  |  |  | 		return s.a.Err() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return s.b.Err() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | func (s *shardSeriesSet) compare() int { | 
					
						
							|  |  |  | 	if s.as == nil { | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if s.bs == nil { | 
					
						
							|  |  |  | 		return -1 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return compareLabels(s.as.Labels(), s.bs.Labels()) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | func (s *shardSeriesSet) advanceA() { | 
					
						
							|  |  |  | 	if s.a.Next() { | 
					
						
							|  |  |  | 		s.as = s.a.Series() | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		s.as = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | func (s *shardSeriesSet) advanceB() { | 
					
						
							|  |  |  | 	if s.b.Next() { | 
					
						
							|  |  |  | 		s.bs = s.b.Series() | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		s.bs = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *shardSeriesSet) Next() bool { | 
					
						
							|  |  |  | 	if s.as == nil && s.bs == nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d := s.compare() | 
					
						
							|  |  |  | 	// Both sets contain the current series. Chain them into a single one.
 | 
					
						
							|  |  |  | 	if d > 0 { | 
					
						
							|  |  |  | 		s.cur = s.bs | 
					
						
							|  |  |  | 		s.advanceB() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if d < 0 { | 
					
						
							|  |  |  | 		s.cur = s.as | 
					
						
							|  |  |  | 		s.advanceA() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		s.cur = &chainedSeries{series: []Series{s.as, s.bs}} | 
					
						
							|  |  |  | 		s.advanceA() | 
					
						
							|  |  |  | 		s.advanceB() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // blockSeriesSet is a set of series from an inverted index query.
 | 
					
						
							|  |  |  | type blockSeriesSet struct { | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	index      IndexReader | 
					
						
							|  |  |  | 	it         Postings | 
					
						
							|  |  |  | 	mint, maxt int64 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err error | 
					
						
							|  |  |  | 	cur Series | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *blockSeriesSet) Next() bool { | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	// Step through the postings iterator to find potential series.
 | 
					
						
							|  |  |  | 	// Resolving series may return nil if no applicable data for the
 | 
					
						
							|  |  |  | 	// time range exists and we can skip to the next series.
 | 
					
						
							|  |  |  | 	for s.it.Next() { | 
					
						
							|  |  |  | 		series, err := s.index.Series(s.it.Value(), s.mint, s.maxt) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			s.err = err | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if series != nil { | 
					
						
							|  |  |  | 			s.cur = series | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	if s.it.Err() != nil { | 
					
						
							|  |  |  | 		s.err = s.it.Err() | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	return false | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *blockSeriesSet) Series() Series { return s.cur } | 
					
						
							|  |  |  | func (s *blockSeriesSet) Err() error     { return s.err } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | type series struct { | 
					
						
							|  |  |  | 	labels Labels | 
					
						
							|  |  |  | 	chunks []ChunkMeta // in-order chunk refs
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	chunk func(ref uint32) (chunks.Chunk, error) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *series) Labels() Labels { | 
					
						
							|  |  |  | 	return s.labels | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *series) Iterator() SeriesIterator { | 
					
						
							|  |  |  | 	var cs []chunks.Chunk | 
					
						
							|  |  |  | 	var mints []int64 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, co := range s.chunks { | 
					
						
							|  |  |  | 		c, err := s.chunk(co.Ref) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			panic(err) // TODO(fabxc): add error series iterator.
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cs = append(cs, c) | 
					
						
							|  |  |  | 		mints = append(mints, co.MinTime) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO(fabxc): consider pushing chunk retrieval further down. In practice, we
 | 
					
						
							|  |  |  | 	// probably have to touch all chunks anyway and it doesn't matter.
 | 
					
						
							|  |  |  | 	return newChunkSeriesIterator(mints, cs) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 01:08:50 +08:00
										 |  |  | // SeriesIterator iterates over the data of a time series.
 | 
					
						
							|  |  |  | type SeriesIterator interface { | 
					
						
							|  |  |  | 	// Seek advances the iterator forward to the given timestamp.
 | 
					
						
							|  |  |  | 	// If there's no value exactly at ts, it advances to the last value
 | 
					
						
							|  |  |  | 	// before tt.
 | 
					
						
							|  |  |  | 	Seek(t int64) bool | 
					
						
							|  |  |  | 	// Values returns the current timestamp/value pair.
 | 
					
						
							|  |  |  | 	Values() (t int64, v float64) | 
					
						
							|  |  |  | 	// Next advances the iterator by one.
 | 
					
						
							|  |  |  | 	Next() bool | 
					
						
							|  |  |  | 	// Err returns the current error.
 | 
					
						
							|  |  |  | 	Err() error | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | // chainedSeries implements a series for a list of time-sorted series.
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | type chainedSeries struct { | 
					
						
							|  |  |  | 	series []Series | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *chainedSeries) Labels() Labels { | 
					
						
							|  |  |  | 	return s.series[0].Labels() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *chainedSeries) Iterator() SeriesIterator { | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	return &chainedSeriesIterator{series: s.series} | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // chainedSeriesIterator implements a series iterater over a list
 | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | // of time-sorted, non-overlapping iterators.
 | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | type chainedSeriesIterator struct { | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	series []Series // series in time order
 | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	i   int | 
					
						
							|  |  |  | 	cur SeriesIterator | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *chainedSeriesIterator) Seek(t int64) bool { | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	// We just scan the chained series sequentially as they are already
 | 
					
						
							|  |  |  | 	// pre-selected by relevant time and should be accessed sequentially anyway.
 | 
					
						
							|  |  |  | 	for i, s := range it.series[it.i:] { | 
					
						
							|  |  |  | 		cur := s.Iterator() | 
					
						
							|  |  |  | 		if !cur.Seek(t) { | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 		it.cur = cur | 
					
						
							|  |  |  | 		it.i += i | 
					
						
							|  |  |  | 		return true | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | func (it *chainedSeriesIterator) Next() bool { | 
					
						
							|  |  |  | 	if it.cur.Next() { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := it.cur.Err(); err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if it.i == len(it.series)-1 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	it.i++ | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 	it.cur = it.series[it.i].Iterator() | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return it.Next() | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | func (it *chainedSeriesIterator) Values() (t int64, v float64) { | 
					
						
							|  |  |  | 	return it.cur.Values() | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *chainedSeriesIterator) Err() error { | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 	return it.cur.Err() | 
					
						
							| 
									
										
										
										
											2016-12-14 22:39:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | // chunkSeriesIterator implements a series iterator on top
 | 
					
						
							|  |  |  | // of a list of time-sorted, non-overlapping chunks.
 | 
					
						
							|  |  |  | type chunkSeriesIterator struct { | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 	mints  []int64 // minimum timestamps for each iterator
 | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | 	chunks []chunks.Chunk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i   int | 
					
						
							|  |  |  | 	cur chunks.Iterator | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | func newChunkSeriesIterator(mints []int64, cs []chunks.Chunk) *chunkSeriesIterator { | 
					
						
							|  |  |  | 	if len(mints) != len(cs) { | 
					
						
							|  |  |  | 		panic("chunk references and chunks length don't match") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | 	return &chunkSeriesIterator{ | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 		mints:  mints, | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | 		chunks: cs, | 
					
						
							|  |  |  | 		i:      0, | 
					
						
							|  |  |  | 		cur:    cs[0].Iterator(), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *chunkSeriesIterator) Seek(t int64) (ok bool) { | 
					
						
							| 
									
										
										
										
											2016-12-15 22:23:15 +08:00
										 |  |  | 	x := sort.Search(len(it.mints), func(i int) bool { return it.mints[i] >= t }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if x == len(it.mints) { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if it.mints[x] == t { | 
					
						
							|  |  |  | 		if x == 0 { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		x-- | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	it.i = x | 
					
						
							|  |  |  | 	it.cur = it.chunks[x].Iterator() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for it.cur.Next() { | 
					
						
							|  |  |  | 		t0, _ := it.cur.Values() | 
					
						
							|  |  |  | 		if t0 >= t { | 
					
						
							| 
									
										
										
										
											2016-12-16 19:13:17 +08:00
										 |  |  | 			return true | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *chunkSeriesIterator) Values() (t int64, v float64) { | 
					
						
							|  |  |  | 	return it.cur.Values() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *chunkSeriesIterator) Next() bool { | 
					
						
							|  |  |  | 	if it.cur.Next() { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := it.cur.Err(); err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if it.i == len(it.chunks)-1 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	it.i++ | 
					
						
							|  |  |  | 	it.cur = it.chunks[it.i].Iterator() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return it.Next() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *chunkSeriesIterator) Err() error { | 
					
						
							|  |  |  | 	return it.cur.Err() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // BufferedSeriesIterator wraps an iterator with a look-back buffer.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | type BufferedSeriesIterator struct { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	it  SeriesIterator | 
					
						
							|  |  |  | 	buf *sampleRing | 
					
						
							| 
									
										
										
										
											2016-12-13 22:26:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // NewBuffer returns a new iterator that buffers the values within the time range
 | 
					
						
							|  |  |  | // of the current element and the duration of delta before.
 | 
					
						
							|  |  |  | func NewBuffer(it SeriesIterator, delta int64) *BufferedSeriesIterator { | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	return &BufferedSeriesIterator{ | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 		it:  it, | 
					
						
							|  |  |  | 		buf: newSampleRing(delta, 16), | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // PeekBack returns the previous element of the iterator. If there is none buffered,
 | 
					
						
							|  |  |  | // ok is false.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (b *BufferedSeriesIterator) PeekBack() (t int64, v float64, ok bool) { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	return b.buf.last() | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // Seek advances the iterator to the element at time t or greater.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (b *BufferedSeriesIterator) Seek(t int64) bool { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	tcur, _ := b.it.Values() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t0 := t - b.buf.delta | 
					
						
							|  |  |  | 	// If the delta would cause us to seek backwards, preserve the buffer
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:43:08 +08:00
										 |  |  | 	// and just continue regular advancment while filling the buffer on the way.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	if t0 <= tcur { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:43:08 +08:00
										 |  |  | 		for b.Next() { | 
					
						
							|  |  |  | 			if tcur, _ = b.it.Values(); tcur >= t { | 
					
						
							|  |  |  | 				return true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.buf.reset() | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ok := b.it.Seek(t0) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	b.buf.add(b.it.Values()) | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for b.Next() { | 
					
						
							|  |  |  | 		if ts, _ := b.Values(); ts >= t { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // Next advances the iterator to the next element.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (b *BufferedSeriesIterator) Next() bool { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 	// Add current element to buffer before advancing.
 | 
					
						
							|  |  |  | 	b.buf.add(b.it.Values()) | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return b.it.Next() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // Values returns the current element of the iterator.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (b *BufferedSeriesIterator) Values() (int64, float64) { | 
					
						
							|  |  |  | 	return b.it.Values() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | // Err returns the last encountered error.
 | 
					
						
							| 
									
										
										
										
											2016-12-15 01:38:46 +08:00
										 |  |  | func (b *BufferedSeriesIterator) Err() error { | 
					
						
							|  |  |  | 	return b.it.Err() | 
					
						
							| 
									
										
										
										
											2016-12-13 02:12:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type sample struct { | 
					
						
							|  |  |  | 	t int64 | 
					
						
							|  |  |  | 	v float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type sampleRing struct { | 
					
						
							|  |  |  | 	delta int64 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf []sample // lookback buffer
 | 
					
						
							|  |  |  | 	i   int      // position of most recent element in ring buffer
 | 
					
						
							|  |  |  | 	f   int      // position of first element in ring buffer
 | 
					
						
							|  |  |  | 	l   int      // number of elements in buffer
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newSampleRing(delta int64, sz int) *sampleRing { | 
					
						
							|  |  |  | 	r := &sampleRing{delta: delta, buf: make([]sample, sz)} | 
					
						
							|  |  |  | 	r.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *sampleRing) reset() { | 
					
						
							|  |  |  | 	r.l = 0 | 
					
						
							|  |  |  | 	r.i = -1 | 
					
						
							|  |  |  | 	r.f = 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // add adds a sample to the ring buffer and frees all samples that fall
 | 
					
						
							|  |  |  | // out of the delta range.
 | 
					
						
							|  |  |  | func (r *sampleRing) add(t int64, v float64) { | 
					
						
							|  |  |  | 	l := len(r.buf) | 
					
						
							|  |  |  | 	// Grow the ring buffer if it fits no more elements.
 | 
					
						
							|  |  |  | 	if l == r.l { | 
					
						
							|  |  |  | 		buf := make([]sample, 2*l) | 
					
						
							|  |  |  | 		copy(buf[l+r.f:], r.buf[r.f:]) | 
					
						
							|  |  |  | 		copy(buf, r.buf[:r.f]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r.buf = buf | 
					
						
							|  |  |  | 		r.i = r.f | 
					
						
							|  |  |  | 		r.f += l | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		r.i++ | 
					
						
							|  |  |  | 		if r.i >= l { | 
					
						
							|  |  |  | 			r.i -= l | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r.buf[r.i] = sample{t: t, v: v} | 
					
						
							|  |  |  | 	r.l++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Free head of the buffer of samples that just fell out of the range.
 | 
					
						
							|  |  |  | 	for r.buf[r.f].t < t-r.delta { | 
					
						
							|  |  |  | 		r.f++ | 
					
						
							|  |  |  | 		if r.f >= l { | 
					
						
							|  |  |  | 			r.f -= l | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		r.l-- | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // last returns the most recent element added to the ring.
 | 
					
						
							|  |  |  | func (r *sampleRing) last() (int64, float64, bool) { | 
					
						
							|  |  |  | 	if r.l == 0 { | 
					
						
							|  |  |  | 		return 0, 0, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	s := r.buf[r.i] | 
					
						
							|  |  |  | 	return s.t, s.v, true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *sampleRing) samples() []sample { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 	res := make([]sample, r.l) | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var k = r.f + r.l | 
					
						
							|  |  |  | 	var j int | 
					
						
							|  |  |  | 	if k > len(r.buf) { | 
					
						
							|  |  |  | 		k = len(r.buf) | 
					
						
							|  |  |  | 		j = r.l - k + r.f | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 04:58:29 +08:00
										 |  |  | 	n := copy(res, r.buf[r.f:k]) | 
					
						
							|  |  |  | 	copy(res[n:], r.buf[:j]) | 
					
						
							| 
									
										
										
										
											2016-12-15 04:14:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | } |