Skip to content

Commit

Permalink
db: return error from Close if open snapshots remain
Browse files Browse the repository at this point in the history
Return an error from DB.Close if the database has open snapshots. This
helps ensure clients don't accidentally leak snapshots, which during
normal operation prevents dropping any keys older than the snapshot.

Fix cockroachdb#1986.
  • Loading branch information
jbowens committed Oct 5, 2022
1 parent 499bd88 commit eec7375
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 0 deletions.
29 changes: 29 additions & 0 deletions compaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,7 @@ func TestManualCompaction(t *testing.T) {
var d *DB
defer func() {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
}()
Expand All @@ -1236,6 +1237,7 @@ func TestManualCompaction(t *testing.T) {

reset := func(minVersion, maxVersion FormatMajorVersion) {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
mem = vfs.NewMem()
Expand Down Expand Up @@ -1330,6 +1332,9 @@ func TestManualCompaction(t *testing.T) {

case "define":
if d != nil {
if err := closeAllSnapshots(d); err != nil {
return err.Error()
}
if err := d.Close(); err != nil {
return err.Error()
}
Expand Down Expand Up @@ -1840,6 +1845,7 @@ func TestCompactionDeleteOnlyHints(t *testing.T) {
var d *DB
defer func() {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
}()
Expand All @@ -1848,6 +1854,9 @@ func TestCompactionDeleteOnlyHints(t *testing.T) {
reset := func() (*Options, error) {
if d != nil {
compactInfo = nil
if err := closeAllSnapshots(d); err != nil {
return nil, err
}
if err := d.Close(); err != nil {
return nil, err
}
Expand Down Expand Up @@ -2087,6 +2096,7 @@ func TestCompactionTombstones(t *testing.T) {
var d *DB
defer func() {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
}()
Expand Down Expand Up @@ -2116,6 +2126,7 @@ func TestCompactionTombstones(t *testing.T) {
case "define":
if d != nil {
compactInfo = nil
require.NoError(t, closeAllSnapshots(d))
if err := d.Close(); err != nil {
return err.Error()
}
Expand Down Expand Up @@ -2189,6 +2200,22 @@ func TestCompactionTombstones(t *testing.T) {
})
}

func closeAllSnapshots(d *DB) error {
d.mu.Lock()
var ss []*Snapshot
l := &d.mu.snapshots
for i := l.root.next; i != &l.root; i = i.next {
ss = append(ss, i)
}
d.mu.Unlock()
for i := range ss {
if err := ss[i].Close(); err != nil {
return err
}
}
return nil
}

func TestCompactionReadTriggeredQueue(t *testing.T) {

// Convert a read compaction to a string which this test
Expand Down Expand Up @@ -2597,6 +2624,7 @@ func TestCompactionAllowZeroSeqNum(t *testing.T) {
var d *DB
defer func() {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
}()
Expand Down Expand Up @@ -2628,6 +2656,7 @@ func TestCompactionAllowZeroSeqNum(t *testing.T) {
switch td.Cmd {
case "define":
if d != nil {
require.NoError(t, closeAllSnapshots(d))
if err := d.Close(); err != nil {
return err.Error()
}
Expand Down
6 changes: 6 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,12 @@ func (d *DB) Close() error {
if d.opts.private.fsCloser != nil {
d.opts.private.fsCloser.Close()
}

// Return an error if the user failed to close all open snapshots.
if v := d.mu.snapshots.count(); v > 0 {
err = firstError(err, errors.Errorf("leaked snapshots: %d open snapshots on DB %p", v, d))
}

return err
}

Expand Down
1 change: 1 addition & 0 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ func TestUnremovableSingleDelete(t *testing.T) {

require.NoError(t, d.Set(key, valFirst, nil))
ss := d.NewSnapshot()
defer ss.Close()
require.NoError(t, d.SingleDelete(key, nil))
require.NoError(t, d.Set(key, valSecond, nil))
require.NoError(t, d.Flush())
Expand Down
4 changes: 4 additions & 0 deletions range_del_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestRangeDel(t *testing.T) {
var d *DB
defer func() {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
}()
Expand All @@ -37,6 +38,9 @@ func TestRangeDel(t *testing.T) {
switch td.Cmd {
case "define":
if d != nil {
if err := closeAllSnapshots(d); err != nil {
return err.Error()
}
if err := d.Close(); err != nil {
return err.Error()
}
Expand Down
2 changes: 2 additions & 0 deletions table_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func TestTableStats(t *testing.T) {
require.NoError(t, err)
defer func() {
if d != nil {
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
}
}()
Expand All @@ -60,6 +61,7 @@ func TestTableStats(t *testing.T) {
return ""

case "define":
require.NoError(t, closeAllSnapshots(d))
require.NoError(t, d.Close())
loadedInfo = nil

Expand Down

0 comments on commit eec7375

Please sign in to comment.