github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/db_test.go (about)

     1  // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
     2  // All rights reserved.
     3  //
     4  // Use of this source code is governed by a BSD-style license that can be
     5  // found in the LICENSE file.
     6  
     7  package leveldb
     8  
     9  import (
    10  	"bytes"
    11  	"container/list"
    12  	crand "crypto/rand"
    13  	"encoding/binary"
    14  	"fmt"
    15  	"math/rand"
    16  	"os"
    17  	"path/filepath"
    18  	"runtime"
    19  	"strings"
    20  	"sync"
    21  	"sync/atomic"
    22  	"testing"
    23  	"time"
    24  	"unsafe"
    25  
    26  	"github.com/insionng/yougam/libraries/onsi/gomega"
    27  
    28  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/comparer"
    29  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors"
    30  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/filter"
    31  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/iterator"
    32  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/opt"
    33  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/storage"
    34  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/testutil"
    35  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/util"
    36  )
    37  
    38  func tkey(i int) []byte {
    39  	return []byte(fmt.Sprintf("%016d", i))
    40  }
    41  
    42  func tval(seed, n int) []byte {
    43  	r := rand.New(rand.NewSource(int64(seed)))
    44  	return randomString(r, n)
    45  }
    46  
    47  func testingLogger(t *testing.T) func(log string) {
    48  	return func(log string) {
    49  		t.Log(log)
    50  	}
    51  }
    52  
    53  func testingPreserveOnFailed(t *testing.T) func() (preserve bool, err error) {
    54  	return func() (preserve bool, err error) {
    55  		preserve = t.Failed()
    56  		return
    57  	}
    58  }
    59  
    60  type dbHarness struct {
    61  	t *testing.T
    62  
    63  	stor *testutil.Storage
    64  	db   *DB
    65  	o    *opt.Options
    66  	ro   *opt.ReadOptions
    67  	wo   *opt.WriteOptions
    68  }
    69  
    70  func newDbHarnessWopt(t *testing.T, o *opt.Options) *dbHarness {
    71  	h := new(dbHarness)
    72  	h.init(t, o)
    73  	return h
    74  }
    75  
    76  func newDbHarness(t *testing.T) *dbHarness {
    77  	return newDbHarnessWopt(t, &opt.Options{DisableLargeBatchTransaction: true})
    78  }
    79  
    80  func (h *dbHarness) init(t *testing.T, o *opt.Options) {
    81  	gomega.RegisterTestingT(t)
    82  	h.t = t
    83  	h.stor = testutil.NewStorage()
    84  	h.stor.OnLog(testingLogger(t))
    85  	h.stor.OnClose(testingPreserveOnFailed(t))
    86  	h.o = o
    87  	h.ro = nil
    88  	h.wo = nil
    89  
    90  	if err := h.openDB0(); err != nil {
    91  		// So that it will come after fatal message.
    92  		defer h.stor.Close()
    93  		h.t.Fatal("Open (init): got error: ", err)
    94  	}
    95  }
    96  
    97  func (h *dbHarness) openDB0() (err error) {
    98  	h.t.Log("opening DB")
    99  	h.db, err = Open(h.stor, h.o)
   100  	return
   101  }
   102  
   103  func (h *dbHarness) openDB() {
   104  	if err := h.openDB0(); err != nil {
   105  		h.t.Fatal("Open: got error: ", err)
   106  	}
   107  }
   108  
   109  func (h *dbHarness) closeDB0() error {
   110  	h.t.Log("closing DB")
   111  	return h.db.Close()
   112  }
   113  
   114  func (h *dbHarness) closeDB() {
   115  	if h.db != nil {
   116  		if err := h.closeDB0(); err != nil {
   117  			h.t.Error("Close: got error: ", err)
   118  		}
   119  		h.db = nil
   120  	}
   121  	h.stor.CloseCheck()
   122  	runtime.GC()
   123  }
   124  
   125  func (h *dbHarness) reopenDB() {
   126  	if h.db != nil {
   127  		h.closeDB()
   128  	}
   129  	h.openDB()
   130  }
   131  
   132  func (h *dbHarness) close() {
   133  	if h.db != nil {
   134  		h.closeDB0()
   135  		h.db = nil
   136  	}
   137  	h.stor.Close()
   138  	h.stor = nil
   139  	runtime.GC()
   140  }
   141  
   142  func (h *dbHarness) openAssert(want bool) {
   143  	db, err := Open(h.stor, h.o)
   144  	if err != nil {
   145  		if want {
   146  			h.t.Error("Open: assert: got error: ", err)
   147  		} else {
   148  			h.t.Log("Open: assert: got error (expected): ", err)
   149  		}
   150  	} else {
   151  		if !want {
   152  			h.t.Error("Open: assert: expect error")
   153  		}
   154  		db.Close()
   155  	}
   156  }
   157  
   158  func (h *dbHarness) write(batch *Batch) {
   159  	if err := h.db.Write(batch, h.wo); err != nil {
   160  		h.t.Error("Write: got error: ", err)
   161  	}
   162  }
   163  
   164  func (h *dbHarness) put(key, value string) {
   165  	if err := h.db.Put([]byte(key), []byte(value), h.wo); err != nil {
   166  		h.t.Error("Put: got error: ", err)
   167  	}
   168  }
   169  
   170  func (h *dbHarness) putMulti(n int, low, hi string) {
   171  	for i := 0; i < n; i++ {
   172  		h.put(low, "begin")
   173  		h.put(hi, "end")
   174  		h.compactMem()
   175  	}
   176  }
   177  
   178  func (h *dbHarness) maxNextLevelOverlappingBytes(want int64) {
   179  	t := h.t
   180  	db := h.db
   181  
   182  	var (
   183  		maxOverlaps int64
   184  		maxLevel    int
   185  	)
   186  	v := db.s.version()
   187  	if len(v.levels) > 2 {
   188  		for i, tt := range v.levels[1 : len(v.levels)-1] {
   189  			level := i + 1
   190  			next := v.levels[level+1]
   191  			for _, t := range tt {
   192  				r := next.getOverlaps(nil, db.s.icmp, t.imin.ukey(), t.imax.ukey(), false)
   193  				sum := r.size()
   194  				if sum > maxOverlaps {
   195  					maxOverlaps = sum
   196  					maxLevel = level
   197  				}
   198  			}
   199  		}
   200  	}
   201  	v.release()
   202  
   203  	if maxOverlaps > want {
   204  		t.Errorf("next level most overlapping bytes is more than %d, got=%d level=%d", want, maxOverlaps, maxLevel)
   205  	} else {
   206  		t.Logf("next level most overlapping bytes is %d, level=%d want=%d", maxOverlaps, maxLevel, want)
   207  	}
   208  }
   209  
   210  func (h *dbHarness) delete(key string) {
   211  	t := h.t
   212  	db := h.db
   213  
   214  	err := db.Delete([]byte(key), h.wo)
   215  	if err != nil {
   216  		t.Error("Delete: got error: ", err)
   217  	}
   218  }
   219  
   220  func (h *dbHarness) assertNumKeys(want int) {
   221  	iter := h.db.NewIterator(nil, h.ro)
   222  	defer iter.Release()
   223  	got := 0
   224  	for iter.Next() {
   225  		got++
   226  	}
   227  	if err := iter.Error(); err != nil {
   228  		h.t.Error("assertNumKeys: ", err)
   229  	}
   230  	if want != got {
   231  		h.t.Errorf("assertNumKeys: want=%d got=%d", want, got)
   232  	}
   233  }
   234  
   235  func (h *dbHarness) getr(db Reader, key string, expectFound bool) (found bool, v []byte) {
   236  	t := h.t
   237  	v, err := db.Get([]byte(key), h.ro)
   238  	switch err {
   239  	case ErrNotFound:
   240  		if expectFound {
   241  			t.Errorf("Get: key '%s' not found, want found", key)
   242  		}
   243  	case nil:
   244  		found = true
   245  		if !expectFound {
   246  			t.Errorf("Get: key '%s' found, want not found", key)
   247  		}
   248  	default:
   249  		t.Error("Get: got error: ", err)
   250  	}
   251  	return
   252  }
   253  
   254  func (h *dbHarness) get(key string, expectFound bool) (found bool, v []byte) {
   255  	return h.getr(h.db, key, expectFound)
   256  }
   257  
   258  func (h *dbHarness) getValr(db Reader, key, value string) {
   259  	t := h.t
   260  	found, r := h.getr(db, key, true)
   261  	if !found {
   262  		return
   263  	}
   264  	rval := string(r)
   265  	if rval != value {
   266  		t.Errorf("Get: invalid value, got '%s', want '%s'", rval, value)
   267  	}
   268  }
   269  
   270  func (h *dbHarness) getVal(key, value string) {
   271  	h.getValr(h.db, key, value)
   272  }
   273  
   274  func (h *dbHarness) allEntriesFor(key, want string) {
   275  	t := h.t
   276  	db := h.db
   277  	s := db.s
   278  
   279  	ikey := makeInternalKey(nil, []byte(key), keyMaxSeq, keyTypeVal)
   280  	iter := db.newRawIterator(nil, nil, nil, nil)
   281  	if !iter.Seek(ikey) && iter.Error() != nil {
   282  		t.Error("AllEntries: error during seek, err: ", iter.Error())
   283  		return
   284  	}
   285  	res := "[ "
   286  	first := true
   287  	for iter.Valid() {
   288  		if ukey, _, kt, kerr := parseInternalKey(iter.Key()); kerr == nil {
   289  			if s.icmp.uCompare(ikey.ukey(), ukey) != 0 {
   290  				break
   291  			}
   292  			if !first {
   293  				res += ", "
   294  			}
   295  			first = false
   296  			switch kt {
   297  			case keyTypeVal:
   298  				res += string(iter.Value())
   299  			case keyTypeDel:
   300  				res += "DEL"
   301  			}
   302  		} else {
   303  			if !first {
   304  				res += ", "
   305  			}
   306  			first = false
   307  			res += "CORRUPTED"
   308  		}
   309  		iter.Next()
   310  	}
   311  	if !first {
   312  		res += " "
   313  	}
   314  	res += "]"
   315  	if res != want {
   316  		t.Errorf("AllEntries: assert failed for key %q, got=%q want=%q", key, res, want)
   317  	}
   318  }
   319  
   320  // Return a string that contains all key,value pairs in order,
   321  // formatted like "(k1->v1)(k2->v2)".
   322  func (h *dbHarness) getKeyVal(want string) {
   323  	t := h.t
   324  	db := h.db
   325  
   326  	s, err := db.GetSnapshot()
   327  	if err != nil {
   328  		t.Fatal("GetSnapshot: got error: ", err)
   329  	}
   330  	res := ""
   331  	iter := s.NewIterator(nil, nil)
   332  	for iter.Next() {
   333  		res += fmt.Sprintf("(%s->%s)", string(iter.Key()), string(iter.Value()))
   334  	}
   335  	iter.Release()
   336  
   337  	if res != want {
   338  		t.Errorf("GetKeyVal: invalid key/value pair, got=%q want=%q", res, want)
   339  	}
   340  	s.Release()
   341  }
   342  
   343  func (h *dbHarness) waitCompaction() {
   344  	t := h.t
   345  	db := h.db
   346  	if err := db.compTriggerWait(db.tcompCmdC); err != nil {
   347  		t.Error("compaction error: ", err)
   348  	}
   349  }
   350  
   351  func (h *dbHarness) waitMemCompaction() {
   352  	t := h.t
   353  	db := h.db
   354  
   355  	if err := db.compTriggerWait(db.mcompCmdC); err != nil {
   356  		t.Error("compaction error: ", err)
   357  	}
   358  }
   359  
   360  func (h *dbHarness) compactMem() {
   361  	t := h.t
   362  	db := h.db
   363  
   364  	t.Log("starting memdb compaction")
   365  
   366  	db.writeLockC <- struct{}{}
   367  	defer func() {
   368  		<-db.writeLockC
   369  	}()
   370  
   371  	if _, err := db.rotateMem(0, true); err != nil {
   372  		t.Error("compaction error: ", err)
   373  	}
   374  
   375  	if h.totalTables() == 0 {
   376  		t.Error("zero tables after mem compaction")
   377  	}
   378  
   379  	t.Log("memdb compaction done")
   380  }
   381  
   382  func (h *dbHarness) compactRangeAtErr(level int, min, max string, wanterr bool) {
   383  	t := h.t
   384  	db := h.db
   385  
   386  	var _min, _max []byte
   387  	if min != "" {
   388  		_min = []byte(min)
   389  	}
   390  	if max != "" {
   391  		_max = []byte(max)
   392  	}
   393  
   394  	t.Logf("starting table range compaction: level=%d, min=%q, max=%q", level, min, max)
   395  
   396  	if err := db.compTriggerRange(db.tcompCmdC, level, _min, _max); err != nil {
   397  		if wanterr {
   398  			t.Log("CompactRangeAt: got error (expected): ", err)
   399  		} else {
   400  			t.Error("CompactRangeAt: got error: ", err)
   401  		}
   402  	} else if wanterr {
   403  		t.Error("CompactRangeAt: expect error")
   404  	}
   405  
   406  	t.Log("table range compaction done")
   407  }
   408  
   409  func (h *dbHarness) compactRangeAt(level int, min, max string) {
   410  	h.compactRangeAtErr(level, min, max, false)
   411  }
   412  
   413  func (h *dbHarness) compactRange(min, max string) {
   414  	t := h.t
   415  	db := h.db
   416  
   417  	t.Logf("starting DB range compaction: min=%q, max=%q", min, max)
   418  
   419  	var r util.Range
   420  	if min != "" {
   421  		r.Start = []byte(min)
   422  	}
   423  	if max != "" {
   424  		r.Limit = []byte(max)
   425  	}
   426  	if err := db.CompactRange(r); err != nil {
   427  		t.Error("CompactRange: got error: ", err)
   428  	}
   429  
   430  	t.Log("DB range compaction done")
   431  }
   432  
   433  func (h *dbHarness) sizeOf(start, limit string) int64 {
   434  	sz, err := h.db.SizeOf([]util.Range{
   435  		{[]byte(start), []byte(limit)},
   436  	})
   437  	if err != nil {
   438  		h.t.Error("SizeOf: got error: ", err)
   439  	}
   440  	return sz.Sum()
   441  }
   442  
   443  func (h *dbHarness) sizeAssert(start, limit string, low, hi int64) {
   444  	sz := h.sizeOf(start, limit)
   445  	if sz < low || sz > hi {
   446  		h.t.Errorf("sizeOf %q to %q not in range, want %d - %d, got %d",
   447  			shorten(start), shorten(limit), low, hi, sz)
   448  	}
   449  }
   450  
   451  func (h *dbHarness) getSnapshot() (s *Snapshot) {
   452  	s, err := h.db.GetSnapshot()
   453  	if err != nil {
   454  		h.t.Fatal("GetSnapshot: got error: ", err)
   455  	}
   456  	return
   457  }
   458  
   459  func (h *dbHarness) getTablesPerLevel() string {
   460  	res := ""
   461  	nz := 0
   462  	v := h.db.s.version()
   463  	for level, tables := range v.levels {
   464  		if level > 0 {
   465  			res += ","
   466  		}
   467  		res += fmt.Sprint(len(tables))
   468  		if len(tables) > 0 {
   469  			nz = len(res)
   470  		}
   471  	}
   472  	v.release()
   473  	return res[:nz]
   474  }
   475  
   476  func (h *dbHarness) tablesPerLevel(want string) {
   477  	res := h.getTablesPerLevel()
   478  	if res != want {
   479  		h.t.Errorf("invalid tables len, want=%s, got=%s", want, res)
   480  	}
   481  }
   482  
   483  func (h *dbHarness) totalTables() (n int) {
   484  	v := h.db.s.version()
   485  	for _, tables := range v.levels {
   486  		n += len(tables)
   487  	}
   488  	v.release()
   489  	return
   490  }
   491  
   492  type keyValue interface {
   493  	Key() []byte
   494  	Value() []byte
   495  }
   496  
   497  func testKeyVal(t *testing.T, kv keyValue, want string) {
   498  	res := string(kv.Key()) + "->" + string(kv.Value())
   499  	if res != want {
   500  		t.Errorf("invalid key/value, want=%q, got=%q", want, res)
   501  	}
   502  }
   503  
   504  func numKey(num int) string {
   505  	return fmt.Sprintf("key%06d", num)
   506  }
   507  
   508  var testingBloomFilter = filter.NewBloomFilter(10)
   509  
   510  func truno(t *testing.T, o *opt.Options, f func(h *dbHarness)) {
   511  	for i := 0; i < 4; i++ {
   512  		func() {
   513  			switch i {
   514  			case 0:
   515  			case 1:
   516  				if o == nil {
   517  					o = &opt.Options{
   518  						DisableLargeBatchTransaction: true,
   519  						Filter: testingBloomFilter,
   520  					}
   521  				} else {
   522  					old := o
   523  					o = &opt.Options{}
   524  					*o = *old
   525  					o.Filter = testingBloomFilter
   526  				}
   527  			case 2:
   528  				if o == nil {
   529  					o = &opt.Options{
   530  						DisableLargeBatchTransaction: true,
   531  						Compression:                  opt.NoCompression,
   532  					}
   533  				} else {
   534  					old := o
   535  					o = &opt.Options{}
   536  					*o = *old
   537  					o.Compression = opt.NoCompression
   538  				}
   539  			}
   540  			h := newDbHarnessWopt(t, o)
   541  			defer h.close()
   542  			switch i {
   543  			case 3:
   544  				h.reopenDB()
   545  			}
   546  			f(h)
   547  		}()
   548  	}
   549  }
   550  
   551  func trun(t *testing.T, f func(h *dbHarness)) {
   552  	truno(t, nil, f)
   553  }
   554  
   555  func testAligned(t *testing.T, name string, offset uintptr) {
   556  	if offset%8 != 0 {
   557  		t.Errorf("field %s offset is not 64-bit aligned", name)
   558  	}
   559  }
   560  
   561  func Test_FieldsAligned(t *testing.T) {
   562  	p1 := new(DB)
   563  	testAligned(t, "DB.seq", unsafe.Offsetof(p1.seq))
   564  	p2 := new(session)
   565  	testAligned(t, "session.stNextFileNum", unsafe.Offsetof(p2.stNextFileNum))
   566  	testAligned(t, "session.stJournalNum", unsafe.Offsetof(p2.stJournalNum))
   567  	testAligned(t, "session.stPrevJournalNum", unsafe.Offsetof(p2.stPrevJournalNum))
   568  	testAligned(t, "session.stSeqNum", unsafe.Offsetof(p2.stSeqNum))
   569  }
   570  
   571  func TestDB_Locking(t *testing.T) {
   572  	h := newDbHarness(t)
   573  	defer h.stor.Close()
   574  	h.openAssert(false)
   575  	h.closeDB()
   576  	h.openAssert(true)
   577  }
   578  
   579  func TestDB_Empty(t *testing.T) {
   580  	trun(t, func(h *dbHarness) {
   581  		h.get("foo", false)
   582  
   583  		h.reopenDB()
   584  		h.get("foo", false)
   585  	})
   586  }
   587  
   588  func TestDB_ReadWrite(t *testing.T) {
   589  	trun(t, func(h *dbHarness) {
   590  		h.put("foo", "v1")
   591  		h.getVal("foo", "v1")
   592  		h.put("bar", "v2")
   593  		h.put("foo", "v3")
   594  		h.getVal("foo", "v3")
   595  		h.getVal("bar", "v2")
   596  
   597  		h.reopenDB()
   598  		h.getVal("foo", "v3")
   599  		h.getVal("bar", "v2")
   600  	})
   601  }
   602  
   603  func TestDB_PutDeleteGet(t *testing.T) {
   604  	trun(t, func(h *dbHarness) {
   605  		h.put("foo", "v1")
   606  		h.getVal("foo", "v1")
   607  		h.put("foo", "v2")
   608  		h.getVal("foo", "v2")
   609  		h.delete("foo")
   610  		h.get("foo", false)
   611  
   612  		h.reopenDB()
   613  		h.get("foo", false)
   614  	})
   615  }
   616  
   617  func TestDB_EmptyBatch(t *testing.T) {
   618  	h := newDbHarness(t)
   619  	defer h.close()
   620  
   621  	h.get("foo", false)
   622  	err := h.db.Write(new(Batch), h.wo)
   623  	if err != nil {
   624  		t.Error("writing empty batch yield error: ", err)
   625  	}
   626  	h.get("foo", false)
   627  }
   628  
   629  func TestDB_GetFromFrozen(t *testing.T) {
   630  	h := newDbHarnessWopt(t, &opt.Options{
   631  		DisableLargeBatchTransaction: true,
   632  		WriteBuffer:                  100100,
   633  	})
   634  	defer h.close()
   635  
   636  	h.put("foo", "v1")
   637  	h.getVal("foo", "v1")
   638  
   639  	h.stor.Stall(testutil.ModeSync, storage.TypeTable) // Block sync calls
   640  	h.put("k1", strings.Repeat("x", 100000))           // Fill memtable
   641  	h.put("k2", strings.Repeat("y", 100000))           // Trigger compaction
   642  	for i := 0; h.db.getFrozenMem() == nil && i < 100; i++ {
   643  		time.Sleep(10 * time.Microsecond)
   644  	}
   645  	if h.db.getFrozenMem() == nil {
   646  		h.stor.Release(testutil.ModeSync, storage.TypeTable)
   647  		t.Fatal("No frozen mem")
   648  	}
   649  	h.getVal("foo", "v1")
   650  	h.stor.Release(testutil.ModeSync, storage.TypeTable) // Release sync calls
   651  
   652  	h.reopenDB()
   653  	h.getVal("foo", "v1")
   654  	h.get("k1", true)
   655  	h.get("k2", true)
   656  }
   657  
   658  func TestDB_GetFromTable(t *testing.T) {
   659  	trun(t, func(h *dbHarness) {
   660  		h.put("foo", "v1")
   661  		h.compactMem()
   662  		h.getVal("foo", "v1")
   663  	})
   664  }
   665  
   666  func TestDB_GetSnapshot(t *testing.T) {
   667  	trun(t, func(h *dbHarness) {
   668  		bar := strings.Repeat("b", 200)
   669  		h.put("foo", "v1")
   670  		h.put(bar, "v1")
   671  
   672  		snap, err := h.db.GetSnapshot()
   673  		if err != nil {
   674  			t.Fatal("GetSnapshot: got error: ", err)
   675  		}
   676  
   677  		h.put("foo", "v2")
   678  		h.put(bar, "v2")
   679  
   680  		h.getVal("foo", "v2")
   681  		h.getVal(bar, "v2")
   682  		h.getValr(snap, "foo", "v1")
   683  		h.getValr(snap, bar, "v1")
   684  
   685  		h.compactMem()
   686  
   687  		h.getVal("foo", "v2")
   688  		h.getVal(bar, "v2")
   689  		h.getValr(snap, "foo", "v1")
   690  		h.getValr(snap, bar, "v1")
   691  
   692  		snap.Release()
   693  
   694  		h.reopenDB()
   695  		h.getVal("foo", "v2")
   696  		h.getVal(bar, "v2")
   697  	})
   698  }
   699  
   700  func TestDB_GetLevel0Ordering(t *testing.T) {
   701  	trun(t, func(h *dbHarness) {
   702  		h.db.memdbMaxLevel = 2
   703  
   704  		for i := 0; i < 4; i++ {
   705  			h.put("bar", fmt.Sprintf("b%d", i))
   706  			h.put("foo", fmt.Sprintf("v%d", i))
   707  			h.compactMem()
   708  		}
   709  		h.getVal("foo", "v3")
   710  		h.getVal("bar", "b3")
   711  
   712  		v := h.db.s.version()
   713  		t0len := v.tLen(0)
   714  		v.release()
   715  		if t0len < 2 {
   716  			t.Errorf("level-0 tables is less than 2, got %d", t0len)
   717  		}
   718  
   719  		h.reopenDB()
   720  		h.getVal("foo", "v3")
   721  		h.getVal("bar", "b3")
   722  	})
   723  }
   724  
   725  func TestDB_GetOrderedByLevels(t *testing.T) {
   726  	trun(t, func(h *dbHarness) {
   727  		h.put("foo", "v1")
   728  		h.compactMem()
   729  		h.compactRange("a", "z")
   730  		h.getVal("foo", "v1")
   731  		h.put("foo", "v2")
   732  		h.compactMem()
   733  		h.getVal("foo", "v2")
   734  	})
   735  }
   736  
   737  func TestDB_GetPicksCorrectFile(t *testing.T) {
   738  	trun(t, func(h *dbHarness) {
   739  		// Arrange to have multiple files in a non-level-0 level.
   740  		h.put("a", "va")
   741  		h.compactMem()
   742  		h.compactRange("a", "b")
   743  		h.put("x", "vx")
   744  		h.compactMem()
   745  		h.compactRange("x", "y")
   746  		h.put("f", "vf")
   747  		h.compactMem()
   748  		h.compactRange("f", "g")
   749  
   750  		h.getVal("a", "va")
   751  		h.getVal("f", "vf")
   752  		h.getVal("x", "vx")
   753  
   754  		h.compactRange("", "")
   755  		h.getVal("a", "va")
   756  		h.getVal("f", "vf")
   757  		h.getVal("x", "vx")
   758  	})
   759  }
   760  
   761  func TestDB_GetEncountersEmptyLevel(t *testing.T) {
   762  	trun(t, func(h *dbHarness) {
   763  		h.db.memdbMaxLevel = 2
   764  
   765  		// Arrange for the following to happen:
   766  		//   * sstable A in level 0
   767  		//   * nothing in level 1
   768  		//   * sstable B in level 2
   769  		// Then do enough Get() calls to arrange for an automatic compaction
   770  		// of sstable A.  A bug would cause the compaction to be marked as
   771  		// occuring at level 1 (instead of the correct level 0).
   772  
   773  		// Step 1: First place sstables in levels 0 and 2
   774  		for i := 0; ; i++ {
   775  			if i >= 100 {
   776  				t.Fatal("could not fill levels-0 and level-2")
   777  			}
   778  			v := h.db.s.version()
   779  			if v.tLen(0) > 0 && v.tLen(2) > 0 {
   780  				v.release()
   781  				break
   782  			}
   783  			v.release()
   784  			h.put("a", "begin")
   785  			h.put("z", "end")
   786  			h.compactMem()
   787  
   788  			h.getVal("a", "begin")
   789  			h.getVal("z", "end")
   790  		}
   791  
   792  		// Step 2: clear level 1 if necessary.
   793  		h.compactRangeAt(1, "", "")
   794  		h.tablesPerLevel("1,0,1")
   795  
   796  		h.getVal("a", "begin")
   797  		h.getVal("z", "end")
   798  
   799  		// Step 3: read a bunch of times
   800  		for i := 0; i < 200; i++ {
   801  			h.get("missing", false)
   802  		}
   803  
   804  		// Step 4: Wait for compaction to finish
   805  		h.waitCompaction()
   806  
   807  		v := h.db.s.version()
   808  		if v.tLen(0) > 0 {
   809  			t.Errorf("level-0 tables more than 0, got %d", v.tLen(0))
   810  		}
   811  		v.release()
   812  
   813  		h.getVal("a", "begin")
   814  		h.getVal("z", "end")
   815  	})
   816  }
   817  
   818  func TestDB_IterMultiWithDelete(t *testing.T) {
   819  	trun(t, func(h *dbHarness) {
   820  		h.put("a", "va")
   821  		h.put("b", "vb")
   822  		h.put("c", "vc")
   823  		h.delete("b")
   824  		h.get("b", false)
   825  
   826  		iter := h.db.NewIterator(nil, nil)
   827  		iter.Seek([]byte("c"))
   828  		testKeyVal(t, iter, "c->vc")
   829  		iter.Prev()
   830  		testKeyVal(t, iter, "a->va")
   831  		iter.Release()
   832  
   833  		h.compactMem()
   834  
   835  		iter = h.db.NewIterator(nil, nil)
   836  		iter.Seek([]byte("c"))
   837  		testKeyVal(t, iter, "c->vc")
   838  		iter.Prev()
   839  		testKeyVal(t, iter, "a->va")
   840  		iter.Release()
   841  	})
   842  }
   843  
   844  func TestDB_IteratorPinsRef(t *testing.T) {
   845  	h := newDbHarness(t)
   846  	defer h.close()
   847  
   848  	h.put("foo", "hello")
   849  
   850  	// Get iterator that will yield the current contents of the DB.
   851  	iter := h.db.NewIterator(nil, nil)
   852  
   853  	// Write to force compactions
   854  	h.put("foo", "newvalue1")
   855  	for i := 0; i < 100; i++ {
   856  		h.put(numKey(i), strings.Repeat(fmt.Sprintf("v%09d", i), 100000/10))
   857  	}
   858  	h.put("foo", "newvalue2")
   859  
   860  	iter.First()
   861  	testKeyVal(t, iter, "foo->hello")
   862  	if iter.Next() {
   863  		t.Errorf("expect eof")
   864  	}
   865  	iter.Release()
   866  }
   867  
   868  func TestDB_Recover(t *testing.T) {
   869  	trun(t, func(h *dbHarness) {
   870  		h.put("foo", "v1")
   871  		h.put("baz", "v5")
   872  
   873  		h.reopenDB()
   874  		h.getVal("foo", "v1")
   875  
   876  		h.getVal("foo", "v1")
   877  		h.getVal("baz", "v5")
   878  		h.put("bar", "v2")
   879  		h.put("foo", "v3")
   880  
   881  		h.reopenDB()
   882  		h.getVal("foo", "v3")
   883  		h.put("foo", "v4")
   884  		h.getVal("foo", "v4")
   885  		h.getVal("bar", "v2")
   886  		h.getVal("baz", "v5")
   887  	})
   888  }
   889  
   890  func TestDB_RecoverWithEmptyJournal(t *testing.T) {
   891  	trun(t, func(h *dbHarness) {
   892  		h.put("foo", "v1")
   893  		h.put("foo", "v2")
   894  
   895  		h.reopenDB()
   896  		h.reopenDB()
   897  		h.put("foo", "v3")
   898  
   899  		h.reopenDB()
   900  		h.getVal("foo", "v3")
   901  	})
   902  }
   903  
   904  func TestDB_RecoverDuringMemtableCompaction(t *testing.T) {
   905  	truno(t, &opt.Options{DisableLargeBatchTransaction: true, WriteBuffer: 1000000}, func(h *dbHarness) {
   906  
   907  		h.stor.Stall(testutil.ModeSync, storage.TypeTable)
   908  		h.put("big1", strings.Repeat("x", 10000000))
   909  		h.put("big2", strings.Repeat("y", 1000))
   910  		h.put("bar", "v2")
   911  		h.stor.Release(testutil.ModeSync, storage.TypeTable)
   912  
   913  		h.reopenDB()
   914  		h.getVal("bar", "v2")
   915  		h.getVal("big1", strings.Repeat("x", 10000000))
   916  		h.getVal("big2", strings.Repeat("y", 1000))
   917  	})
   918  }
   919  
   920  func TestDB_MinorCompactionsHappen(t *testing.T) {
   921  	h := newDbHarnessWopt(t, &opt.Options{DisableLargeBatchTransaction: true, WriteBuffer: 10000})
   922  	defer h.close()
   923  
   924  	n := 500
   925  
   926  	key := func(i int) string {
   927  		return fmt.Sprintf("key%06d", i)
   928  	}
   929  
   930  	for i := 0; i < n; i++ {
   931  		h.put(key(i), key(i)+strings.Repeat("v", 1000))
   932  	}
   933  
   934  	for i := 0; i < n; i++ {
   935  		h.getVal(key(i), key(i)+strings.Repeat("v", 1000))
   936  	}
   937  
   938  	h.reopenDB()
   939  	for i := 0; i < n; i++ {
   940  		h.getVal(key(i), key(i)+strings.Repeat("v", 1000))
   941  	}
   942  }
   943  
   944  func TestDB_RecoverWithLargeJournal(t *testing.T) {
   945  	h := newDbHarness(t)
   946  	defer h.close()
   947  
   948  	h.put("big1", strings.Repeat("1", 200000))
   949  	h.put("big2", strings.Repeat("2", 200000))
   950  	h.put("small3", strings.Repeat("3", 10))
   951  	h.put("small4", strings.Repeat("4", 10))
   952  	h.tablesPerLevel("")
   953  
   954  	// Make sure that if we re-open with a small write buffer size that
   955  	// we flush table files in the middle of a large journal file.
   956  	h.o.WriteBuffer = 100000
   957  	h.reopenDB()
   958  	h.getVal("big1", strings.Repeat("1", 200000))
   959  	h.getVal("big2", strings.Repeat("2", 200000))
   960  	h.getVal("small3", strings.Repeat("3", 10))
   961  	h.getVal("small4", strings.Repeat("4", 10))
   962  	v := h.db.s.version()
   963  	if v.tLen(0) <= 1 {
   964  		t.Errorf("tables-0 less than one")
   965  	}
   966  	v.release()
   967  }
   968  
   969  func TestDB_CompactionsGenerateMultipleFiles(t *testing.T) {
   970  	h := newDbHarnessWopt(t, &opt.Options{
   971  		DisableLargeBatchTransaction: true,
   972  		WriteBuffer:                  10000000,
   973  		Compression:                  opt.NoCompression,
   974  	})
   975  	defer h.close()
   976  
   977  	v := h.db.s.version()
   978  	if v.tLen(0) > 0 {
   979  		t.Errorf("level-0 tables more than 0, got %d", v.tLen(0))
   980  	}
   981  	v.release()
   982  
   983  	n := 80
   984  
   985  	// Write 8MB (80 values, each 100K)
   986  	for i := 0; i < n; i++ {
   987  		h.put(numKey(i), strings.Repeat(fmt.Sprintf("v%09d", i), 100000/10))
   988  	}
   989  
   990  	// Reopening moves updates to level-0
   991  	h.reopenDB()
   992  	h.compactRangeAt(0, "", "")
   993  
   994  	v = h.db.s.version()
   995  	if v.tLen(0) > 0 {
   996  		t.Errorf("level-0 tables more than 0, got %d", v.tLen(0))
   997  	}
   998  	if v.tLen(1) <= 1 {
   999  		t.Errorf("level-1 tables less than 1, got %d", v.tLen(1))
  1000  	}
  1001  	v.release()
  1002  
  1003  	for i := 0; i < n; i++ {
  1004  		h.getVal(numKey(i), strings.Repeat(fmt.Sprintf("v%09d", i), 100000/10))
  1005  	}
  1006  }
  1007  
  1008  func TestDB_RepeatedWritesToSameKey(t *testing.T) {
  1009  	h := newDbHarnessWopt(t, &opt.Options{DisableLargeBatchTransaction: true, WriteBuffer: 100000})
  1010  	defer h.close()
  1011  
  1012  	maxTables := h.o.GetWriteL0PauseTrigger() + 7
  1013  
  1014  	value := strings.Repeat("v", 2*h.o.GetWriteBuffer())
  1015  	for i := 0; i < 5*maxTables; i++ {
  1016  		h.put("key", value)
  1017  		n := h.totalTables()
  1018  		if n > maxTables {
  1019  			t.Errorf("total tables exceed %d, got=%d, iter=%d", maxTables, n, i)
  1020  		}
  1021  	}
  1022  }
  1023  
  1024  func TestDB_RepeatedWritesToSameKeyAfterReopen(t *testing.T) {
  1025  	h := newDbHarnessWopt(t, &opt.Options{
  1026  		DisableLargeBatchTransaction: true,
  1027  		WriteBuffer:                  100000,
  1028  	})
  1029  	defer h.close()
  1030  
  1031  	h.reopenDB()
  1032  
  1033  	maxTables := h.o.GetWriteL0PauseTrigger() + 7
  1034  
  1035  	value := strings.Repeat("v", 2*h.o.GetWriteBuffer())
  1036  	for i := 0; i < 5*maxTables; i++ {
  1037  		h.put("key", value)
  1038  		n := h.totalTables()
  1039  		if n > maxTables {
  1040  			t.Errorf("total tables exceed %d, got=%d, iter=%d", maxTables, n, i)
  1041  		}
  1042  	}
  1043  }
  1044  
  1045  func TestDB_SparseMerge(t *testing.T) {
  1046  	h := newDbHarnessWopt(t, &opt.Options{DisableLargeBatchTransaction: true, Compression: opt.NoCompression})
  1047  	defer h.close()
  1048  
  1049  	h.putMulti(7, "A", "Z")
  1050  
  1051  	// Suppose there is:
  1052  	//    small amount of data with prefix A
  1053  	//    large amount of data with prefix B
  1054  	//    small amount of data with prefix C
  1055  	// and that recent updates have made small changes to all three prefixes.
  1056  	// Check that we do not do a compaction that merges all of B in one shot.
  1057  	h.put("A", "va")
  1058  	value := strings.Repeat("x", 1000)
  1059  	for i := 0; i < 100000; i++ {
  1060  		h.put(fmt.Sprintf("B%010d", i), value)
  1061  	}
  1062  	h.put("C", "vc")
  1063  	h.compactMem()
  1064  	h.compactRangeAt(0, "", "")
  1065  	h.waitCompaction()
  1066  
  1067  	// Make sparse update
  1068  	h.put("A", "va2")
  1069  	h.put("B100", "bvalue2")
  1070  	h.put("C", "vc2")
  1071  	h.compactMem()
  1072  
  1073  	h.waitCompaction()
  1074  	h.maxNextLevelOverlappingBytes(20 * 1048576)
  1075  	h.compactRangeAt(0, "", "")
  1076  	h.waitCompaction()
  1077  	h.maxNextLevelOverlappingBytes(20 * 1048576)
  1078  	h.compactRangeAt(1, "", "")
  1079  	h.waitCompaction()
  1080  	h.maxNextLevelOverlappingBytes(20 * 1048576)
  1081  }
  1082  
  1083  func TestDB_SizeOf(t *testing.T) {
  1084  	h := newDbHarnessWopt(t, &opt.Options{
  1085  		DisableLargeBatchTransaction: true,
  1086  		Compression:                  opt.NoCompression,
  1087  		WriteBuffer:                  10000000,
  1088  	})
  1089  	defer h.close()
  1090  
  1091  	h.sizeAssert("", "xyz", 0, 0)
  1092  	h.reopenDB()
  1093  	h.sizeAssert("", "xyz", 0, 0)
  1094  
  1095  	// Write 8MB (80 values, each 100K)
  1096  	n := 80
  1097  	s1 := 100000
  1098  	s2 := 105000
  1099  
  1100  	for i := 0; i < n; i++ {
  1101  		h.put(numKey(i), strings.Repeat(fmt.Sprintf("v%09d", i), s1/10))
  1102  	}
  1103  
  1104  	// 0 because SizeOf() does not account for memtable space
  1105  	h.sizeAssert("", numKey(50), 0, 0)
  1106  
  1107  	for r := 0; r < 3; r++ {
  1108  		h.reopenDB()
  1109  
  1110  		for cs := 0; cs < n; cs += 10 {
  1111  			for i := 0; i < n; i += 10 {
  1112  				h.sizeAssert("", numKey(i), int64(s1*i), int64(s2*i))
  1113  				h.sizeAssert("", numKey(i)+".suffix", int64(s1*(i+1)), int64(s2*(i+1)))
  1114  				h.sizeAssert(numKey(i), numKey(i+10), int64(s1*10), int64(s2*10))
  1115  			}
  1116  
  1117  			h.sizeAssert("", numKey(50), int64(s1*50), int64(s2*50))
  1118  			h.sizeAssert("", numKey(50)+".suffix", int64(s1*50), int64(s2*50))
  1119  
  1120  			h.compactRangeAt(0, numKey(cs), numKey(cs+9))
  1121  		}
  1122  
  1123  		v := h.db.s.version()
  1124  		if v.tLen(0) != 0 {
  1125  			t.Errorf("level-0 tables was not zero, got %d", v.tLen(0))
  1126  		}
  1127  		if v.tLen(1) == 0 {
  1128  			t.Error("level-1 tables was zero")
  1129  		}
  1130  		v.release()
  1131  	}
  1132  }
  1133  
  1134  func TestDB_SizeOf_MixOfSmallAndLarge(t *testing.T) {
  1135  	h := newDbHarnessWopt(t, &opt.Options{
  1136  		DisableLargeBatchTransaction: true,
  1137  		Compression:                  opt.NoCompression,
  1138  	})
  1139  	defer h.close()
  1140  
  1141  	sizes := []int64{
  1142  		10000,
  1143  		10000,
  1144  		100000,
  1145  		10000,
  1146  		100000,
  1147  		10000,
  1148  		300000,
  1149  		10000,
  1150  	}
  1151  
  1152  	for i, n := range sizes {
  1153  		h.put(numKey(i), strings.Repeat(fmt.Sprintf("v%09d", i), int(n)/10))
  1154  	}
  1155  
  1156  	for r := 0; r < 3; r++ {
  1157  		h.reopenDB()
  1158  
  1159  		var x int64
  1160  		for i, n := range sizes {
  1161  			y := x
  1162  			if i > 0 {
  1163  				y += 1000
  1164  			}
  1165  			h.sizeAssert("", numKey(i), x, y)
  1166  			x += n
  1167  		}
  1168  
  1169  		h.sizeAssert(numKey(3), numKey(5), 110000, 111000)
  1170  
  1171  		h.compactRangeAt(0, "", "")
  1172  	}
  1173  }
  1174  
  1175  func TestDB_Snapshot(t *testing.T) {
  1176  	trun(t, func(h *dbHarness) {
  1177  		h.put("foo", "v1")
  1178  		s1 := h.getSnapshot()
  1179  		h.put("foo", "v2")
  1180  		s2 := h.getSnapshot()
  1181  		h.put("foo", "v3")
  1182  		s3 := h.getSnapshot()
  1183  		h.put("foo", "v4")
  1184  
  1185  		h.getValr(s1, "foo", "v1")
  1186  		h.getValr(s2, "foo", "v2")
  1187  		h.getValr(s3, "foo", "v3")
  1188  		h.getVal("foo", "v4")
  1189  
  1190  		s3.Release()
  1191  		h.getValr(s1, "foo", "v1")
  1192  		h.getValr(s2, "foo", "v2")
  1193  		h.getVal("foo", "v4")
  1194  
  1195  		s1.Release()
  1196  		h.getValr(s2, "foo", "v2")
  1197  		h.getVal("foo", "v4")
  1198  
  1199  		s2.Release()
  1200  		h.getVal("foo", "v4")
  1201  	})
  1202  }
  1203  
  1204  func TestDB_SnapshotList(t *testing.T) {
  1205  	db := &DB{snapsList: list.New()}
  1206  	e0a := db.acquireSnapshot()
  1207  	e0b := db.acquireSnapshot()
  1208  	db.seq = 1
  1209  	e1 := db.acquireSnapshot()
  1210  	db.seq = 2
  1211  	e2 := db.acquireSnapshot()
  1212  
  1213  	if db.minSeq() != 0 {
  1214  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1215  	}
  1216  	db.releaseSnapshot(e0a)
  1217  	if db.minSeq() != 0 {
  1218  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1219  	}
  1220  	db.releaseSnapshot(e2)
  1221  	if db.minSeq() != 0 {
  1222  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1223  	}
  1224  	db.releaseSnapshot(e0b)
  1225  	if db.minSeq() != 1 {
  1226  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1227  	}
  1228  	e2 = db.acquireSnapshot()
  1229  	if db.minSeq() != 1 {
  1230  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1231  	}
  1232  	db.releaseSnapshot(e1)
  1233  	if db.minSeq() != 2 {
  1234  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1235  	}
  1236  	db.releaseSnapshot(e2)
  1237  	if db.minSeq() != 2 {
  1238  		t.Fatalf("invalid sequence number, got=%d", db.minSeq())
  1239  	}
  1240  }
  1241  
  1242  func TestDB_HiddenValuesAreRemoved(t *testing.T) {
  1243  	trun(t, func(h *dbHarness) {
  1244  		s := h.db.s
  1245  
  1246  		m := 2
  1247  		h.db.memdbMaxLevel = m
  1248  
  1249  		h.put("foo", "v1")
  1250  		h.compactMem()
  1251  		v := s.version()
  1252  		num := v.tLen(m)
  1253  		v.release()
  1254  		if num != 1 {
  1255  			t.Errorf("invalid level-%d len, want=1 got=%d", m, num)
  1256  		}
  1257  
  1258  		// Place a table at level last-1 to prevent merging with preceding mutation
  1259  		h.put("a", "begin")
  1260  		h.put("z", "end")
  1261  		h.compactMem()
  1262  		v = s.version()
  1263  		if v.tLen(m) != 1 {
  1264  			t.Errorf("invalid level-%d len, want=1 got=%d", m, v.tLen(m))
  1265  		}
  1266  		if v.tLen(m-1) != 1 {
  1267  			t.Errorf("invalid level-%d len, want=1 got=%d", m-1, v.tLen(m-1))
  1268  		}
  1269  		v.release()
  1270  
  1271  		h.delete("foo")
  1272  		h.put("foo", "v2")
  1273  		h.allEntriesFor("foo", "[ v2, DEL, v1 ]")
  1274  		h.compactMem()
  1275  		h.allEntriesFor("foo", "[ v2, DEL, v1 ]")
  1276  		h.compactRangeAt(m-2, "", "z")
  1277  		// DEL eliminated, but v1 remains because we aren't compacting that level
  1278  		// (DEL can be eliminated because v2 hides v1).
  1279  		h.allEntriesFor("foo", "[ v2, v1 ]")
  1280  		h.compactRangeAt(m-1, "", "")
  1281  		// Merging last-1 w/ last, so we are the base level for "foo", so
  1282  		// DEL is removed.  (as is v1).
  1283  		h.allEntriesFor("foo", "[ v2 ]")
  1284  	})
  1285  }
  1286  
  1287  func TestDB_DeletionMarkers2(t *testing.T) {
  1288  	h := newDbHarness(t)
  1289  	defer h.close()
  1290  	s := h.db.s
  1291  
  1292  	m := 2
  1293  	h.db.memdbMaxLevel = m
  1294  
  1295  	h.put("foo", "v1")
  1296  	h.compactMem()
  1297  	v := s.version()
  1298  	num := v.tLen(m)
  1299  	v.release()
  1300  	if num != 1 {
  1301  		t.Errorf("invalid level-%d len, want=1 got=%d", m, num)
  1302  	}
  1303  
  1304  	// Place a table at level last-1 to prevent merging with preceding mutation
  1305  	h.put("a", "begin")
  1306  	h.put("z", "end")
  1307  	h.compactMem()
  1308  	v = s.version()
  1309  	if v.tLen(m) != 1 {
  1310  		t.Errorf("invalid level-%d len, want=1 got=%d", m, v.tLen(m))
  1311  	}
  1312  	if v.tLen(m-1) != 1 {
  1313  		t.Errorf("invalid level-%d len, want=1 got=%d", m-1, v.tLen(m-1))
  1314  	}
  1315  	v.release()
  1316  
  1317  	h.delete("foo")
  1318  	h.allEntriesFor("foo", "[ DEL, v1 ]")
  1319  	h.compactMem() // Moves to level last-2
  1320  	h.allEntriesFor("foo", "[ DEL, v1 ]")
  1321  	h.compactRangeAt(m-2, "", "")
  1322  	// DEL kept: "last" file overlaps
  1323  	h.allEntriesFor("foo", "[ DEL, v1 ]")
  1324  	h.compactRangeAt(m-1, "", "")
  1325  	// Merging last-1 w/ last, so we are the base level for "foo", so
  1326  	// DEL is removed.  (as is v1).
  1327  	h.allEntriesFor("foo", "[ ]")
  1328  }
  1329  
  1330  func TestDB_CompactionTableOpenError(t *testing.T) {
  1331  	h := newDbHarnessWopt(t, &opt.Options{
  1332  		DisableLargeBatchTransaction: true,
  1333  		OpenFilesCacheCapacity:       -1,
  1334  	})
  1335  	defer h.close()
  1336  
  1337  	h.db.memdbMaxLevel = 2
  1338  
  1339  	im := 10
  1340  	jm := 10
  1341  	for r := 0; r < 2; r++ {
  1342  		for i := 0; i < im; i++ {
  1343  			for j := 0; j < jm; j++ {
  1344  				h.put(fmt.Sprintf("k%d,%d", i, j), fmt.Sprintf("v%d,%d", i, j))
  1345  			}
  1346  			h.compactMem()
  1347  		}
  1348  	}
  1349  
  1350  	if n := h.totalTables(); n != im*2 {
  1351  		t.Errorf("total tables is %d, want %d", n, im*2)
  1352  	}
  1353  
  1354  	h.stor.EmulateError(testutil.ModeOpen, storage.TypeTable, errors.New("open error during table compaction"))
  1355  	go h.db.CompactRange(util.Range{})
  1356  	if err := h.db.compTriggerWait(h.db.tcompCmdC); err != nil {
  1357  		t.Log("compaction error: ", err)
  1358  	}
  1359  	h.closeDB0()
  1360  	h.openDB()
  1361  	h.stor.EmulateError(testutil.ModeOpen, storage.TypeTable, nil)
  1362  
  1363  	for i := 0; i < im; i++ {
  1364  		for j := 0; j < jm; j++ {
  1365  			h.getVal(fmt.Sprintf("k%d,%d", i, j), fmt.Sprintf("v%d,%d", i, j))
  1366  		}
  1367  	}
  1368  }
  1369  
  1370  func TestDB_OverlapInLevel0(t *testing.T) {
  1371  	trun(t, func(h *dbHarness) {
  1372  		h.db.memdbMaxLevel = 2
  1373  
  1374  		// Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0.
  1375  		h.put("100", "v100")
  1376  		h.put("999", "v999")
  1377  		h.compactMem()
  1378  		h.delete("100")
  1379  		h.delete("999")
  1380  		h.compactMem()
  1381  		h.tablesPerLevel("0,1,1")
  1382  
  1383  		// Make files spanning the following ranges in level-0:
  1384  		//  files[0]  200 .. 900
  1385  		//  files[1]  300 .. 500
  1386  		// Note that files are sorted by min key.
  1387  		h.put("300", "v300")
  1388  		h.put("500", "v500")
  1389  		h.compactMem()
  1390  		h.put("200", "v200")
  1391  		h.put("600", "v600")
  1392  		h.put("900", "v900")
  1393  		h.compactMem()
  1394  		h.tablesPerLevel("2,1,1")
  1395  
  1396  		// Compact away the placeholder files we created initially
  1397  		h.compactRangeAt(1, "", "")
  1398  		h.compactRangeAt(2, "", "")
  1399  		h.tablesPerLevel("2")
  1400  
  1401  		// Do a memtable compaction.  Before bug-fix, the compaction would
  1402  		// not detect the overlap with level-0 files and would incorrectly place
  1403  		// the deletion in a deeper level.
  1404  		h.delete("600")
  1405  		h.compactMem()
  1406  		h.tablesPerLevel("3")
  1407  		h.get("600", false)
  1408  	})
  1409  }
  1410  
  1411  func TestDB_L0_CompactionBug_Issue44_a(t *testing.T) {
  1412  	h := newDbHarness(t)
  1413  	defer h.close()
  1414  
  1415  	h.reopenDB()
  1416  	h.put("b", "v")
  1417  	h.reopenDB()
  1418  	h.delete("b")
  1419  	h.delete("a")
  1420  	h.reopenDB()
  1421  	h.delete("a")
  1422  	h.reopenDB()
  1423  	h.put("a", "v")
  1424  	h.reopenDB()
  1425  	h.reopenDB()
  1426  	h.getKeyVal("(a->v)")
  1427  	h.waitCompaction()
  1428  	h.getKeyVal("(a->v)")
  1429  }
  1430  
  1431  func TestDB_L0_CompactionBug_Issue44_b(t *testing.T) {
  1432  	h := newDbHarness(t)
  1433  	defer h.close()
  1434  
  1435  	h.reopenDB()
  1436  	h.put("", "")
  1437  	h.reopenDB()
  1438  	h.delete("e")
  1439  	h.put("", "")
  1440  	h.reopenDB()
  1441  	h.put("c", "cv")
  1442  	h.reopenDB()
  1443  	h.put("", "")
  1444  	h.reopenDB()
  1445  	h.put("", "")
  1446  	h.waitCompaction()
  1447  	h.reopenDB()
  1448  	h.put("d", "dv")
  1449  	h.reopenDB()
  1450  	h.put("", "")
  1451  	h.reopenDB()
  1452  	h.delete("d")
  1453  	h.delete("b")
  1454  	h.reopenDB()
  1455  	h.getKeyVal("(->)(c->cv)")
  1456  	h.waitCompaction()
  1457  	h.getKeyVal("(->)(c->cv)")
  1458  }
  1459  
  1460  func TestDB_SingleEntryMemCompaction(t *testing.T) {
  1461  	trun(t, func(h *dbHarness) {
  1462  		for i := 0; i < 10; i++ {
  1463  			h.put("big", strings.Repeat("v", opt.DefaultWriteBuffer))
  1464  			h.compactMem()
  1465  			h.put("key", strings.Repeat("v", opt.DefaultBlockSize))
  1466  			h.compactMem()
  1467  			h.put("k", "v")
  1468  			h.compactMem()
  1469  			h.put("", "")
  1470  			h.compactMem()
  1471  			h.put("verybig", strings.Repeat("v", opt.DefaultWriteBuffer*2))
  1472  			h.compactMem()
  1473  		}
  1474  	})
  1475  }
  1476  
  1477  func TestDB_ManifestWriteError(t *testing.T) {
  1478  	for i := 0; i < 2; i++ {
  1479  		func() {
  1480  			h := newDbHarness(t)
  1481  			defer h.close()
  1482  
  1483  			h.put("foo", "bar")
  1484  			h.getVal("foo", "bar")
  1485  
  1486  			// Mem compaction (will succeed)
  1487  			h.compactMem()
  1488  			h.getVal("foo", "bar")
  1489  			v := h.db.s.version()
  1490  			if n := v.tLen(0); n != 1 {
  1491  				t.Errorf("invalid total tables, want=1 got=%d", n)
  1492  			}
  1493  			v.release()
  1494  
  1495  			if i == 0 {
  1496  				h.stor.EmulateError(testutil.ModeWrite, storage.TypeManifest, errors.New("manifest write error"))
  1497  			} else {
  1498  				h.stor.EmulateError(testutil.ModeSync, storage.TypeManifest, errors.New("manifest sync error"))
  1499  			}
  1500  
  1501  			// Merging compaction (will fail)
  1502  			h.compactRangeAtErr(0, "", "", true)
  1503  
  1504  			h.db.Close()
  1505  			h.stor.EmulateError(testutil.ModeWrite, storage.TypeManifest, nil)
  1506  			h.stor.EmulateError(testutil.ModeSync, storage.TypeManifest, nil)
  1507  
  1508  			// Should not lose data
  1509  			h.openDB()
  1510  			h.getVal("foo", "bar")
  1511  		}()
  1512  	}
  1513  }
  1514  
  1515  func assertErr(t *testing.T, err error, wanterr bool) {
  1516  	if err != nil {
  1517  		if wanterr {
  1518  			t.Log("AssertErr: got error (expected): ", err)
  1519  		} else {
  1520  			t.Error("AssertErr: got error: ", err)
  1521  		}
  1522  	} else if wanterr {
  1523  		t.Error("AssertErr: expect error")
  1524  	}
  1525  }
  1526  
  1527  func TestDB_ClosedIsClosed(t *testing.T) {
  1528  	h := newDbHarness(t)
  1529  	db := h.db
  1530  
  1531  	var iter, iter2 iterator.Iterator
  1532  	var snap *Snapshot
  1533  	func() {
  1534  		defer h.close()
  1535  
  1536  		h.put("k", "v")
  1537  		h.getVal("k", "v")
  1538  
  1539  		iter = db.NewIterator(nil, h.ro)
  1540  		iter.Seek([]byte("k"))
  1541  		testKeyVal(t, iter, "k->v")
  1542  
  1543  		var err error
  1544  		snap, err = db.GetSnapshot()
  1545  		if err != nil {
  1546  			t.Fatal("GetSnapshot: got error: ", err)
  1547  		}
  1548  
  1549  		h.getValr(snap, "k", "v")
  1550  
  1551  		iter2 = snap.NewIterator(nil, h.ro)
  1552  		iter2.Seek([]byte("k"))
  1553  		testKeyVal(t, iter2, "k->v")
  1554  
  1555  		h.put("foo", "v2")
  1556  		h.delete("foo")
  1557  
  1558  		// closing DB
  1559  		iter.Release()
  1560  		iter2.Release()
  1561  	}()
  1562  
  1563  	assertErr(t, db.Put([]byte("x"), []byte("y"), h.wo), true)
  1564  	_, err := db.Get([]byte("k"), h.ro)
  1565  	assertErr(t, err, true)
  1566  
  1567  	if iter.Valid() {
  1568  		t.Errorf("iter.Valid should false")
  1569  	}
  1570  	assertErr(t, iter.Error(), false)
  1571  	testKeyVal(t, iter, "->")
  1572  	if iter.Seek([]byte("k")) {
  1573  		t.Errorf("iter.Seek should false")
  1574  	}
  1575  	assertErr(t, iter.Error(), true)
  1576  
  1577  	assertErr(t, iter2.Error(), false)
  1578  
  1579  	_, err = snap.Get([]byte("k"), h.ro)
  1580  	assertErr(t, err, true)
  1581  
  1582  	_, err = db.GetSnapshot()
  1583  	assertErr(t, err, true)
  1584  
  1585  	iter3 := db.NewIterator(nil, h.ro)
  1586  	assertErr(t, iter3.Error(), true)
  1587  
  1588  	iter3 = snap.NewIterator(nil, h.ro)
  1589  	assertErr(t, iter3.Error(), true)
  1590  
  1591  	assertErr(t, db.Delete([]byte("k"), h.wo), true)
  1592  
  1593  	_, err = db.GetProperty("leveldb.stats")
  1594  	assertErr(t, err, true)
  1595  
  1596  	_, err = db.SizeOf([]util.Range{{[]byte("a"), []byte("z")}})
  1597  	assertErr(t, err, true)
  1598  
  1599  	assertErr(t, db.CompactRange(util.Range{}), true)
  1600  
  1601  	assertErr(t, db.Close(), true)
  1602  }
  1603  
  1604  type numberComparer struct{}
  1605  
  1606  func (numberComparer) num(x []byte) (n int) {
  1607  	fmt.Sscan(string(x[1:len(x)-1]), &n)
  1608  	return
  1609  }
  1610  
  1611  func (numberComparer) Name() string {
  1612  	return "test.NumberComparer"
  1613  }
  1614  
  1615  func (p numberComparer) Compare(a, b []byte) int {
  1616  	return p.num(a) - p.num(b)
  1617  }
  1618  
  1619  func (numberComparer) Separator(dst, a, b []byte) []byte { return nil }
  1620  func (numberComparer) Successor(dst, b []byte) []byte    { return nil }
  1621  
  1622  func TestDB_CustomComparer(t *testing.T) {
  1623  	h := newDbHarnessWopt(t, &opt.Options{
  1624  		DisableLargeBatchTransaction: true,
  1625  		Comparer:                     numberComparer{},
  1626  		WriteBuffer:                  1000,
  1627  	})
  1628  	defer h.close()
  1629  
  1630  	h.put("[10]", "ten")
  1631  	h.put("[0x14]", "twenty")
  1632  	for i := 0; i < 2; i++ {
  1633  		h.getVal("[10]", "ten")
  1634  		h.getVal("[0xa]", "ten")
  1635  		h.getVal("[20]", "twenty")
  1636  		h.getVal("[0x14]", "twenty")
  1637  		h.get("[15]", false)
  1638  		h.get("[0xf]", false)
  1639  		h.compactMem()
  1640  		h.compactRange("[0]", "[9999]")
  1641  	}
  1642  
  1643  	for n := 0; n < 2; n++ {
  1644  		for i := 0; i < 100; i++ {
  1645  			v := fmt.Sprintf("[%d]", i*10)
  1646  			h.put(v, v)
  1647  		}
  1648  		h.compactMem()
  1649  		h.compactRange("[0]", "[1000000]")
  1650  	}
  1651  }
  1652  
  1653  func TestDB_ManualCompaction(t *testing.T) {
  1654  	h := newDbHarness(t)
  1655  	defer h.close()
  1656  
  1657  	h.db.memdbMaxLevel = 2
  1658  
  1659  	h.putMulti(3, "p", "q")
  1660  	h.tablesPerLevel("1,1,1")
  1661  
  1662  	// Compaction range falls before files
  1663  	h.compactRange("", "c")
  1664  	h.tablesPerLevel("1,1,1")
  1665  
  1666  	// Compaction range falls after files
  1667  	h.compactRange("r", "z")
  1668  	h.tablesPerLevel("1,1,1")
  1669  
  1670  	// Compaction range overlaps files
  1671  	h.compactRange("p1", "p9")
  1672  	h.tablesPerLevel("0,0,1")
  1673  
  1674  	// Populate a different range
  1675  	h.putMulti(3, "c", "e")
  1676  	h.tablesPerLevel("1,1,2")
  1677  
  1678  	// Compact just the new range
  1679  	h.compactRange("b", "f")
  1680  	h.tablesPerLevel("0,0,2")
  1681  
  1682  	// Compact all
  1683  	h.putMulti(1, "a", "z")
  1684  	h.tablesPerLevel("0,1,2")
  1685  	h.compactRange("", "")
  1686  	h.tablesPerLevel("0,0,1")
  1687  }
  1688  
  1689  func TestDB_BloomFilter(t *testing.T) {
  1690  	h := newDbHarnessWopt(t, &opt.Options{
  1691  		DisableLargeBatchTransaction: true,
  1692  		DisableBlockCache:            true,
  1693  		Filter:                       filter.NewBloomFilter(10),
  1694  	})
  1695  	defer h.close()
  1696  
  1697  	key := func(i int) string {
  1698  		return fmt.Sprintf("key%06d", i)
  1699  	}
  1700  
  1701  	const n = 10000
  1702  
  1703  	// Populate multiple layers
  1704  	for i := 0; i < n; i++ {
  1705  		h.put(key(i), key(i))
  1706  	}
  1707  	h.compactMem()
  1708  	h.compactRange("a", "z")
  1709  	for i := 0; i < n; i += 100 {
  1710  		h.put(key(i), key(i))
  1711  	}
  1712  	h.compactMem()
  1713  
  1714  	// Prevent auto compactions triggered by seeks
  1715  	h.stor.Stall(testutil.ModeSync, storage.TypeTable)
  1716  
  1717  	// Lookup present keys. Should rarely read from small sstable.
  1718  	h.stor.ResetCounter(testutil.ModeRead, storage.TypeTable)
  1719  	for i := 0; i < n; i++ {
  1720  		h.getVal(key(i), key(i))
  1721  	}
  1722  	cnt, _ := h.stor.Counter(testutil.ModeRead, storage.TypeTable)
  1723  	t.Logf("lookup of %d present keys yield %d sstable I/O reads", n, cnt)
  1724  	if min, max := n, n+2*n/100; cnt < min || cnt > max {
  1725  		t.Errorf("num of sstable I/O reads of present keys not in range of %d - %d, got %d", min, max, cnt)
  1726  	}
  1727  
  1728  	// Lookup missing keys. Should rarely read from either sstable.
  1729  	h.stor.ResetCounter(testutil.ModeRead, storage.TypeTable)
  1730  	for i := 0; i < n; i++ {
  1731  		h.get(key(i)+".missing", false)
  1732  	}
  1733  	cnt, _ = h.stor.Counter(testutil.ModeRead, storage.TypeTable)
  1734  	t.Logf("lookup of %d missing keys yield %d sstable I/O reads", n, cnt)
  1735  	if max := 3 * n / 100; cnt > max {
  1736  		t.Errorf("num of sstable I/O reads of missing keys was more than %d, got %d", max, cnt)
  1737  	}
  1738  
  1739  	h.stor.Release(testutil.ModeSync, storage.TypeTable)
  1740  }
  1741  
  1742  func TestDB_Concurrent(t *testing.T) {
  1743  	const n, secs, maxkey = 4, 6, 1000
  1744  	h := newDbHarness(t)
  1745  	defer h.close()
  1746  
  1747  	runtime.GOMAXPROCS(runtime.NumCPU())
  1748  
  1749  	var (
  1750  		closeWg sync.WaitGroup
  1751  		stop    uint32
  1752  		cnt     [n]uint32
  1753  	)
  1754  
  1755  	for i := 0; i < n; i++ {
  1756  		closeWg.Add(1)
  1757  		go func(i int) {
  1758  			var put, get, found uint
  1759  			defer func() {
  1760  				t.Logf("goroutine %d stopped after %d ops, put=%d get=%d found=%d missing=%d",
  1761  					i, cnt[i], put, get, found, get-found)
  1762  				closeWg.Done()
  1763  			}()
  1764  
  1765  			rnd := rand.New(rand.NewSource(int64(1000 + i)))
  1766  			for atomic.LoadUint32(&stop) == 0 {
  1767  				x := cnt[i]
  1768  
  1769  				k := rnd.Intn(maxkey)
  1770  				kstr := fmt.Sprintf("%016d", k)
  1771  
  1772  				if (rnd.Int() % 2) > 0 {
  1773  					put++
  1774  					h.put(kstr, fmt.Sprintf("%d.%d.%-1000d", k, i, x))
  1775  				} else {
  1776  					get++
  1777  					v, err := h.db.Get([]byte(kstr), h.ro)
  1778  					if err == nil {
  1779  						found++
  1780  						rk, ri, rx := 0, -1, uint32(0)
  1781  						fmt.Sscanf(string(v), "%d.%d.%d", &rk, &ri, &rx)
  1782  						if rk != k {
  1783  							t.Errorf("invalid key want=%d got=%d", k, rk)
  1784  						}
  1785  						if ri < 0 || ri >= n {
  1786  							t.Error("invalid goroutine number: ", ri)
  1787  						} else {
  1788  							tx := atomic.LoadUint32(&(cnt[ri]))
  1789  							if rx > tx {
  1790  								t.Errorf("invalid seq number, %d > %d ", rx, tx)
  1791  							}
  1792  						}
  1793  					} else if err != ErrNotFound {
  1794  						t.Error("Get: got error: ", err)
  1795  						return
  1796  					}
  1797  				}
  1798  				atomic.AddUint32(&cnt[i], 1)
  1799  			}
  1800  		}(i)
  1801  	}
  1802  
  1803  	time.Sleep(secs * time.Second)
  1804  	atomic.StoreUint32(&stop, 1)
  1805  	closeWg.Wait()
  1806  }
  1807  
  1808  func TestDB_ConcurrentIterator(t *testing.T) {
  1809  	const n, n2 = 4, 1000
  1810  	h := newDbHarnessWopt(t, &opt.Options{DisableLargeBatchTransaction: true, WriteBuffer: 30})
  1811  	defer h.close()
  1812  
  1813  	runtime.GOMAXPROCS(runtime.NumCPU())
  1814  
  1815  	var (
  1816  		closeWg sync.WaitGroup
  1817  		stop    uint32
  1818  	)
  1819  
  1820  	for i := 0; i < n; i++ {
  1821  		closeWg.Add(1)
  1822  		go func(i int) {
  1823  			for k := 0; atomic.LoadUint32(&stop) == 0; k++ {
  1824  				h.put(fmt.Sprintf("k%d", k), fmt.Sprintf("%d.%d.", k, i)+strings.Repeat("x", 10))
  1825  			}
  1826  			closeWg.Done()
  1827  		}(i)
  1828  	}
  1829  
  1830  	for i := 0; i < n; i++ {
  1831  		closeWg.Add(1)
  1832  		go func(i int) {
  1833  			for k := 1000000; k < 0 || atomic.LoadUint32(&stop) == 0; k-- {
  1834  				h.put(fmt.Sprintf("k%d", k), fmt.Sprintf("%d.%d.", k, i)+strings.Repeat("x", 10))
  1835  			}
  1836  			closeWg.Done()
  1837  		}(i)
  1838  	}
  1839  
  1840  	cmp := comparer.DefaultComparer
  1841  	for i := 0; i < n2; i++ {
  1842  		closeWg.Add(1)
  1843  		go func(i int) {
  1844  			it := h.db.NewIterator(nil, nil)
  1845  			var pk []byte
  1846  			for it.Next() {
  1847  				kk := it.Key()
  1848  				if cmp.Compare(kk, pk) <= 0 {
  1849  					t.Errorf("iter %d: %q is successor of %q", i, pk, kk)
  1850  				}
  1851  				pk = append(pk[:0], kk...)
  1852  				var k, vk, vi int
  1853  				if n, err := fmt.Sscanf(string(it.Key()), "k%d", &k); err != nil {
  1854  					t.Errorf("iter %d: Scanf error on key %q: %v", i, it.Key(), err)
  1855  				} else if n < 1 {
  1856  					t.Errorf("iter %d: Cannot parse key %q", i, it.Key())
  1857  				}
  1858  				if n, err := fmt.Sscanf(string(it.Value()), "%d.%d", &vk, &vi); err != nil {
  1859  					t.Errorf("iter %d: Scanf error on value %q: %v", i, it.Value(), err)
  1860  				} else if n < 2 {
  1861  					t.Errorf("iter %d: Cannot parse value %q", i, it.Value())
  1862  				}
  1863  
  1864  				if vk != k {
  1865  					t.Errorf("iter %d: invalid value i=%d, want=%d got=%d", i, vi, k, vk)
  1866  				}
  1867  			}
  1868  			if err := it.Error(); err != nil {
  1869  				t.Errorf("iter %d: Got error: %v", i, err)
  1870  			}
  1871  			it.Release()
  1872  			closeWg.Done()
  1873  		}(i)
  1874  	}
  1875  
  1876  	atomic.StoreUint32(&stop, 1)
  1877  	closeWg.Wait()
  1878  }
  1879  
  1880  func TestDB_ConcurrentWrite(t *testing.T) {
  1881  	const n, niter = 10, 10000
  1882  	h := newDbHarness(t)
  1883  	defer h.close()
  1884  
  1885  	runtime.GOMAXPROCS(runtime.NumCPU())
  1886  
  1887  	var wg sync.WaitGroup
  1888  	for i := 0; i < n; i++ {
  1889  		wg.Add(1)
  1890  		go func(i int) {
  1891  			defer wg.Done()
  1892  			for k := 0; k < niter; k++ {
  1893  				kstr := fmt.Sprintf("%d.%d", i, k)
  1894  				vstr := fmt.Sprintf("v%d", k)
  1895  				h.put(kstr, vstr)
  1896  				// Key should immediately available after put returns.
  1897  				h.getVal(kstr, vstr)
  1898  			}
  1899  		}(i)
  1900  	}
  1901  	wg.Wait()
  1902  }
  1903  
  1904  func TestDB_CreateReopenDbOnFile(t *testing.T) {
  1905  	dbpath := filepath.Join(os.TempDir(), fmt.Sprintf("goleveldbtestCreateReopenDbOnFile-%d", os.Getuid()))
  1906  	if err := os.RemoveAll(dbpath); err != nil {
  1907  		t.Fatal("cannot remove old db: ", err)
  1908  	}
  1909  	defer os.RemoveAll(dbpath)
  1910  
  1911  	for i := 0; i < 3; i++ {
  1912  		stor, err := storage.OpenFile(dbpath, false)
  1913  		if err != nil {
  1914  			t.Fatalf("(%d) cannot open storage: %s", i, err)
  1915  		}
  1916  		db, err := Open(stor, nil)
  1917  		if err != nil {
  1918  			t.Fatalf("(%d) cannot open db: %s", i, err)
  1919  		}
  1920  		if err := db.Put([]byte("foo"), []byte("bar"), nil); err != nil {
  1921  			t.Fatalf("(%d) cannot write to db: %s", i, err)
  1922  		}
  1923  		if err := db.Close(); err != nil {
  1924  			t.Fatalf("(%d) cannot close db: %s", i, err)
  1925  		}
  1926  		if err := stor.Close(); err != nil {
  1927  			t.Fatalf("(%d) cannot close storage: %s", i, err)
  1928  		}
  1929  	}
  1930  }
  1931  
  1932  func TestDB_CreateReopenDbOnFile2(t *testing.T) {
  1933  	dbpath := filepath.Join(os.TempDir(), fmt.Sprintf("goleveldbtestCreateReopenDbOnFile2-%d", os.Getuid()))
  1934  	if err := os.RemoveAll(dbpath); err != nil {
  1935  		t.Fatal("cannot remove old db: ", err)
  1936  	}
  1937  	defer os.RemoveAll(dbpath)
  1938  
  1939  	for i := 0; i < 3; i++ {
  1940  		db, err := OpenFile(dbpath, nil)
  1941  		if err != nil {
  1942  			t.Fatalf("(%d) cannot open db: %s", i, err)
  1943  		}
  1944  		if err := db.Put([]byte("foo"), []byte("bar"), nil); err != nil {
  1945  			t.Fatalf("(%d) cannot write to db: %s", i, err)
  1946  		}
  1947  		if err := db.Close(); err != nil {
  1948  			t.Fatalf("(%d) cannot close db: %s", i, err)
  1949  		}
  1950  	}
  1951  }
  1952  
  1953  func TestDB_DeletionMarkersOnMemdb(t *testing.T) {
  1954  	h := newDbHarness(t)
  1955  	defer h.close()
  1956  
  1957  	h.put("foo", "v1")
  1958  	h.compactMem()
  1959  	h.delete("foo")
  1960  	h.get("foo", false)
  1961  	h.getKeyVal("")
  1962  }
  1963  
  1964  func TestDB_LeveldbIssue178(t *testing.T) {
  1965  	nKeys := (opt.DefaultCompactionTableSize / 30) * 5
  1966  	key1 := func(i int) string {
  1967  		return fmt.Sprintf("my_key_%d", i)
  1968  	}
  1969  	key2 := func(i int) string {
  1970  		return fmt.Sprintf("my_key_%d_xxx", i)
  1971  	}
  1972  
  1973  	// Disable compression since it affects the creation of layers and the
  1974  	// code below is trying to test against a very specific scenario.
  1975  	h := newDbHarnessWopt(t, &opt.Options{
  1976  		DisableLargeBatchTransaction: true,
  1977  		Compression:                  opt.NoCompression,
  1978  	})
  1979  	defer h.close()
  1980  
  1981  	// Create first key range.
  1982  	batch := new(Batch)
  1983  	for i := 0; i < nKeys; i++ {
  1984  		batch.Put([]byte(key1(i)), []byte("value for range 1 key"))
  1985  	}
  1986  	h.write(batch)
  1987  
  1988  	// Create second key range.
  1989  	batch.Reset()
  1990  	for i := 0; i < nKeys; i++ {
  1991  		batch.Put([]byte(key2(i)), []byte("value for range 2 key"))
  1992  	}
  1993  	h.write(batch)
  1994  
  1995  	// Delete second key range.
  1996  	batch.Reset()
  1997  	for i := 0; i < nKeys; i++ {
  1998  		batch.Delete([]byte(key2(i)))
  1999  	}
  2000  	h.write(batch)
  2001  	h.waitMemCompaction()
  2002  
  2003  	// Run manual compaction.
  2004  	h.compactRange(key1(0), key1(nKeys-1))
  2005  
  2006  	// Checking the keys.
  2007  	h.assertNumKeys(nKeys)
  2008  }
  2009  
  2010  func TestDB_LeveldbIssue200(t *testing.T) {
  2011  	h := newDbHarness(t)
  2012  	defer h.close()
  2013  
  2014  	h.put("1", "b")
  2015  	h.put("2", "c")
  2016  	h.put("3", "d")
  2017  	h.put("4", "e")
  2018  	h.put("5", "f")
  2019  
  2020  	iter := h.db.NewIterator(nil, h.ro)
  2021  
  2022  	// Add an element that should not be reflected in the iterator.
  2023  	h.put("25", "cd")
  2024  
  2025  	iter.Seek([]byte("5"))
  2026  	assertBytes(t, []byte("5"), iter.Key())
  2027  	iter.Prev()
  2028  	assertBytes(t, []byte("4"), iter.Key())
  2029  	iter.Prev()
  2030  	assertBytes(t, []byte("3"), iter.Key())
  2031  	iter.Next()
  2032  	assertBytes(t, []byte("4"), iter.Key())
  2033  	iter.Next()
  2034  	assertBytes(t, []byte("5"), iter.Key())
  2035  }
  2036  
  2037  func TestDB_GoleveldbIssue74(t *testing.T) {
  2038  	h := newDbHarnessWopt(t, &opt.Options{
  2039  		DisableLargeBatchTransaction: true,
  2040  		WriteBuffer:                  1 * opt.MiB,
  2041  	})
  2042  	defer h.close()
  2043  
  2044  	const n, dur = 10000, 5 * time.Second
  2045  
  2046  	runtime.GOMAXPROCS(runtime.NumCPU())
  2047  
  2048  	until := time.Now().Add(dur)
  2049  	wg := new(sync.WaitGroup)
  2050  	wg.Add(2)
  2051  	var done uint32
  2052  	go func() {
  2053  		var i int
  2054  		defer func() {
  2055  			t.Logf("WRITER DONE #%d", i)
  2056  			atomic.StoreUint32(&done, 1)
  2057  			wg.Done()
  2058  		}()
  2059  
  2060  		b := new(Batch)
  2061  		for ; time.Now().Before(until) && atomic.LoadUint32(&done) == 0; i++ {
  2062  			iv := fmt.Sprintf("VAL%010d", i)
  2063  			for k := 0; k < n; k++ {
  2064  				key := fmt.Sprintf("KEY%06d", k)
  2065  				b.Put([]byte(key), []byte(key+iv))
  2066  				b.Put([]byte(fmt.Sprintf("PTR%06d", k)), []byte(key))
  2067  			}
  2068  			h.write(b)
  2069  
  2070  			b.Reset()
  2071  			snap := h.getSnapshot()
  2072  			iter := snap.NewIterator(util.BytesPrefix([]byte("PTR")), nil)
  2073  			var k int
  2074  			for ; iter.Next(); k++ {
  2075  				ptrKey := iter.Key()
  2076  				key := iter.Value()
  2077  
  2078  				if _, err := snap.Get(ptrKey, nil); err != nil {
  2079  					t.Fatalf("WRITER #%d snapshot.Get %q: %v", i, ptrKey, err)
  2080  				}
  2081  				if value, err := snap.Get(key, nil); err != nil {
  2082  					t.Fatalf("WRITER #%d snapshot.Get %q: %v", i, key, err)
  2083  				} else if string(value) != string(key)+iv {
  2084  					t.Fatalf("WRITER #%d snapshot.Get %q got invalid value, want %q got %q", i, key, string(key)+iv, value)
  2085  				}
  2086  
  2087  				b.Delete(key)
  2088  				b.Delete(ptrKey)
  2089  			}
  2090  			h.write(b)
  2091  			iter.Release()
  2092  			snap.Release()
  2093  			if k != n {
  2094  				t.Fatalf("#%d %d != %d", i, k, n)
  2095  			}
  2096  		}
  2097  	}()
  2098  	go func() {
  2099  		var i int
  2100  		defer func() {
  2101  			t.Logf("READER DONE #%d", i)
  2102  			atomic.StoreUint32(&done, 1)
  2103  			wg.Done()
  2104  		}()
  2105  		for ; time.Now().Before(until) && atomic.LoadUint32(&done) == 0; i++ {
  2106  			snap := h.getSnapshot()
  2107  			iter := snap.NewIterator(util.BytesPrefix([]byte("PTR")), nil)
  2108  			var prevValue string
  2109  			var k int
  2110  			for ; iter.Next(); k++ {
  2111  				ptrKey := iter.Key()
  2112  				key := iter.Value()
  2113  
  2114  				if _, err := snap.Get(ptrKey, nil); err != nil {
  2115  					t.Fatalf("READER #%d snapshot.Get %q: %v", i, ptrKey, err)
  2116  				}
  2117  
  2118  				if value, err := snap.Get(key, nil); err != nil {
  2119  					t.Fatalf("READER #%d snapshot.Get %q: %v", i, key, err)
  2120  				} else if prevValue != "" && string(value) != string(key)+prevValue {
  2121  					t.Fatalf("READER #%d snapshot.Get %q got invalid value, want %q got %q", i, key, string(key)+prevValue, value)
  2122  				} else {
  2123  					prevValue = string(value[len(key):])
  2124  				}
  2125  			}
  2126  			iter.Release()
  2127  			snap.Release()
  2128  			if k > 0 && k != n {
  2129  				t.Fatalf("#%d %d != %d", i, k, n)
  2130  			}
  2131  		}
  2132  	}()
  2133  	wg.Wait()
  2134  }
  2135  
  2136  func TestDB_GetProperties(t *testing.T) {
  2137  	h := newDbHarness(t)
  2138  	defer h.close()
  2139  
  2140  	_, err := h.db.GetProperty("leveldb.num-files-at-level")
  2141  	if err == nil {
  2142  		t.Error("GetProperty() failed to detect missing level")
  2143  	}
  2144  
  2145  	_, err = h.db.GetProperty("leveldb.num-files-at-level0")
  2146  	if err != nil {
  2147  		t.Error("got unexpected error", err)
  2148  	}
  2149  
  2150  	_, err = h.db.GetProperty("leveldb.num-files-at-level0x")
  2151  	if err == nil {
  2152  		t.Error("GetProperty() failed to detect invalid level")
  2153  	}
  2154  }
  2155  
  2156  func TestDB_GoleveldbIssue72and83(t *testing.T) {
  2157  	h := newDbHarnessWopt(t, &opt.Options{
  2158  		DisableLargeBatchTransaction: true,
  2159  		WriteBuffer:                  1 * opt.MiB,
  2160  		OpenFilesCacheCapacity:       3,
  2161  	})
  2162  	defer h.close()
  2163  
  2164  	const n, wn, dur = 10000, 100, 30 * time.Second
  2165  
  2166  	runtime.GOMAXPROCS(runtime.NumCPU())
  2167  
  2168  	randomData := func(prefix byte, i int) []byte {
  2169  		data := make([]byte, 1+4+32+64+32)
  2170  		_, err := crand.Reader.Read(data[1 : len(data)-8])
  2171  		if err != nil {
  2172  			panic(err)
  2173  		}
  2174  		data[0] = prefix
  2175  		binary.LittleEndian.PutUint32(data[len(data)-8:], uint32(i))
  2176  		binary.LittleEndian.PutUint32(data[len(data)-4:], util.NewCRC(data[:len(data)-4]).Value())
  2177  		return data
  2178  	}
  2179  
  2180  	keys := make([][]byte, n)
  2181  	for i := range keys {
  2182  		keys[i] = randomData(1, 0)
  2183  	}
  2184  
  2185  	until := time.Now().Add(dur)
  2186  	wg := new(sync.WaitGroup)
  2187  	wg.Add(3)
  2188  	var done uint32
  2189  	go func() {
  2190  		i := 0
  2191  		defer func() {
  2192  			t.Logf("WRITER DONE #%d", i)
  2193  			wg.Done()
  2194  		}()
  2195  
  2196  		b := new(Batch)
  2197  		for ; i < wn && atomic.LoadUint32(&done) == 0; i++ {
  2198  			b.Reset()
  2199  			for _, k1 := range keys {
  2200  				k2 := randomData(2, i)
  2201  				b.Put(k2, randomData(42, i))
  2202  				b.Put(k1, k2)
  2203  			}
  2204  			if err := h.db.Write(b, h.wo); err != nil {
  2205  				atomic.StoreUint32(&done, 1)
  2206  				t.Fatalf("WRITER #%d db.Write: %v", i, err)
  2207  			}
  2208  		}
  2209  	}()
  2210  	go func() {
  2211  		var i int
  2212  		defer func() {
  2213  			t.Logf("READER0 DONE #%d", i)
  2214  			atomic.StoreUint32(&done, 1)
  2215  			wg.Done()
  2216  		}()
  2217  		for ; time.Now().Before(until) && atomic.LoadUint32(&done) == 0; i++ {
  2218  			snap := h.getSnapshot()
  2219  			seq := snap.elem.seq
  2220  			if seq == 0 {
  2221  				snap.Release()
  2222  				continue
  2223  			}
  2224  			iter := snap.NewIterator(util.BytesPrefix([]byte{1}), nil)
  2225  			writei := int(seq/(n*2) - 1)
  2226  			var k int
  2227  			for ; iter.Next(); k++ {
  2228  				k1 := iter.Key()
  2229  				k2 := iter.Value()
  2230  				k1checksum0 := binary.LittleEndian.Uint32(k1[len(k1)-4:])
  2231  				k1checksum1 := util.NewCRC(k1[:len(k1)-4]).Value()
  2232  				if k1checksum0 != k1checksum1 {
  2233  					t.Fatalf("READER0 #%d.%d W#%d invalid K1 checksum: %#x != %#x", i, k, k1checksum0, k1checksum0)
  2234  				}
  2235  				k2checksum0 := binary.LittleEndian.Uint32(k2[len(k2)-4:])
  2236  				k2checksum1 := util.NewCRC(k2[:len(k2)-4]).Value()
  2237  				if k2checksum0 != k2checksum1 {
  2238  					t.Fatalf("READER0 #%d.%d W#%d invalid K2 checksum: %#x != %#x", i, k, k2checksum0, k2checksum1)
  2239  				}
  2240  				kwritei := int(binary.LittleEndian.Uint32(k2[len(k2)-8:]))
  2241  				if writei != kwritei {
  2242  					t.Fatalf("READER0 #%d.%d W#%d invalid write iteration num: %d", i, k, writei, kwritei)
  2243  				}
  2244  				if _, err := snap.Get(k2, nil); err != nil {
  2245  					t.Fatalf("READER0 #%d.%d W#%d snap.Get: %v\nk1: %x\n -> k2: %x", i, k, writei, err, k1, k2)
  2246  				}
  2247  			}
  2248  			if err := iter.Error(); err != nil {
  2249  				t.Fatalf("READER0 #%d.%d W#%d snap.Iterator: %v", i, k, writei, err)
  2250  			}
  2251  			iter.Release()
  2252  			snap.Release()
  2253  			if k > 0 && k != n {
  2254  				t.Fatalf("READER0 #%d W#%d short read, got=%d want=%d", i, writei, k, n)
  2255  			}
  2256  		}
  2257  	}()
  2258  	go func() {
  2259  		var i int
  2260  		defer func() {
  2261  			t.Logf("READER1 DONE #%d", i)
  2262  			atomic.StoreUint32(&done, 1)
  2263  			wg.Done()
  2264  		}()
  2265  		for ; time.Now().Before(until) && atomic.LoadUint32(&done) == 0; i++ {
  2266  			iter := h.db.NewIterator(nil, nil)
  2267  			seq := iter.(*dbIter).seq
  2268  			if seq == 0 {
  2269  				iter.Release()
  2270  				continue
  2271  			}
  2272  			writei := int(seq/(n*2) - 1)
  2273  			var k int
  2274  			for ok := iter.Last(); ok; ok = iter.Prev() {
  2275  				k++
  2276  			}
  2277  			if err := iter.Error(); err != nil {
  2278  				t.Fatalf("READER1 #%d.%d W#%d db.Iterator: %v", i, k, writei, err)
  2279  			}
  2280  			iter.Release()
  2281  			if m := (writei+1)*n + n; k != m {
  2282  				t.Fatalf("READER1 #%d W#%d short read, got=%d want=%d", i, writei, k, m)
  2283  			}
  2284  		}
  2285  	}()
  2286  
  2287  	wg.Wait()
  2288  }
  2289  
  2290  func TestDB_TransientError(t *testing.T) {
  2291  	h := newDbHarnessWopt(t, &opt.Options{
  2292  		DisableLargeBatchTransaction: true,
  2293  		WriteBuffer:                  128 * opt.KiB,
  2294  		OpenFilesCacheCapacity:       3,
  2295  		DisableCompactionBackoff:     true,
  2296  	})
  2297  	defer h.close()
  2298  
  2299  	const (
  2300  		nSnap = 20
  2301  		nKey  = 10000
  2302  	)
  2303  
  2304  	var (
  2305  		snaps [nSnap]*Snapshot
  2306  		b     = &Batch{}
  2307  	)
  2308  	for i := range snaps {
  2309  		vtail := fmt.Sprintf("VAL%030d", i)
  2310  		b.Reset()
  2311  		for k := 0; k < nKey; k++ {
  2312  			key := fmt.Sprintf("KEY%8d", k)
  2313  			b.Put([]byte(key), []byte(key+vtail))
  2314  		}
  2315  		h.stor.EmulateError(testutil.ModeOpen|testutil.ModeRead, storage.TypeTable, errors.New("table transient read error"))
  2316  		if err := h.db.Write(b, nil); err != nil {
  2317  			t.Logf("WRITE #%d error: %v", i, err)
  2318  			h.stor.EmulateError(testutil.ModeOpen|testutil.ModeRead, storage.TypeTable, nil)
  2319  			for {
  2320  				if err := h.db.Write(b, nil); err == nil {
  2321  					break
  2322  				} else if errors.IsCorrupted(err) {
  2323  					t.Fatalf("WRITE #%d corrupted: %v", i, err)
  2324  				}
  2325  			}
  2326  		}
  2327  
  2328  		snaps[i] = h.db.newSnapshot()
  2329  		b.Reset()
  2330  		for k := 0; k < nKey; k++ {
  2331  			key := fmt.Sprintf("KEY%8d", k)
  2332  			b.Delete([]byte(key))
  2333  		}
  2334  		h.stor.EmulateError(testutil.ModeOpen|testutil.ModeRead, storage.TypeTable, errors.New("table transient read error"))
  2335  		if err := h.db.Write(b, nil); err != nil {
  2336  			t.Logf("WRITE #%d  error: %v", i, err)
  2337  			h.stor.EmulateError(testutil.ModeOpen|testutil.ModeRead, storage.TypeTable, nil)
  2338  			for {
  2339  				if err := h.db.Write(b, nil); err == nil {
  2340  					break
  2341  				} else if errors.IsCorrupted(err) {
  2342  					t.Fatalf("WRITE #%d corrupted: %v", i, err)
  2343  				}
  2344  			}
  2345  		}
  2346  	}
  2347  	h.stor.EmulateError(testutil.ModeOpen|testutil.ModeRead, storage.TypeTable, nil)
  2348  
  2349  	runtime.GOMAXPROCS(runtime.NumCPU())
  2350  
  2351  	rnd := rand.New(rand.NewSource(0xecafdaed))
  2352  	wg := &sync.WaitGroup{}
  2353  	for i, snap := range snaps {
  2354  		wg.Add(2)
  2355  
  2356  		go func(i int, snap *Snapshot, sk []int) {
  2357  			defer wg.Done()
  2358  
  2359  			vtail := fmt.Sprintf("VAL%030d", i)
  2360  			for _, k := range sk {
  2361  				key := fmt.Sprintf("KEY%8d", k)
  2362  				xvalue, err := snap.Get([]byte(key), nil)
  2363  				if err != nil {
  2364  					t.Fatalf("READER_GET #%d SEQ=%d K%d error: %v", i, snap.elem.seq, k, err)
  2365  				}
  2366  				value := key + vtail
  2367  				if !bytes.Equal([]byte(value), xvalue) {
  2368  					t.Fatalf("READER_GET #%d SEQ=%d K%d invalid value: want %q, got %q", i, snap.elem.seq, k, value, xvalue)
  2369  				}
  2370  			}
  2371  		}(i, snap, rnd.Perm(nKey))
  2372  
  2373  		go func(i int, snap *Snapshot) {
  2374  			defer wg.Done()
  2375  
  2376  			vtail := fmt.Sprintf("VAL%030d", i)
  2377  			iter := snap.NewIterator(nil, nil)
  2378  			defer iter.Release()
  2379  			for k := 0; k < nKey; k++ {
  2380  				if !iter.Next() {
  2381  					if err := iter.Error(); err != nil {
  2382  						t.Fatalf("READER_ITER #%d K%d error: %v", i, k, err)
  2383  					} else {
  2384  						t.Fatalf("READER_ITER #%d K%d eoi", i, k)
  2385  					}
  2386  				}
  2387  				key := fmt.Sprintf("KEY%8d", k)
  2388  				xkey := iter.Key()
  2389  				if !bytes.Equal([]byte(key), xkey) {
  2390  					t.Fatalf("READER_ITER #%d K%d invalid key: want %q, got %q", i, k, key, xkey)
  2391  				}
  2392  				value := key + vtail
  2393  				xvalue := iter.Value()
  2394  				if !bytes.Equal([]byte(value), xvalue) {
  2395  					t.Fatalf("READER_ITER #%d K%d invalid value: want %q, got %q", i, k, value, xvalue)
  2396  				}
  2397  			}
  2398  		}(i, snap)
  2399  	}
  2400  
  2401  	wg.Wait()
  2402  }
  2403  
  2404  func TestDB_UkeyShouldntHopAcrossTable(t *testing.T) {
  2405  	h := newDbHarnessWopt(t, &opt.Options{
  2406  		DisableLargeBatchTransaction: true,
  2407  		WriteBuffer:                  112 * opt.KiB,
  2408  		CompactionTableSize:          90 * opt.KiB,
  2409  		CompactionExpandLimitFactor:  1,
  2410  	})
  2411  	defer h.close()
  2412  
  2413  	const (
  2414  		nSnap = 190
  2415  		nKey  = 140
  2416  	)
  2417  
  2418  	var (
  2419  		snaps [nSnap]*Snapshot
  2420  		b     = &Batch{}
  2421  	)
  2422  	for i := range snaps {
  2423  		vtail := fmt.Sprintf("VAL%030d", i)
  2424  		b.Reset()
  2425  		for k := 0; k < nKey; k++ {
  2426  			key := fmt.Sprintf("KEY%08d", k)
  2427  			b.Put([]byte(key), []byte(key+vtail))
  2428  		}
  2429  		if err := h.db.Write(b, nil); err != nil {
  2430  			t.Fatalf("WRITE #%d error: %v", i, err)
  2431  		}
  2432  
  2433  		snaps[i] = h.db.newSnapshot()
  2434  		b.Reset()
  2435  		for k := 0; k < nKey; k++ {
  2436  			key := fmt.Sprintf("KEY%08d", k)
  2437  			b.Delete([]byte(key))
  2438  		}
  2439  		if err := h.db.Write(b, nil); err != nil {
  2440  			t.Fatalf("WRITE #%d  error: %v", i, err)
  2441  		}
  2442  	}
  2443  
  2444  	h.compactMem()
  2445  
  2446  	h.waitCompaction()
  2447  	for level, tables := range h.db.s.stVersion.levels {
  2448  		for _, table := range tables {
  2449  			t.Logf("L%d@%d %q:%q", level, table.fd.Num, table.imin, table.imax)
  2450  		}
  2451  	}
  2452  
  2453  	h.compactRangeAt(0, "", "")
  2454  	h.waitCompaction()
  2455  	for level, tables := range h.db.s.stVersion.levels {
  2456  		for _, table := range tables {
  2457  			t.Logf("L%d@%d %q:%q", level, table.fd.Num, table.imin, table.imax)
  2458  		}
  2459  	}
  2460  	h.compactRangeAt(1, "", "")
  2461  	h.waitCompaction()
  2462  	for level, tables := range h.db.s.stVersion.levels {
  2463  		for _, table := range tables {
  2464  			t.Logf("L%d@%d %q:%q", level, table.fd.Num, table.imin, table.imax)
  2465  		}
  2466  	}
  2467  	runtime.GOMAXPROCS(runtime.NumCPU())
  2468  
  2469  	wg := &sync.WaitGroup{}
  2470  	for i, snap := range snaps {
  2471  		wg.Add(1)
  2472  
  2473  		go func(i int, snap *Snapshot) {
  2474  			defer wg.Done()
  2475  
  2476  			vtail := fmt.Sprintf("VAL%030d", i)
  2477  			for k := 0; k < nKey; k++ {
  2478  				key := fmt.Sprintf("KEY%08d", k)
  2479  				xvalue, err := snap.Get([]byte(key), nil)
  2480  				if err != nil {
  2481  					t.Fatalf("READER_GET #%d SEQ=%d K%d error: %v", i, snap.elem.seq, k, err)
  2482  				}
  2483  				value := key + vtail
  2484  				if !bytes.Equal([]byte(value), xvalue) {
  2485  					t.Fatalf("READER_GET #%d SEQ=%d K%d invalid value: want %q, got %q", i, snap.elem.seq, k, value, xvalue)
  2486  				}
  2487  			}
  2488  		}(i, snap)
  2489  	}
  2490  
  2491  	wg.Wait()
  2492  }
  2493  
  2494  func TestDB_TableCompactionBuilder(t *testing.T) {
  2495  	gomega.RegisterTestingT(t)
  2496  	stor := testutil.NewStorage()
  2497  	stor.OnLog(testingLogger(t))
  2498  	stor.OnClose(testingPreserveOnFailed(t))
  2499  	defer stor.Close()
  2500  
  2501  	const nSeq = 99
  2502  
  2503  	o := &opt.Options{
  2504  		DisableLargeBatchTransaction: true,
  2505  		WriteBuffer:                  112 * opt.KiB,
  2506  		CompactionTableSize:          43 * opt.KiB,
  2507  		CompactionExpandLimitFactor:  1,
  2508  		CompactionGPOverlapsFactor:   1,
  2509  		DisableBlockCache:            true,
  2510  	}
  2511  	s, err := newSession(stor, o)
  2512  	if err != nil {
  2513  		t.Fatal(err)
  2514  	}
  2515  	if err := s.create(); err != nil {
  2516  		t.Fatal(err)
  2517  	}
  2518  	defer s.close()
  2519  	var (
  2520  		seq        uint64
  2521  		targetSize = 5 * o.CompactionTableSize
  2522  		value      = bytes.Repeat([]byte{'0'}, 100)
  2523  	)
  2524  	for i := 0; i < 2; i++ {
  2525  		tw, err := s.tops.create()
  2526  		if err != nil {
  2527  			t.Fatal(err)
  2528  		}
  2529  		for k := 0; tw.tw.BytesLen() < targetSize; k++ {
  2530  			key := []byte(fmt.Sprintf("%09d", k))
  2531  			seq += nSeq - 1
  2532  			for x := uint64(0); x < nSeq; x++ {
  2533  				if err := tw.append(makeInternalKey(nil, key, seq-x, keyTypeVal), value); err != nil {
  2534  					t.Fatal(err)
  2535  				}
  2536  			}
  2537  		}
  2538  		tf, err := tw.finish()
  2539  		if err != nil {
  2540  			t.Fatal(err)
  2541  		}
  2542  		rec := &sessionRecord{}
  2543  		rec.addTableFile(i, tf)
  2544  		if err := s.commit(rec); err != nil {
  2545  			t.Fatal(err)
  2546  		}
  2547  	}
  2548  
  2549  	// Build grandparent.
  2550  	v := s.version()
  2551  	c := newCompaction(s, v, 1, append(tFiles{}, v.levels[1]...))
  2552  	rec := &sessionRecord{}
  2553  	b := &tableCompactionBuilder{
  2554  		s:         s,
  2555  		c:         c,
  2556  		rec:       rec,
  2557  		stat1:     new(cStatStaging),
  2558  		minSeq:    0,
  2559  		strict:    true,
  2560  		tableSize: o.CompactionTableSize/3 + 961,
  2561  	}
  2562  	if err := b.run(new(compactionTransactCounter)); err != nil {
  2563  		t.Fatal(err)
  2564  	}
  2565  	for _, t := range c.levels[0] {
  2566  		rec.delTable(c.sourceLevel, t.fd.Num)
  2567  	}
  2568  	if err := s.commit(rec); err != nil {
  2569  		t.Fatal(err)
  2570  	}
  2571  	c.release()
  2572  
  2573  	// Build level-1.
  2574  	v = s.version()
  2575  	c = newCompaction(s, v, 0, append(tFiles{}, v.levels[0]...))
  2576  	rec = &sessionRecord{}
  2577  	b = &tableCompactionBuilder{
  2578  		s:         s,
  2579  		c:         c,
  2580  		rec:       rec,
  2581  		stat1:     new(cStatStaging),
  2582  		minSeq:    0,
  2583  		strict:    true,
  2584  		tableSize: o.CompactionTableSize,
  2585  	}
  2586  	if err := b.run(new(compactionTransactCounter)); err != nil {
  2587  		t.Fatal(err)
  2588  	}
  2589  	for _, t := range c.levels[0] {
  2590  		rec.delTable(c.sourceLevel, t.fd.Num)
  2591  	}
  2592  	// Move grandparent to level-3
  2593  	for _, t := range v.levels[2] {
  2594  		rec.delTable(2, t.fd.Num)
  2595  		rec.addTableFile(3, t)
  2596  	}
  2597  	if err := s.commit(rec); err != nil {
  2598  		t.Fatal(err)
  2599  	}
  2600  	c.release()
  2601  
  2602  	v = s.version()
  2603  	for level, want := range []bool{false, true, false, true} {
  2604  		got := len(v.levels[level]) > 0
  2605  		if want != got {
  2606  			t.Fatalf("invalid level-%d tables len: want %v, got %v", level, want, got)
  2607  		}
  2608  	}
  2609  	for i, f := range v.levels[1][:len(v.levels[1])-1] {
  2610  		nf := v.levels[1][i+1]
  2611  		if bytes.Equal(f.imax.ukey(), nf.imin.ukey()) {
  2612  			t.Fatalf("KEY %q hop across table %d .. %d", f.imax.ukey(), f.fd.Num, nf.fd.Num)
  2613  		}
  2614  	}
  2615  	v.release()
  2616  
  2617  	// Compaction with transient error.
  2618  	v = s.version()
  2619  	c = newCompaction(s, v, 1, append(tFiles{}, v.levels[1]...))
  2620  	rec = &sessionRecord{}
  2621  	b = &tableCompactionBuilder{
  2622  		s:         s,
  2623  		c:         c,
  2624  		rec:       rec,
  2625  		stat1:     new(cStatStaging),
  2626  		minSeq:    0,
  2627  		strict:    true,
  2628  		tableSize: o.CompactionTableSize,
  2629  	}
  2630  	stor.EmulateErrorOnce(testutil.ModeSync, storage.TypeTable, errors.New("table sync error (once)"))
  2631  	stor.EmulateRandomError(testutil.ModeRead|testutil.ModeWrite, storage.TypeTable, 0.01, errors.New("table random IO error"))
  2632  	for {
  2633  		if err := b.run(new(compactionTransactCounter)); err != nil {
  2634  			t.Logf("(expected) b.run: %v", err)
  2635  		} else {
  2636  			break
  2637  		}
  2638  	}
  2639  	if err := s.commit(rec); err != nil {
  2640  		t.Fatal(err)
  2641  	}
  2642  	c.release()
  2643  
  2644  	stor.EmulateErrorOnce(testutil.ModeSync, storage.TypeTable, nil)
  2645  	stor.EmulateRandomError(testutil.ModeRead|testutil.ModeWrite, storage.TypeTable, 0, nil)
  2646  
  2647  	v = s.version()
  2648  	if len(v.levels[1]) != len(v.levels[2]) {
  2649  		t.Fatalf("invalid tables length, want %d, got %d", len(v.levels[1]), len(v.levels[2]))
  2650  	}
  2651  	for i, f0 := range v.levels[1] {
  2652  		f1 := v.levels[2][i]
  2653  		iter0 := s.tops.newIterator(f0, nil, nil)
  2654  		iter1 := s.tops.newIterator(f1, nil, nil)
  2655  		for j := 0; true; j++ {
  2656  			next0 := iter0.Next()
  2657  			next1 := iter1.Next()
  2658  			if next0 != next1 {
  2659  				t.Fatalf("#%d.%d invalid eoi: want %v, got %v", i, j, next0, next1)
  2660  			}
  2661  			key0 := iter0.Key()
  2662  			key1 := iter1.Key()
  2663  			if !bytes.Equal(key0, key1) {
  2664  				t.Fatalf("#%d.%d invalid key: want %q, got %q", i, j, key0, key1)
  2665  			}
  2666  			if next0 == false {
  2667  				break
  2668  			}
  2669  		}
  2670  		iter0.Release()
  2671  		iter1.Release()
  2672  	}
  2673  	v.release()
  2674  }
  2675  
  2676  func testDB_IterTriggeredCompaction(t *testing.T, limitDiv int) {
  2677  	const (
  2678  		vSize = 200 * opt.KiB
  2679  		tSize = 100 * opt.MiB
  2680  		mIter = 100
  2681  		n     = tSize / vSize
  2682  	)
  2683  
  2684  	h := newDbHarnessWopt(t, &opt.Options{
  2685  		DisableLargeBatchTransaction: true,
  2686  		Compression:                  opt.NoCompression,
  2687  		DisableBlockCache:            true,
  2688  	})
  2689  	defer h.close()
  2690  
  2691  	h.db.memdbMaxLevel = 2
  2692  
  2693  	key := func(x int) string {
  2694  		return fmt.Sprintf("v%06d", x)
  2695  	}
  2696  
  2697  	// Fill.
  2698  	value := strings.Repeat("x", vSize)
  2699  	for i := 0; i < n; i++ {
  2700  		h.put(key(i), value)
  2701  	}
  2702  	h.compactMem()
  2703  
  2704  	// Delete all.
  2705  	for i := 0; i < n; i++ {
  2706  		h.delete(key(i))
  2707  	}
  2708  	h.compactMem()
  2709  
  2710  	var (
  2711  		limit = n / limitDiv
  2712  
  2713  		startKey = key(0)
  2714  		limitKey = key(limit)
  2715  		maxKey   = key(n)
  2716  		slice    = &util.Range{Limit: []byte(limitKey)}
  2717  
  2718  		initialSize0 = h.sizeOf(startKey, limitKey)
  2719  		initialSize1 = h.sizeOf(limitKey, maxKey)
  2720  	)
  2721  
  2722  	t.Logf("inital size %s [rest %s]", shortenb(int(initialSize0)), shortenb(int(initialSize1)))
  2723  
  2724  	for r := 0; true; r++ {
  2725  		if r >= mIter {
  2726  			t.Fatal("taking too long to compact")
  2727  		}
  2728  
  2729  		// Iterates.
  2730  		iter := h.db.NewIterator(slice, h.ro)
  2731  		for iter.Next() {
  2732  		}
  2733  		if err := iter.Error(); err != nil {
  2734  			t.Fatalf("Iter err: %v", err)
  2735  		}
  2736  		iter.Release()
  2737  
  2738  		// Wait compaction.
  2739  		h.waitCompaction()
  2740  
  2741  		// Check size.
  2742  		size0 := h.sizeOf(startKey, limitKey)
  2743  		size1 := h.sizeOf(limitKey, maxKey)
  2744  		t.Logf("#%03d size %s [rest %s]", r, shortenb(int(size0)), shortenb(int(size1)))
  2745  		if size0 < initialSize0/10 {
  2746  			break
  2747  		}
  2748  	}
  2749  
  2750  	if initialSize1 > 0 {
  2751  		h.sizeAssert(limitKey, maxKey, initialSize1/4-opt.MiB, initialSize1+opt.MiB)
  2752  	}
  2753  }
  2754  
  2755  func TestDB_IterTriggeredCompaction(t *testing.T) {
  2756  	testDB_IterTriggeredCompaction(t, 1)
  2757  }
  2758  
  2759  func TestDB_IterTriggeredCompactionHalf(t *testing.T) {
  2760  	testDB_IterTriggeredCompaction(t, 2)
  2761  }
  2762  
  2763  func TestDB_ReadOnly(t *testing.T) {
  2764  	h := newDbHarness(t)
  2765  	defer h.close()
  2766  
  2767  	h.put("foo", "v1")
  2768  	h.put("bar", "v2")
  2769  	h.compactMem()
  2770  
  2771  	h.put("xfoo", "v1")
  2772  	h.put("xbar", "v2")
  2773  
  2774  	t.Log("Trigger read-only")
  2775  	if err := h.db.SetReadOnly(); err != nil {
  2776  		h.close()
  2777  		t.Fatalf("SetReadOnly error: %v", err)
  2778  	}
  2779  
  2780  	mode := testutil.ModeCreate | testutil.ModeRemove | testutil.ModeRename | testutil.ModeWrite | testutil.ModeSync
  2781  	h.stor.EmulateError(mode, storage.TypeAll, errors.New("read-only DB shouldn't writes"))
  2782  
  2783  	ro := func(key, value, wantValue string) {
  2784  		if err := h.db.Put([]byte(key), []byte(value), h.wo); err != ErrReadOnly {
  2785  			t.Fatalf("unexpected error: %v", err)
  2786  		}
  2787  		h.getVal(key, wantValue)
  2788  	}
  2789  
  2790  	ro("foo", "vx", "v1")
  2791  
  2792  	h.o.ReadOnly = true
  2793  	h.reopenDB()
  2794  
  2795  	ro("foo", "vx", "v1")
  2796  	ro("bar", "vx", "v2")
  2797  	h.assertNumKeys(4)
  2798  }
  2799  
  2800  func TestDB_BulkInsertDelete(t *testing.T) {
  2801  	h := newDbHarnessWopt(t, &opt.Options{
  2802  		DisableLargeBatchTransaction: true,
  2803  		Compression:                  opt.NoCompression,
  2804  		CompactionTableSize:          128 * opt.KiB,
  2805  		CompactionTotalSize:          1 * opt.MiB,
  2806  		WriteBuffer:                  256 * opt.KiB,
  2807  	})
  2808  	defer h.close()
  2809  
  2810  	const R = 100
  2811  	const N = 2500
  2812  	key := make([]byte, 4)
  2813  	value := make([]byte, 256)
  2814  	for i := 0; i < R; i++ {
  2815  		offset := N * i
  2816  		for j := 0; j < N; j++ {
  2817  			binary.BigEndian.PutUint32(key, uint32(offset+j))
  2818  			h.db.Put(key, value, nil)
  2819  		}
  2820  		for j := 0; j < N; j++ {
  2821  			binary.BigEndian.PutUint32(key, uint32(offset+j))
  2822  			h.db.Delete(key, nil)
  2823  		}
  2824  	}
  2825  
  2826  	if tot := h.totalTables(); tot > 10 {
  2827  		t.Fatalf("too many uncompacted tables: %d (%s)", tot, h.getTablesPerLevel())
  2828  	}
  2829  }