diff --git a/CHANGELOG.md b/CHANGELOG.md index fa9098fedba..45e3b46f8f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ - [#8908](https://github.com/influxdata/influxdb/issues/8908): Fix missing man pages in new packaging output - [#8909](https://github.com/influxdata/influxdb/issues/8909): Fix use of `INFLUXD_OPTS` in service file - [#8952](https://github.com/influxdata/influxdb/issues/8952): Fix WAL panic: runtime error: makeslice: cap out of range +- [#8975](https://github.com/influxdata/influxdb/pull/8975): Copy returned bytes from TSI meta functions. ## v1.3.4 [unreleased] diff --git a/pkg/bytesutil/bytesutil.go b/pkg/bytesutil/bytesutil.go index 552391d0ce3..f67d1e4d936 100644 --- a/pkg/bytesutil/bytesutil.go +++ b/pkg/bytesutil/bytesutil.go @@ -88,6 +88,25 @@ func Intersect(a, b [][]byte) [][]byte { return other } +// Clone returns a copy of b. +func Clone(b []byte) []byte { + if b == nil { + return nil + } + buf := make([]byte, len(b)) + copy(buf, b) + return buf +} + +// CloneSlice returns a copy of a slice of byte slices. +func CloneSlice(a [][]byte) [][]byte { + other := make([][]byte, len(a)) + for i := range a { + other[i] = Clone(a[i]) + } + return other +} + type byteSlices [][]byte func (a byteSlices) Len() int { return len(a) } diff --git a/tsdb/index/tsi1/index.go b/tsdb/index/tsi1/index.go index 6cfc8bbddfd..1b80d9df678 100644 --- a/tsdb/index/tsi1/index.go +++ b/tsdb/index/tsi1/index.go @@ -17,6 +17,7 @@ import ( "github.com/influxdata/influxdb/influxql" "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/pkg/bytesutil" "github.com/influxdata/influxdb/pkg/estimator" "github.com/influxdata/influxdb/query" "github.com/influxdata/influxdb/tsdb" @@ -402,7 +403,11 @@ func (i *Index) MeasurementExists(name []byte) (bool, error) { func (i *Index) MeasurementNamesByExpr(expr influxql.Expr) ([][]byte, error) { fs := i.RetainFileSet() defer fs.Release() - return fs.MeasurementNamesByExpr(expr) + + names, err := fs.MeasurementNamesByExpr(expr) + + // Clone byte slices since they will be used after the fileset is released. + return bytesutil.CloneSlice(names), err } func (i *Index) MeasurementNamesByRegex(re *regexp.Regexp) ([][]byte, error) { @@ -413,7 +418,8 @@ func (i *Index) MeasurementNamesByRegex(re *regexp.Regexp) ([][]byte, error) { var a [][]byte for e := itr.Next(); e != nil; e = itr.Next() { if re.Match(e.Name()) { - a = append(a, e.Name()) + // Clone bytes since they will be used after the fileset is released. + a = append(a, bytesutil.Clone(e.Name())) } } return a, nil @@ -726,7 +732,11 @@ func (i *Index) TagKeyCardinality(name, key []byte) int { func (i *Index) MeasurementSeriesKeysByExpr(name []byte, expr influxql.Expr) ([][]byte, error) { fs := i.RetainFileSet() defer fs.Release() - return fs.MeasurementSeriesKeysByExpr(name, expr, i.fieldset) + + keys, err := fs.MeasurementSeriesKeysByExpr(name, expr, i.fieldset) + + // Clone byte slices since they will be used after the fileset is released. + return bytesutil.CloneSlice(keys), err } // TagSets returns an ordered list of tag sets for a measurement by dimension diff --git a/tsdb/index/tsi1/index_files.go b/tsdb/index/tsi1/index_files.go index 1cb6f22e736..fb8f5df95b3 100644 --- a/tsdb/index/tsi1/index_files.go +++ b/tsdb/index/tsi1/index_files.go @@ -8,6 +8,7 @@ import ( "sort" "time" + "github.com/influxdata/influxdb/pkg/bytesutil" "github.com/influxdata/influxdb/pkg/estimator/hll" "github.com/influxdata/influxdb/pkg/mmap" ) @@ -52,7 +53,7 @@ func (p *IndexFiles) MeasurementNames() [][]byte { itr := p.MeasurementIterator() var names [][]byte for e := itr.Next(); e != nil; e = itr.Next() { - names = append(names, copyBytes(e.Name())) + names = append(names, bytesutil.Clone(e.Name())) } sort.Sort(byteSlices(names)) return names diff --git a/tsdb/index/tsi1/tsi1.go b/tsdb/index/tsi1/tsi1.go index 57d6c8ffdb7..1d1b565857f 100644 --- a/tsdb/index/tsi1/tsi1.go +++ b/tsdb/index/tsi1/tsi1.go @@ -792,16 +792,6 @@ 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 {