2018-10-03 18:34:34 +00:00
|
|
|
package storage
|
2018-09-25 00:52:40 +00:00
|
|
|
|
|
|
|
import (
|
2019-02-15 21:30:50 +00:00
|
|
|
"bytes"
|
2018-09-25 00:52:40 +00:00
|
|
|
"errors"
|
|
|
|
"sort"
|
|
|
|
|
2019-02-19 22:10:33 +00:00
|
|
|
"github.com/influxdata/influxdb"
|
2019-01-08 00:37:16 +00:00
|
|
|
"github.com/influxdata/influxdb/models"
|
storage: fix problems with keeping resources alive
This commit adds the pkg/lifecycle.Resource to help manage opening,
closing, and leasing out references to some resource. A resource
cannot be closed until all acquired references have been released.
If the debug_ref tag is enabled, all resource acquisitions keep
track of the stack trace that created them and have a finalizer
associated with them to print on stderr if they are leaked. It also
registers a handler on SIGUSR2 to dump all of the currently live
resources.
Having resources tracked in a uniform way with a data type allows us
to do more sophisticated tracking with the debug_ref tag, as well.
For example, we could panic the process if a resource cannot be
closed within a certain time frame, or attempt to figure out the
DAG of resource ownership dynamically.
This commit also fixes many issues around resources, correctness
during error scenarios, reporting of errors, idempotency of
close, tracking of memory for some data structures, resource leaks
in tests, and out of order dependency closes in tests.
2019-02-25 23:51:08 +00:00
|
|
|
"github.com/influxdata/influxdb/pkg/lifecycle"
|
2019-01-08 00:37:16 +00:00
|
|
|
"github.com/influxdata/influxdb/tsdb"
|
|
|
|
"github.com/influxdata/influxdb/tsdb/tsi1"
|
2018-09-25 00:52:40 +00:00
|
|
|
"github.com/influxdata/influxql"
|
|
|
|
)
|
|
|
|
|
2019-02-15 21:30:50 +00:00
|
|
|
var (
|
|
|
|
errUnexpectedOrg = errors.New("seriesCursor: unexpected org")
|
|
|
|
errUnexpectedTagComparisonOperator = errors.New("seriesCursor: unexpected tag comparison operator")
|
|
|
|
)
|
|
|
|
|
2018-09-25 00:52:40 +00:00
|
|
|
type SeriesCursor interface {
|
|
|
|
Close() error
|
|
|
|
Next() (*SeriesCursorRow, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type SeriesCursorRequest struct {
|
2019-02-15 21:30:50 +00:00
|
|
|
// Name contains the tsdb encoded org and bucket ID
|
2019-02-19 22:10:33 +00:00
|
|
|
Name [influxdb.IDLength]byte
|
2018-09-25 00:52:40 +00:00
|
|
|
}
|
|
|
|
|
2018-10-23 07:32:11 +00:00
|
|
|
// seriesCursor is an implementation of SeriesCursor over an tsi1.Index.
|
2018-09-25 00:52:40 +00:00
|
|
|
type seriesCursor struct {
|
storage: fix problems with keeping resources alive
This commit adds the pkg/lifecycle.Resource to help manage opening,
closing, and leasing out references to some resource. A resource
cannot be closed until all acquired references have been released.
If the debug_ref tag is enabled, all resource acquisitions keep
track of the stack trace that created them and have a finalizer
associated with them to print on stderr if they are leaked. It also
registers a handler on SIGUSR2 to dump all of the currently live
resources.
Having resources tracked in a uniform way with a data type allows us
to do more sophisticated tracking with the debug_ref tag, as well.
For example, we could panic the process if a resource cannot be
closed within a certain time frame, or attempt to figure out the
DAG of resource ownership dynamically.
This commit also fixes many issues around resources, correctness
during error scenarios, reporting of errors, idempotency of
close, tracking of memory for some data structures, resource leaks
in tests, and out of order dependency closes in tests.
2019-02-25 23:51:08 +00:00
|
|
|
index *tsi1.Index
|
|
|
|
indexref *lifecycle.Reference
|
|
|
|
sfile *tsdb.SeriesFile
|
|
|
|
sfileref *lifecycle.Reference
|
|
|
|
name [influxdb.IDLength]byte
|
|
|
|
keys [][]byte
|
|
|
|
ofs int
|
|
|
|
row SeriesCursorRow
|
|
|
|
cond influxql.Expr
|
|
|
|
init bool
|
2018-09-25 00:52:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type SeriesCursorRow struct {
|
|
|
|
Name []byte
|
|
|
|
Tags models.Tags
|
|
|
|
}
|
|
|
|
|
|
|
|
// newSeriesCursor returns a new instance of SeriesCursor.
|
2019-02-19 22:10:33 +00:00
|
|
|
func newSeriesCursor(req SeriesCursorRequest, index *tsi1.Index, sfile *tsdb.SeriesFile, cond influxql.Expr) (SeriesCursor, error) {
|
2019-02-15 21:30:50 +00:00
|
|
|
if cond != nil {
|
|
|
|
var err error
|
|
|
|
influxql.WalkFunc(cond, func(node influxql.Node) {
|
|
|
|
switch n := node.(type) {
|
|
|
|
case *influxql.BinaryExpr:
|
|
|
|
switch n.Op {
|
|
|
|
case influxql.EQ, influxql.NEQ, influxql.EQREGEX, influxql.NEQREGEX, influxql.OR, influxql.AND:
|
|
|
|
default:
|
|
|
|
err = errUnexpectedTagComparisonOperator
|
|
|
|
}
|
2018-09-25 00:52:40 +00:00
|
|
|
}
|
2019-02-15 21:30:50 +00:00
|
|
|
})
|
2018-09-25 00:52:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
storage: fix problems with keeping resources alive
This commit adds the pkg/lifecycle.Resource to help manage opening,
closing, and leasing out references to some resource. A resource
cannot be closed until all acquired references have been released.
If the debug_ref tag is enabled, all resource acquisitions keep
track of the stack trace that created them and have a finalizer
associated with them to print on stderr if they are leaked. It also
registers a handler on SIGUSR2 to dump all of the currently live
resources.
Having resources tracked in a uniform way with a data type allows us
to do more sophisticated tracking with the debug_ref tag, as well.
For example, we could panic the process if a resource cannot be
closed within a certain time frame, or attempt to figure out the
DAG of resource ownership dynamically.
This commit also fixes many issues around resources, correctness
during error scenarios, reporting of errors, idempotency of
close, tracking of memory for some data structures, resource leaks
in tests, and out of order dependency closes in tests.
2019-02-25 23:51:08 +00:00
|
|
|
indexref, err := index.Acquire()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
sfileref, err := sfile.Acquire()
|
|
|
|
if err != nil {
|
|
|
|
indexref.Release()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-09-25 00:52:40 +00:00
|
|
|
return &seriesCursor{
|
storage: fix problems with keeping resources alive
This commit adds the pkg/lifecycle.Resource to help manage opening,
closing, and leasing out references to some resource. A resource
cannot be closed until all acquired references have been released.
If the debug_ref tag is enabled, all resource acquisitions keep
track of the stack trace that created them and have a finalizer
associated with them to print on stderr if they are leaked. It also
registers a handler on SIGUSR2 to dump all of the currently live
resources.
Having resources tracked in a uniform way with a data type allows us
to do more sophisticated tracking with the debug_ref tag, as well.
For example, we could panic the process if a resource cannot be
closed within a certain time frame, or attempt to figure out the
DAG of resource ownership dynamically.
This commit also fixes many issues around resources, correctness
during error scenarios, reporting of errors, idempotency of
close, tracking of memory for some data structures, resource leaks
in tests, and out of order dependency closes in tests.
2019-02-25 23:51:08 +00:00
|
|
|
index: index,
|
|
|
|
indexref: indexref,
|
|
|
|
sfile: sfile,
|
|
|
|
sfileref: sfileref,
|
|
|
|
name: req.Name,
|
|
|
|
cond: cond,
|
2018-09-25 00:52:40 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
storage: fix problems with keeping resources alive
This commit adds the pkg/lifecycle.Resource to help manage opening,
closing, and leasing out references to some resource. A resource
cannot be closed until all acquired references have been released.
If the debug_ref tag is enabled, all resource acquisitions keep
track of the stack trace that created them and have a finalizer
associated with them to print on stderr if they are leaked. It also
registers a handler on SIGUSR2 to dump all of the currently live
resources.
Having resources tracked in a uniform way with a data type allows us
to do more sophisticated tracking with the debug_ref tag, as well.
For example, we could panic the process if a resource cannot be
closed within a certain time frame, or attempt to figure out the
DAG of resource ownership dynamically.
This commit also fixes many issues around resources, correctness
during error scenarios, reporting of errors, idempotency of
close, tracking of memory for some data structures, resource leaks
in tests, and out of order dependency closes in tests.
2019-02-25 23:51:08 +00:00
|
|
|
// Close closes the iterator. Safe to call multiple times.
|
2019-02-19 22:10:33 +00:00
|
|
|
func (cur *seriesCursor) Close() error {
|
storage: fix problems with keeping resources alive
This commit adds the pkg/lifecycle.Resource to help manage opening,
closing, and leasing out references to some resource. A resource
cannot be closed until all acquired references have been released.
If the debug_ref tag is enabled, all resource acquisitions keep
track of the stack trace that created them and have a finalizer
associated with them to print on stderr if they are leaked. It also
registers a handler on SIGUSR2 to dump all of the currently live
resources.
Having resources tracked in a uniform way with a data type allows us
to do more sophisticated tracking with the debug_ref tag, as well.
For example, we could panic the process if a resource cannot be
closed within a certain time frame, or attempt to figure out the
DAG of resource ownership dynamically.
This commit also fixes many issues around resources, correctness
during error scenarios, reporting of errors, idempotency of
close, tracking of memory for some data structures, resource leaks
in tests, and out of order dependency closes in tests.
2019-02-25 23:51:08 +00:00
|
|
|
cur.sfileref.Release()
|
|
|
|
cur.indexref.Release()
|
2019-02-19 22:10:33 +00:00
|
|
|
return nil
|
2018-09-25 00:52:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next emits the next point in the iterator.
|
|
|
|
func (cur *seriesCursor) Next() (*SeriesCursorRow, error) {
|
2019-02-19 22:10:33 +00:00
|
|
|
if !cur.init {
|
|
|
|
if err := cur.readSeriesKeys(); err != nil {
|
|
|
|
return nil, err
|
2018-09-25 00:52:40 +00:00
|
|
|
}
|
2019-02-19 22:10:33 +00:00
|
|
|
cur.init = true
|
|
|
|
}
|
2018-09-25 00:52:40 +00:00
|
|
|
|
2019-02-19 22:10:33 +00:00
|
|
|
if cur.ofs < len(cur.keys) {
|
2018-10-03 18:34:34 +00:00
|
|
|
cur.row.Name, cur.row.Tags = tsdb.ParseSeriesKey(cur.keys[cur.ofs])
|
2019-02-19 22:10:33 +00:00
|
|
|
if !bytes.HasPrefix(cur.row.Name, cur.name[:influxdb.OrgIDLength]) {
|
2019-02-15 21:30:50 +00:00
|
|
|
return nil, errUnexpectedOrg
|
|
|
|
}
|
2018-09-25 00:52:40 +00:00
|
|
|
cur.ofs++
|
|
|
|
return &cur.row, nil
|
|
|
|
}
|
2019-02-19 22:10:33 +00:00
|
|
|
|
|
|
|
return nil, nil
|
2018-09-25 00:52:40 +00:00
|
|
|
}
|
|
|
|
|
2019-02-19 22:10:33 +00:00
|
|
|
func (cur *seriesCursor) readSeriesKeys() error {
|
|
|
|
sitr, err := cur.index.MeasurementSeriesByExprIterator(cur.name[:], cur.cond)
|
2018-09-25 00:52:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if sitr == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
defer sitr.Close()
|
|
|
|
|
|
|
|
for {
|
|
|
|
elem, err := sitr.Next()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if elem.SeriesID.IsZero() {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2019-02-15 21:30:50 +00:00
|
|
|
key := cur.sfile.SeriesKey(elem.SeriesID)
|
2018-09-25 00:52:40 +00:00
|
|
|
if len(key) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
cur.keys = append(cur.keys, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort keys.
|
|
|
|
sort.Sort(seriesKeys(cur.keys))
|
|
|
|
return nil
|
|
|
|
}
|
2018-10-03 18:34:34 +00:00
|
|
|
|
|
|
|
type seriesKeys [][]byte
|
|
|
|
|
|
|
|
func (a seriesKeys) Len() int { return len(a) }
|
|
|
|
func (a seriesKeys) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
func (a seriesKeys) Less(i, j int) bool {
|
|
|
|
return tsdb.CompareSeriesKeys(a[i], a[j]) == -1
|
|
|
|
}
|