github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bitree_test.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package bitree
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"os"
    21  	"sync"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/stretchr/testify/require"
    26  	"github.com/zuoyebang/bitalosdb/bitable"
    27  	"github.com/zuoyebang/bitalosdb/bitpage"
    28  	"github.com/zuoyebang/bitalosdb/bitree/bdb"
    29  	"github.com/zuoyebang/bitalosdb/internal/base"
    30  	"github.com/zuoyebang/bitalosdb/internal/bitask"
    31  	"github.com/zuoyebang/bitalosdb/internal/consts"
    32  	"github.com/zuoyebang/bitalosdb/internal/hash"
    33  	"github.com/zuoyebang/bitalosdb/internal/options"
    34  	"github.com/zuoyebang/bitalosdb/internal/sortedkv"
    35  	"github.com/zuoyebang/bitalosdb/internal/utils"
    36  )
    37  
    38  const testDir = "test"
    39  const testBitreeIndex = 1
    40  
    41  var testBtree *Bitree
    42  
    43  type testBitpageTask struct {
    44  	task   *bitask.BitpageTask
    45  	taskWg sync.WaitGroup
    46  }
    47  
    48  var bpageTask *testBitpageTask
    49  
    50  var (
    51  	testBithashSize  = 128 << 20
    52  	testIsUseBitable = false
    53  )
    54  
    55  func makeTestKey(i int) []byte {
    56  	return []byte(fmt.Sprintf("bitree_key_%d", i))
    57  }
    58  
    59  func testMakeSortedKV(num int, seqNum uint64, vsize int) sortedkv.SortedKVList {
    60  	return sortedkv.MakeSlotSortedKVList(0, num, seqNum, vsize, uint16(testBitreeIndex))
    61  }
    62  
    63  func testMakeSortedSlotKey(n int) []byte {
    64  	return sortedkv.MakeSortedSlotKey(n, uint16(testBitreeIndex))
    65  }
    66  
    67  func testNewBitreePages(t *Bitree) error {
    68  	err := t.bdb.Update(func(tx *bdb.Tx) error {
    69  		bkt := tx.Bucket(consts.BdbBucketName)
    70  		if bkt == nil {
    71  			return bdb.ErrBucketNotFound
    72  		}
    73  		for j := 1; j < 10; j++ {
    74  			key := makeTestKey(j)
    75  			pn, err := t.bpage.NewPage()
    76  			if err != nil {
    77  				return err
    78  			}
    79  			if err = bkt.Put(key, pn.ToByte()); err != nil {
    80  				return err
    81  			}
    82  		}
    83  		return nil
    84  	})
    85  	return err
    86  }
    87  
    88  func resetTestOptsVal() {
    89  	testBithashSize = 128 << 20
    90  	testIsUseBitable = false
    91  }
    92  
    93  func testOpenBitree() (*Bitree, *options.BitreeOptions) {
    94  	defer func() {
    95  		resetTestOptsVal()
    96  	}()
    97  	optsPool := options.InitTestDefaultsOptionsPool()
    98  	return testOpenBitree1(optsPool)
    99  }
   100  
   101  func testOpenBitree1(optsPool *options.OptionsPool) (*Bitree, *options.BitreeOptions) {
   102  	bpageTask = &testBitpageTask{}
   103  	bpageTask.task = bitask.NewBitpageTask(&bitask.BitpageTaskOptions{
   104  		Size:    100,
   105  		DbState: optsPool.DbState,
   106  		Logger:  optsPool.BaseOptions.Logger,
   107  		DoFunc:  testDoBitpageTask,
   108  		TaskWg:  &bpageTask.taskWg,
   109  	})
   110  	optsPool.BaseOptions.BitpageTaskPushFunc = bpageTask.task.PushTask
   111  	optsPool.BaseOptions.UseBitable = testIsUseBitable
   112  	optsPool.BithashOptions.TableMaxSize = testBithashSize
   113  	optsPool.BaseOptions.KeyPrefixDeleteFunc = options.TestKeyPrefixDeleteFunc
   114  	bitreeOpts := optsPool.CloneBitreeOptions()
   115  	bitreeOpts.Index = testBitreeIndex
   116  
   117  	var err error
   118  	testBtree, err = NewBitree(testDir, bitreeOpts)
   119  	if err != nil {
   120  		panic(err)
   121  	}
   122  	return testBtree, bitreeOpts
   123  }
   124  
   125  func testDoBitpageTask(task *bitask.BitpageTaskData) {
   126  	testBtree.DoBitpageTask(task)
   127  }
   128  
   129  func testBitreeClose(bt *Bitree) error {
   130  	bpageTask.task.Close()
   131  	bpageTask.taskWg.Wait()
   132  	err := bt.Close()
   133  	bt.opts.DeleteFilePacer.Close()
   134  	return err
   135  }
   136  
   137  func TestBitree_CompactToBitable(t *testing.T) {
   138  	defer os.RemoveAll(testDir)
   139  	os.RemoveAll(testDir)
   140  	testBithashSize = 10 << 20
   141  	testIsUseBitable = true
   142  	btree, _ := testOpenBitree()
   143  	defer func() {
   144  		require.NoError(t, testBitreeClose(btree))
   145  	}()
   146  
   147  	require.NotEqual(t, (*bitable.Bitable)(nil), btree.btable)
   148  
   149  	err := btree.bdb.Update(func(tx *bdb.Tx) error {
   150  		bkt := tx.Bucket(consts.BdbBucketName)
   151  		if bkt == nil {
   152  			return bdb.ErrBucketNotFound
   153  		}
   154  		for i := 1; i < 10; i++ {
   155  			key := makeTestKey(i)
   156  			pn, err := btree.bpage.NewPage()
   157  			require.NoError(t, err)
   158  			require.NoError(t, bkt.Put(key, pn.ToByte()))
   159  		}
   160  		return nil
   161  	})
   162  	btree.txPool.Update()
   163  	require.NoError(t, err)
   164  
   165  	bw, err := btree.NewBitreeWriter()
   166  	require.NoError(t, err)
   167  	largeValue := utils.FuncRandBytes(520)
   168  	smallValue := utils.FuncRandBytes(500)
   169  	keyCount := 1000
   170  	seqNum := uint64(0)
   171  	kvList := testMakeSortedKV(keyCount, seqNum, 10)
   172  	seqNum += uint64(keyCount)
   173  
   174  	for i := 0; i < keyCount; i++ {
   175  		if i%2 == 0 {
   176  			kvList[i].Value = smallValue
   177  		} else {
   178  			kvList[i].Value = largeValue
   179  		}
   180  		require.NoError(t, bw.Apply(*kvList[i].Key, kvList[i].Value))
   181  	}
   182  	require.NoError(t, bw.Finish())
   183  
   184  	time.Sleep(2 * time.Second)
   185  
   186  	readIter := func(it base.InternalIterator) {
   187  		i := 0
   188  		for k, v := it.First(); k != nil; k, v = it.Next() {
   189  			if base.InternalCompare(bytes.Compare, *kvList[i].Key, *k) != 0 {
   190  				t.Fatal("InternalCompare", i, k.String(), kvList[i].Key.String())
   191  			}
   192  			require.Equal(t, kvList[i].Value, v)
   193  			i++
   194  		}
   195  		require.Equal(t, keyCount, i)
   196  	}
   197  
   198  	btreeIter := btree.newBitreeIter(nil)
   199  	readIter(btreeIter)
   200  	require.NoError(t, btreeIter.Close())
   201  
   202  	require.Equal(t, 10, btree.bpage.GetPageCount())
   203  	pn := btree.CompactBitreeToBitable()
   204  
   205  	bdbIter := btree.NewBdbIter()
   206  	bdbKey, bdbValue := bdbIter.First()
   207  	require.Equal(t, consts.BdbMaxKey, bdbKey.UserKey)
   208  	require.Equal(t, uint32(pn), utils.BytesToUint32(bdbValue))
   209  	bdbKey, _ = bdbIter.Next()
   210  	require.Equal(t, (*base.InternalKey)(nil), bdbKey)
   211  	require.NoError(t, bdbIter.Close())
   212  
   213  	isFree := btree.bpage.CheckFreePages(pn)
   214  	require.Equal(t, true, isFree)
   215  
   216  	_ = btree.bdb.Update(func(tx *bdb.Tx) error { return nil })
   217  	btree.txPool.Update()
   218  	_ = btree.bdb.Update(func(tx *bdb.Tx) error { return nil })
   219  
   220  	time.Sleep(2 * time.Second)
   221  	require.Equal(t, 1, btree.bpage.GetPageCount())
   222  
   223  	btableIter := btree.newBitableIter(nil)
   224  	readIter(btableIter)
   225  	require.NoError(t, btableIter.Close())
   226  
   227  	btreeIter = btree.newBitreeIter(nil)
   228  	ik, _ := btreeIter.First()
   229  	require.Equal(t, (*base.InternalKey)(nil), ik)
   230  	require.NoError(t, btreeIter.Close())
   231  }
   232  
   233  func TestBitree_Checkpoint_Flush(t *testing.T) {
   234  	ckDir := testDir + "_ck"
   235  	os.RemoveAll(testDir)
   236  	os.RemoveAll(ckDir)
   237  
   238  	require.NoError(t, os.MkdirAll(ckDir, 0755))
   239  	btree, _ := testOpenBitree()
   240  	defer func() {
   241  		require.NoError(t, testBitreeClose(btree))
   242  		require.NoError(t, os.RemoveAll(testDir))
   243  		require.NoError(t, os.RemoveAll(ckDir))
   244  	}()
   245  
   246  	require.NoError(t, testNewBitreePages(btree))
   247  
   248  	keyCount := 200
   249  	seqNum := uint64(0)
   250  	kvList := testMakeSortedKV(keyCount, seqNum, 200)
   251  	seqNum += uint64(keyCount)
   252  
   253  	writeData := func(start int) {
   254  		bw, err := btree.NewBitreeWriter()
   255  		require.NoError(t, err)
   256  		for i := start; i < start+100; i++ {
   257  			require.NoError(t, bw.Apply(*kvList[i].Key, kvList[i].Value))
   258  		}
   259  		require.NoError(t, bw.Finish())
   260  	}
   261  
   262  	writeData(0)
   263  	time.Sleep(1 * time.Second)
   264  	require.Equal(t, uint64(0), btree.dbState.GetBitpageFlushCount())
   265  	require.NoError(t, btree.Checkpoint(btree.opts.FS, ckDir, testDir))
   266  
   267  	writeData(100)
   268  	time.Sleep(1 * time.Second)
   269  	require.Equal(t, uint64(1), btree.dbState.GetBitpageFlushCount())
   270  
   271  	for i := 0; i < keyCount; i++ {
   272  		k := kvList[i].Key.UserKey
   273  		v, exist, vcloser := btree.Get(k, hash.Crc32(k))
   274  		require.Equal(t, true, exist)
   275  		require.Equal(t, kvList[i].Value, v)
   276  		vcloser()
   277  	}
   278  }
   279  
   280  func TestBitree_BitpageFlushState(t *testing.T) {
   281  	defer os.RemoveAll(testDir)
   282  	os.RemoveAll(testDir)
   283  
   284  	btree, _ := testOpenBitree()
   285  	require.NoError(t, testNewBitreePages(btree))
   286  
   287  	keyCount := 100
   288  	seqNum := uint64(0)
   289  	kvList := testMakeSortedKV(keyCount, seqNum, 200)
   290  	seqNum += uint64(keyCount)
   291  
   292  	var pageNum bitpage.PageNum
   293  	bw, err := btree.NewBitreeWriter()
   294  	require.NoError(t, err)
   295  	for i := 0; i < keyCount; i++ {
   296  		pn, sentinel, closer := btree.FindKeyPageNum(kvList[i].Key.UserKey)
   297  		closer()
   298  		require.NotEqual(t, nilPageNum, pn)
   299  		require.NoError(t, bw.set(*kvList[i].Key, kvList[i].Value, pn, sentinel))
   300  		pageNum = pn
   301  	}
   302  	require.NoError(t, bw.Finish())
   303  
   304  	task := &bitask.BitpageTaskData{
   305  		Event:    bitask.BitpageEventFlush,
   306  		Pn:       uint32(pageNum),
   307  		Sentinel: nil,
   308  	}
   309  	err = btree.bpage.PageFlush(bitpage.PageNum(task.Pn), task.Sentinel, "")
   310  	require.Equal(t, bitpage.ErrPageFlushState, err)
   311  
   312  	require.NoError(t, testBitreeClose(btree))
   313  }
   314  
   315  func TestBitree_BitpageFlushDelPercent(t *testing.T) {
   316  	defer os.RemoveAll(testDir)
   317  	os.RemoveAll(testDir)
   318  
   319  	optsPool := options.InitTestDefaultsOptionsPool()
   320  	optsPool.BaseOptions.BitpageFlushSize = 40 << 10
   321  	btree, _ := testOpenBitree1(optsPool)
   322  	require.NoError(t, testNewBitreePages(btree))
   323  
   324  	keyCount := 1000
   325  	seqNum := uint64(0)
   326  	kvList := testMakeSortedKV(keyCount, seqNum, 500)
   327  	seqNum += uint64(keyCount)
   328  
   329  	var pageNum bitpage.PageNum
   330  	bw, err := btree.NewBitreeWriter()
   331  	require.NoError(t, err)
   332  	for i := 0; i < keyCount; i++ {
   333  		k := makeTestKey(i)
   334  		pn, sentinel, closer := btree.FindKeyPageNum(k)
   335  		closer()
   336  		require.NotEqual(t, nilPageNum, pn)
   337  		if i%2 == 0 || i > 700 {
   338  			kvList[i].Key.SetKind(base.InternalKeyKindDelete)
   339  		}
   340  		require.NoError(t, bw.set(*kvList[i].Key, kvList[i].Value, pn, sentinel))
   341  		pageNum = pn
   342  	}
   343  
   344  	delPercent := btree.bpage.GetPageDelPercent(pageNum)
   345  	if delPercent < 0.5 {
   346  		t.Fatal("delpercent err", delPercent)
   347  	}
   348  	require.NoError(t, bw.Finish())
   349  	time.Sleep(2 * time.Second)
   350  	require.Equal(t, uint64(1), btree.dbState.GetBitpageFlushCount())
   351  
   352  	for i := 0; i < keyCount; i++ {
   353  		k := kvList[i].Key.UserKey
   354  		v, exist, vcloser := btree.Get(k, hash.Crc32(k))
   355  		if i%2 == 0 || i > 700 {
   356  			require.Equal(t, false, exist)
   357  		} else {
   358  			require.Equal(t, true, exist)
   359  			require.Equal(t, kvList[i].Value, v)
   360  			vcloser()
   361  		}
   362  	}
   363  
   364  	require.NoError(t, testBitreeClose(btree))
   365  }
   366  
   367  func TestBitree_BitableFlushBatch(t *testing.T) {
   368  	defer os.RemoveAll(testDir)
   369  	os.RemoveAll(testDir)
   370  
   371  	testBithashSize = 10 << 20
   372  	testIsUseBitable = true
   373  	btree, _ := testOpenBitree()
   374  	defer func() {
   375  		require.NoError(t, testBitreeClose(btree))
   376  		require.NoError(t, os.RemoveAll(testDir))
   377  	}()
   378  
   379  	batch := btree.btable.NewFlushBatch(1 << 20)
   380  	require.Equal(t, true, batch.Empty())
   381  	batch.Set([]byte("123"), []byte("123"))
   382  	require.Equal(t, false, batch.Empty())
   383  	batch.Delete([]byte("123"))
   384  	require.Equal(t, false, batch.Empty())
   385  	batch.AllocFree()
   386  	require.NoError(t, batch.Close())
   387  }
   388  
   389  func TestBitree_IterRange(t *testing.T) {
   390  	defer os.RemoveAll(testDir)
   391  	os.RemoveAll(testDir)
   392  
   393  	btree, _ := testOpenBitree()
   394  	require.NoError(t, testNewBitreePages(btree))
   395  
   396  	largeValue := utils.FuncRandBytes(consts.KvSeparateSize + 200)
   397  	smallValue := utils.FuncRandBytes(consts.KvSeparateSize - 10)
   398  	keyCount := 100
   399  	seqNum := uint64(0)
   400  	kvList := testMakeSortedKV(keyCount, seqNum, 1)
   401  	seqNum += uint64(keyCount)
   402  
   403  	bw, err := btree.NewBitreeWriter()
   404  	require.NoError(t, err)
   405  	for i := 0; i < keyCount; i++ {
   406  		if i%3 == 0 {
   407  			kvList[i].Value = smallValue
   408  		} else if i%3 == 1 {
   409  			kvList[i].Value = largeValue
   410  		} else {
   411  			kvList[i].Key.SetKind(base.InternalKeyKindDelete)
   412  		}
   413  		kvList[i].Key.SetSeqNum(seqNum)
   414  		seqNum++
   415  		require.NoError(t, bw.Apply(*kvList[i].Key, kvList[i].Value))
   416  	}
   417  	require.NoError(t, bw.Finish())
   418  	time.Sleep(2 * time.Second)
   419  
   420  	rangeLoop := func(o *options.IterOptions, start int) int {
   421  		iter := btree.newBitreeIter(o)
   422  		i := start
   423  		count := 0
   424  		for ik, val := iter.First(); ik != nil; ik, val = iter.Next() {
   425  			require.Equal(t, 0, base.InternalCompare(bytes.Compare, *kvList[i].Key, *ik))
   426  			kind := ik.Kind()
   427  			if i%3 == 0 || i%3 == 1 {
   428  				require.Equal(t, base.InternalKeyKindSet, kind)
   429  				require.Equal(t, kvList[i].Value, val)
   430  			} else {
   431  				require.Equal(t, base.InternalKeyKindDelete, kind)
   432  				require.Equal(t, 0, len(val))
   433  			}
   434  			i++
   435  			count++
   436  		}
   437  		require.NoError(t, iter.Close())
   438  		return count
   439  	}
   440  
   441  	rangeReverseLoop := func(o *options.IterOptions, start int) int {
   442  		iter := btree.newBitreeIter(o)
   443  		i := start
   444  		count := 0
   445  		for ik, val := iter.Last(); ik != nil; ik, val = iter.Prev() {
   446  			require.Equal(t, 0, base.InternalCompare(bytes.Compare, *kvList[i].Key, *ik))
   447  			kind := ik.Kind()
   448  			if i%3 == 0 || i%3 == 1 {
   449  				require.Equal(t, base.InternalKeyKindSet, kind)
   450  				require.Equal(t, kvList[i].Value, val)
   451  			} else {
   452  				require.Equal(t, base.InternalKeyKindDelete, kind)
   453  				require.Equal(t, 0, len(val))
   454  			}
   455  			i--
   456  			count++
   457  		}
   458  		require.NoError(t, iter.Close())
   459  		return count
   460  	}
   461  
   462  	require.Equal(t, keyCount, rangeLoop(nil, 0))
   463  	require.Equal(t, keyCount, rangeReverseLoop(nil, keyCount-1))
   464  	ops := &options.IterOptions{
   465  		LowerBound: kvList[20].Key.UserKey,
   466  		UpperBound: kvList[50].Key.UserKey,
   467  	}
   468  	require.Equal(t, 30, rangeLoop(ops, 20))
   469  	require.Equal(t, 30, rangeReverseLoop(ops, 49))
   470  	ops = &options.IterOptions{
   471  		LowerBound: kvList[30].Key.UserKey,
   472  	}
   473  	require.Equal(t, 70, rangeLoop(ops, 30))
   474  	ops = &options.IterOptions{
   475  		UpperBound: kvList[50].Key.UserKey,
   476  	}
   477  	require.Equal(t, 50, rangeReverseLoop(ops, 49))
   478  
   479  	require.NoError(t, testBitreeClose(btree))
   480  }
   481  
   482  func TestBitree_IterSeek(t *testing.T) {
   483  	defer os.RemoveAll(testDir)
   484  	os.RemoveAll(testDir)
   485  
   486  	btree, _ := testOpenBitree()
   487  	require.NoError(t, testNewBitreePages(btree))
   488  
   489  	keyCount := 100
   490  	seqNum := uint64(0)
   491  	kvList := testMakeSortedKV(keyCount, seqNum, 520)
   492  	seqNum += uint64(keyCount)
   493  
   494  	bw, err := btree.NewBitreeWriter()
   495  	require.NoError(t, err)
   496  	for i := 0; i < keyCount; i++ {
   497  		if i >= 1 && i < 13 {
   498  			continue
   499  		}
   500  		require.NoError(t, bw.Apply(*kvList[i].Key, kvList[i].Value))
   501  	}
   502  	require.NoError(t, bw.Finish())
   503  	time.Sleep(2 * time.Second)
   504  
   505  	makeByte := func(pos, extra int) []byte {
   506  		return []byte(fmt.Sprintf("%s%d", string(kvList[pos].Key.UserKey), extra))
   507  	}
   508  
   509  	iterOp := func(it *BitreeIterator, op string, seek []byte, want int) {
   510  		var ik *base.InternalKey
   511  		var v []byte
   512  		switch op {
   513  		case "SeekGE":
   514  			ik, v = it.SeekGE(seek)
   515  		case "SeekLT":
   516  			ik, v = it.SeekLT(seek)
   517  		case "First":
   518  			ik, v = it.First()
   519  		case "Next":
   520  			ik, v = it.Next()
   521  		case "Last":
   522  			ik, v = it.Last()
   523  		case "Prev":
   524  			ik, v = it.Prev()
   525  		}
   526  		if want == -1 {
   527  			require.Equal(t, (*base.InternalKey)(nil), ik)
   528  		} else {
   529  			require.Equal(t, kvList[want].Key, ik)
   530  			require.Equal(t, kvList[want].Value, v)
   531  		}
   532  	}
   533  
   534  	iter := btree.newBitreeIter(nil)
   535  	iterOp(iter, "SeekGE", kvList[14].Key.UserKey, 14)
   536  	iterOp(iter, "SeekGE", makeByte(14, 1), 15)
   537  	iterOp(iter, "SeekGE", kvList[29].Key.UserKey, 29)
   538  	iterOp(iter, "SeekGE", makeByte(29, 0), 30)
   539  	iterOp(iter, "SeekGE", makeByte(49, 1), 50)
   540  	iterOp(iter, "SeekGE", kvList[99].Key.UserKey, 99)
   541  	iterOp(iter, "SeekGE", testMakeSortedSlotKey(990), -1)
   542  	require.NoError(t, iter.Close())
   543  
   544  	iter = btree.newBitreeIter(nil)
   545  	iterOp(iter, "SeekLT", kvList[14].Key.UserKey, 13)
   546  	iterOp(iter, "SeekLT", makeByte(14, 1), 14)
   547  	iterOp(iter, "SeekLT", kvList[30].Key.UserKey, 29)
   548  	iterOp(iter, "SeekLT", kvList[31].Key.UserKey, 30)
   549  	iterOp(iter, "SeekLT", testMakeSortedSlotKey(990), 99)
   550  	iterOp(iter, "SeekLT", kvList[0].Key.UserKey, -1)
   551  	require.NoError(t, iter.Close())
   552  
   553  	bw, err = btree.NewBitreeWriter()
   554  	require.NoError(t, err)
   555  	for i := 0; i < keyCount; i++ {
   556  		if i > 0 && i < 90 {
   557  			continue
   558  		}
   559  		kvList[i].Key.SetKind(base.InternalKeyKindDelete)
   560  		kvList[i].Key.SetSeqNum(seqNum)
   561  		kvList[i].Value = []byte(nil)
   562  		seqNum++
   563  		require.NoError(t, bw.Apply(*kvList[i].Key, kvList[i].Value))
   564  	}
   565  	require.NoError(t, bw.Finish())
   566  	time.Sleep(1 * time.Second)
   567  
   568  	iter = btree.newBitreeIter(nil)
   569  	iterOp(iter, "First", nil, 0)
   570  	iterOp(iter, "Next", nil, 13)
   571  	iterOp(iter, "SeekGE", testMakeSortedSlotKey(2), 13)
   572  	iterOp(iter, "Prev", nil, 0)
   573  	iterOp(iter, "Next", nil, 13)
   574  	iterOp(iter, "Last", nil, 99)
   575  	iterOp(iter, "Prev", nil, 98)
   576  	iterOp(iter, "SeekGE", kvList[89].Key.UserKey, 89)
   577  	iterOp(iter, "Prev", nil, 88)
   578  	iterOp(iter, "SeekLT", kvList[60].Key.UserKey, 59)
   579  	iterOp(iter, "Next", nil, 60)
   580  	iterOp(iter, "Prev", nil, 59)
   581  	require.NoError(t, iter.Close())
   582  
   583  	require.NoError(t, testBitreeClose(btree))
   584  }
   585  
   586  func TestBitree_IterCache(t *testing.T) {
   587  	defer os.RemoveAll(testDir)
   588  	os.RemoveAll(testDir)
   589  
   590  	optspool := options.InitDefaultsOptionsPool()
   591  	optspool.BaseOptions.BitpageFlushSize = 1 << 20
   592  	optspool.BaseOptions.UseBlockCompress = true
   593  	btree, _ := testOpenBitree1(optspool)
   594  	require.NoError(t, testNewBitreePages(btree))
   595  
   596  	keyCount := 10000
   597  	seqNum := uint64(0)
   598  	kvList := testMakeSortedKV(keyCount, seqNum, 100)
   599  	seqNum += uint64(keyCount)
   600  
   601  	bw, err := btree.NewBitreeWriter()
   602  	require.NoError(t, err)
   603  	for i := 0; i < keyCount; i++ {
   604  		kvList[i].Key.SetSeqNum(seqNum)
   605  		seqNum++
   606  		require.NoError(t, bw.Apply(*kvList[i].Key, kvList[i].Value))
   607  	}
   608  	require.NoError(t, bw.Finish())
   609  	time.Sleep(1 * time.Second)
   610  
   611  	rangeLoop := func(o *options.IterOptions) int {
   612  		iter := btree.newBitreeIter(o)
   613  		i := 0
   614  		for ik, val := iter.First(); ik != nil; ik, val = iter.Next() {
   615  			require.Equal(t, *kvList[i].Key, *ik)
   616  			require.Equal(t, kvList[i].Value, val)
   617  			i++
   618  		}
   619  		require.NoError(t, iter.Close())
   620  		return i
   621  	}
   622  
   623  	iterOpts := &options.IterOptions{DisableCache: true}
   624  	require.Equal(t, keyCount, rangeLoop(iterOpts))
   625  	fmt.Println("start range disable cache", btree.bpage.GetCacheMetrics())
   626  
   627  	require.Equal(t, keyCount, rangeLoop(nil))
   628  	fmt.Println("start range use cache", btree.bpage.GetCacheMetrics())
   629  
   630  	require.NoError(t, testBitreeClose(btree))
   631  }