make Close methods for the querier safe to call more than once. (#581)
* make Close methods for the querier safe to call more than once. Signed-off-by: Krasi Georgiev <kgeorgie@redhat.com>
This commit is contained in:
parent
19d402d154
commit
5512826f13
|
@ -1,4 +1,6 @@
|
|||
## master / unreleased
|
||||
- [BUGFIX] Calling `Close` more than once on a querier returns an error instead of a panic.
|
||||
|
||||
|
||||
## 0.7.1
|
||||
- [ENHANCEMENT] Reduce memory usage in mergedPostings.Seek
|
||||
|
|
|
@ -205,6 +205,8 @@ type blockQuerier struct {
|
|||
chunks ChunkReader
|
||||
tombstones TombstoneReader
|
||||
|
||||
closed bool
|
||||
|
||||
mint, maxt int64
|
||||
}
|
||||
|
||||
|
@ -252,12 +254,15 @@ func (q *blockQuerier) LabelValuesFor(string, labels.Label) ([]string, error) {
|
|||
}
|
||||
|
||||
func (q *blockQuerier) Close() error {
|
||||
var merr tsdb_errors.MultiError
|
||||
if q.closed {
|
||||
return errors.New("block querier already closed")
|
||||
}
|
||||
|
||||
var merr tsdb_errors.MultiError
|
||||
merr.Add(q.index.Close())
|
||||
merr.Add(q.chunks.Close())
|
||||
merr.Add(q.tombstones.Close())
|
||||
|
||||
q.closed = true
|
||||
return merr.Err()
|
||||
}
|
||||
|
||||
|
|
|
@ -1898,3 +1898,30 @@ func TestPostingsForMatchers(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// TestClose ensures that calling Close more than once doesn't block and doesn't panic.
|
||||
func TestClose(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "test_storage")
|
||||
if err != nil {
|
||||
t.Fatalf("Opening test dir failed: %s", err)
|
||||
}
|
||||
defer func() {
|
||||
testutil.Ok(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
createBlock(t, dir, genSeries(1, 1, 0, 10))
|
||||
createBlock(t, dir, genSeries(1, 1, 10, 20))
|
||||
|
||||
db, err := Open(dir, nil, nil, DefaultOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Opening test storage failed: %s", err)
|
||||
}
|
||||
defer func() {
|
||||
testutil.Ok(t, db.Close())
|
||||
}()
|
||||
|
||||
q, err := db.Querier(0, 20)
|
||||
testutil.Ok(t, err)
|
||||
testutil.Ok(t, q.Close())
|
||||
testutil.NotOk(t, q.Close())
|
||||
}
|
||||
|
|
|
@ -159,9 +159,9 @@ type WAL struct {
|
|||
logger log.Logger
|
||||
segmentSize int
|
||||
mtx sync.RWMutex
|
||||
segment *Segment // active segment
|
||||
donePages int // pages written to the segment
|
||||
page *page // active page
|
||||
segment *Segment // Active segment.
|
||||
donePages int // Pages written to the segment.
|
||||
page *page // Active page.
|
||||
stopc chan chan struct{}
|
||||
actorc chan func()
|
||||
closed bool // To allow calling Close() more than once without blocking.
|
||||
|
@ -606,7 +606,7 @@ func (w *WAL) Close() (err error) {
|
|||
defer w.mtx.Unlock()
|
||||
|
||||
if w.closed {
|
||||
return nil
|
||||
return errors.New("wal already closed")
|
||||
}
|
||||
|
||||
// Flush the last page and zero out all its remaining size.
|
||||
|
|
|
@ -305,6 +305,19 @@ func TestCorruptAndCarryOn(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestClose ensures that calling Close more than once doesn't panic and doesn't block.
|
||||
func TestClose(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "wal_repair")
|
||||
testutil.Ok(t, err)
|
||||
defer func() {
|
||||
testutil.Ok(t, os.RemoveAll(dir))
|
||||
}()
|
||||
w, err := NewSize(nil, nil, dir, pageSize)
|
||||
testutil.Ok(t, err)
|
||||
testutil.Ok(t, w.Close())
|
||||
testutil.NotOk(t, w.Close())
|
||||
}
|
||||
|
||||
func BenchmarkWAL_LogBatched(b *testing.B) {
|
||||
dir, err := ioutil.TempDir("", "bench_logbatch")
|
||||
testutil.Ok(b, err)
|
||||
|
|
Loading…
Reference in New Issue