Skip to content

Commit

Permalink
Initialize vlog before starting compactions in db.Open (#1226)
Browse files Browse the repository at this point in the history
If compaction is started before opening vlog, badger might crash with
nil pointer error when trying to push discard stats at the end of
compactions because discard stats are initialized in vlog open.

This commit fixes it.
  • Loading branch information
Ibrahim Jarif authored Feb 27, 2020
1 parent e908818 commit 617ed7c
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 4 deletions.
3 changes: 3 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ func Open(opt Options) (db *DB, err error) {
return nil, err
}

// Initialize vlog struct.
db.vlog.init(db)

if !opt.ReadOnly {
db.closers.compactors = y.NewCloser(1)
db.lc.startCompact(db.closers.compactors)
Expand Down
15 changes: 13 additions & 2 deletions value.go
Original file line number Diff line number Diff line change
Expand Up @@ -1061,13 +1061,15 @@ func (vlog *valueLog) replayLog(lf *logFile, offset uint32, replayFn logEntry) e
return nil
}

func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
// init initializes the value log struct. This initialization needs to happen
// before compactions start.
func (vlog *valueLog) init(db *DB) {
vlog.opt = db.opt
vlog.db = db
// We don't need to open any vlog files or collect stats for GC if DB is opened
// in InMemory mode. InMemory mode doesn't create any files/directories on disk.
if vlog.opt.InMemory {
return nil
return
}
vlog.dirPath = vlog.opt.ValueDir
vlog.elog = y.NoEventLog
Expand All @@ -1080,6 +1082,15 @@ func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
closer: y.NewCloser(1),
flushChan: make(chan map[uint32]int64, 16),
}
}

func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
// We don't need to open any vlog files or collect stats for GC if DB is opened
// in InMemory mode. InMemory mode doesn't create any files/directories on disk.
if db.opt.InMemory {
return nil
}

go vlog.flushDiscardStats()
if err := vlog.populateFilesMap(); err != nil {
return err
Expand Down
8 changes: 6 additions & 2 deletions value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ func TestValueGC4(t *testing.T) {
err = kv.vlog.Close()
require.NoError(t, err)

kv.vlog.init(kv)
err = kv.vlog.open(kv, valuePointer{Fid: 2}, kv.replayFunction())
require.NoError(t, err)

Expand Down Expand Up @@ -642,8 +643,11 @@ func TestPartialAppendToValueLog(t *testing.T) {
checkKeys(t, kv, [][]byte{k3})
// Replay value log from beginning, badger head is past k2.
require.NoError(t, kv.vlog.Close())
require.NoError(t,
kv.vlog.open(kv, valuePointer{Fid: 0}, kv.replayFunction()))

kv.vlog.init(kv)
require.NoError(
t, kv.vlog.open(kv, valuePointer{Fid: 0}, kv.replayFunction()),
)
require.NoError(t, kv.Close())
}

Expand Down

0 comments on commit 617ed7c

Please sign in to comment.