// newKeyValueFromJSONConfig returns a KeyValue implementation on top of a // github.com/syndtr/goleveldb/leveldb file. func newKeyValueFromJSONConfig(cfg jsonconfig.Obj) (sorted.KeyValue, error) { file := cfg.RequiredString("file") if err := cfg.Validate(); err != nil { return nil, err } strictness := opt.DefaultStrict if env.IsDev() { // Be more strict in dev mode. strictness = opt.StrictAll } opts := &opt.Options{ // The default is 10, // 8 means 2.126% or 1/47th disk check rate, // 10 means 0.812% error rate (1/2^(bits/1.44)) or 1/123th disk check rate, // 12 means 0.31% or 1/322th disk check rate. // TODO(tgulacsi): decide which number is the best here. Till that go with the default. Filter: filter.NewBloomFilter(10), Strict: strictness, } db, err := leveldb.OpenFile(file, opts) if err != nil { return nil, err } is := &kvis{ db: db, path: file, opts: opts, readOpts: &opt.ReadOptions{Strict: strictness}, // On machine crash we want to reindex anyway, and // fsyncs may impose great performance penalty. writeOpts: &opt.WriteOptions{Sync: false}, } return is, nil }
func TestCorruptDB_RecoverTable(t *testing.T) { h := newDbCorruptHarnessWopt(t, &opt.Options{ WriteBuffer: 112 * opt.KiB, CompactionTableSize: 90 * opt.KiB, Filter: filter.NewBloomFilter(10), }) h.build(1000) h.compactMem() h.compactRangeAt(0, "", "") h.compactRangeAt(1, "", "") seq := h.db.seq h.closeDB() h.corrupt(storage.TypeTable, 0, 1000, 1) h.corrupt(storage.TypeTable, 3, 10000, 1) // Corrupted filter shouldn't affect recovery. h.corrupt(storage.TypeTable, 3, 113888, 10) h.corrupt(storage.TypeTable, -1, 20000, 1) h.recover() if h.db.seq != seq { t.Errorf("invalid seq, want=%d got=%d", seq, h.db.seq) } h.check(985, 985) h.close() }