github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/super_table_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 bitpage
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"path/filepath"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/stretchr/testify/require"
    25  	"github.com/zuoyebang/bitalosdb/internal/sortedkv"
    26  	"github.com/zuoyebang/bitalosdb/internal/utils"
    27  )
    28  
    29  var testRunPerf = false
    30  var testTblPath = filepath.Join(testDir, "tbl")
    31  
    32  func testNewPage() *page {
    33  	opts := testInitOpts()
    34  	bpage := &Bitpage{
    35  		dirname: testDir,
    36  		opts:    opts,
    37  	}
    38  	testInitDir()
    39  	return newPage(bpage, PageNum(1))
    40  }
    41  
    42  func testNewSuperTable(t *testing.T, exist bool) *superTable {
    43  	st, err := newSuperTable(testNewPage(), testTblPath, FileNum(1), exist)
    44  	require.NoError(t, err)
    45  	return st
    46  }
    47  
    48  func testCloseSt(st *superTable) error {
    49  	st.p.bp.freeStArenaBuf()
    50  	return st.close()
    51  }
    52  
    53  func TestSuperTable_Open(t *testing.T) {
    54  	defer os.RemoveAll(testDir)
    55  	os.RemoveAll(testDir)
    56  
    57  	st := testNewSuperTable(t, false)
    58  	require.Equal(t, true, st.empty())
    59  	require.Equal(t, stVersionDefault, st.version)
    60  	require.Equal(t, uint64(stHeaderSize), st.inuseBytes())
    61  	require.Equal(t, false, st.indexModified)
    62  
    63  	val, found, kind, _ := st.get([]byte("a"), 0)
    64  	require.Equal(t, false, found)
    65  	require.Equal(t, internalKeyKindInvalid, kind)
    66  	require.Equal(t, []byte(nil), val)
    67  
    68  	num := 100
    69  	kvList := testMakeSortedKV(num, 0, 10)
    70  	for i := 0; i < num; i++ {
    71  		require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
    72  	}
    73  	require.NoError(t, st.mergeIndexes())
    74  	require.Equal(t, true, st.indexModified)
    75  	require.NoError(t, st.close())
    76  
    77  	st = testNewSuperTable(t, true)
    78  	require.Equal(t, false, st.empty())
    79  	require.Equal(t, stVersionDefault, st.version)
    80  	require.Equal(t, uint64(4398), st.inuseBytes())
    81  
    82  	for i := 0; i < num; i++ {
    83  		val, found, kind, _ = st.get(kvList[i].Key.UserKey, 0)
    84  		require.Equal(t, true, found)
    85  		require.Equal(t, internalKeyKindSet, kind)
    86  		require.Equal(t, kvList[i].Value, val)
    87  	}
    88  	require.NoError(t, st.close())
    89  }
    90  
    91  func TestSuperTable_Write(t *testing.T) {
    92  	defer os.RemoveAll(testDir)
    93  	os.RemoveAll(testDir)
    94  
    95  	st := testNewSuperTable(t, false)
    96  	require.Equal(t, true, st.empty())
    97  
    98  	val, found, kind, _ := st.get([]byte("a"), 0)
    99  	require.Equal(t, false, found)
   100  	require.Equal(t, internalKeyKindInvalid, kind)
   101  	require.Equal(t, []byte(nil), val)
   102  
   103  	num := 100
   104  	kvList := testMakeSortedKV(num, 0, 10)
   105  	writeKV := func(pos int) {
   106  		require.NoError(t, st.set(*kvList[pos].Key, kvList[pos].Value))
   107  	}
   108  
   109  	for i := 0; i < 50; i++ {
   110  		writeKV(i)
   111  	}
   112  	require.Equal(t, false, st.empty())
   113  	require.Equal(t, 50, len(st.pending))
   114  	require.NoError(t, st.mergeIndexes())
   115  	require.Equal(t, 0, len(st.pending))
   116  	indexes := st.readIndexes()
   117  	require.Equal(t, 50, len(indexes))
   118  
   119  	for i := 80; i < num; i++ {
   120  		writeKV(i)
   121  	}
   122  	require.Equal(t, 20, len(st.pending))
   123  	require.NoError(t, st.mergeIndexes())
   124  	require.Equal(t, 0, len(st.pending))
   125  	indexes = st.readIndexes()
   126  	require.Equal(t, 70, len(indexes))
   127  
   128  	for i := 50; i < 80; i++ {
   129  		writeKV(i)
   130  	}
   131  	require.Equal(t, 30, len(st.pending))
   132  	require.NoError(t, st.mergeIndexes())
   133  	require.Equal(t, 0, len(st.pending))
   134  	indexes = st.readIndexes()
   135  	require.Equal(t, num, len(indexes))
   136  
   137  	for i := 0; i < num; i++ {
   138  		val, found, kind, _ = st.get(kvList[i].Key.UserKey, 0)
   139  		require.Equal(t, true, found)
   140  		require.Equal(t, internalKeyKindSet, kind)
   141  		require.Equal(t, kvList[i].Value, val)
   142  	}
   143  
   144  	require.NoError(t, st.close())
   145  
   146  	st = testNewSuperTable(t, true)
   147  	for i := 0; i < num; i++ {
   148  		val, found, kind, _ = st.get(kvList[i].Key.UserKey, 0)
   149  		require.Equal(t, true, found)
   150  		require.Equal(t, internalKeyKindSet, kind)
   151  		require.Equal(t, kvList[i].Value, val)
   152  	}
   153  
   154  	require.NoError(t, st.close())
   155  }
   156  
   157  func TestSuperTable_WriteIncomplete(t *testing.T) {
   158  	defer os.RemoveAll(testDir)
   159  	os.RemoveAll(testDir)
   160  
   161  	st := testNewSuperTable(t, false)
   162  	num := 20
   163  	seqNum := uint64(0)
   164  	kvList := testMakeSortedKV(num, seqNum, 10)
   165  	seqNum += uint64(num)
   166  	for i := 0; i < 10; i++ {
   167  		require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
   168  	}
   169  	wn, err := st.writer.writer.Write([]byte("panic"))
   170  	require.NoError(t, err)
   171  	require.Equal(t, 5, wn)
   172  	require.NoError(t, st.writer.fdatasync())
   173  	require.Equal(t, int64(451), st.tbl.fileStatSize())
   174  	require.Equal(t, uint32(446), st.tbl.Size())
   175  	require.NoError(t, testCloseSt(st))
   176  
   177  	st1 := testNewSuperTable(t, true)
   178  	require.Equal(t, int64(451), st1.tbl.fileStatSize())
   179  	require.Equal(t, uint32(446), st1.tbl.Size())
   180  	for i := 10; i < num; i++ {
   181  		require.NoError(t, st1.set(*kvList[i].Key, kvList[i].Value))
   182  	}
   183  	require.NoError(t, st1.mergeIndexes())
   184  	require.Equal(t, int64(878), st1.tbl.fileStatSize())
   185  	require.Equal(t, uint32(878), st1.tbl.Size())
   186  	require.NoError(t, testCloseSt(st1))
   187  	st2 := testNewSuperTable(t, true)
   188  	require.Equal(t, int64(878), st2.tbl.fileStatSize())
   189  	require.Equal(t, uint32(878), st2.tbl.Size())
   190  	for i := 0; i < num; i++ {
   191  		val, found, kind, _ := st2.get(kvList[i].Key.UserKey, 0)
   192  		require.Equal(t, true, found)
   193  		require.Equal(t, internalKeyKindSet, kind)
   194  		require.Equal(t, kvList[i].Value, val)
   195  	}
   196  	require.NoError(t, testCloseSt(st2))
   197  }
   198  
   199  func TestSuperTable_MergeIndexes(t *testing.T) {
   200  	defer os.RemoveAll(testDir)
   201  	os.RemoveAll(testDir)
   202  
   203  	st := testNewSuperTable(t, false)
   204  	val, found, kind, _ := st.get([]byte("a"), 0)
   205  	require.Equal(t, false, found)
   206  	require.Equal(t, internalKeyKindInvalid, kind)
   207  	require.Equal(t, []byte(nil), val)
   208  
   209  	num := 100
   210  	seqNum := uint64(0)
   211  	kvList := testMakeSortedKV(num, seqNum, 10)
   212  	writeKV := func(pos int) {
   213  		require.NoError(t, st.set(*kvList[pos].Key, kvList[pos].Value))
   214  	}
   215  
   216  	seqNum += uint64(num)
   217  	for i := 0; i < 50; i++ {
   218  		require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
   219  	}
   220  	require.Equal(t, 50, len(st.pending))
   221  	require.NoError(t, st.mergeIndexes())
   222  	require.Equal(t, 0, len(st.pending))
   223  	indexes := st.readIndexes()
   224  	require.Equal(t, 50, len(indexes))
   225  	fmt.Println("set 0-49")
   226  
   227  	for i := 50; i < 90; i++ {
   228  		writeKV(i)
   229  	}
   230  	require.Equal(t, 40, len(st.pending))
   231  	require.NoError(t, st.mergeIndexes())
   232  	require.Equal(t, 0, len(st.pending))
   233  	indexes = st.readIndexes()
   234  	require.Equal(t, 90, len(indexes))
   235  	fmt.Println("set 50-89")
   236  
   237  	for i := 20; i < 90; i++ {
   238  		val, found, kind, _ = st.get(kvList[i].Key.UserKey, 0)
   239  		require.Equal(t, true, found)
   240  		require.Equal(t, internalKeyKindSet, kind)
   241  		require.Equal(t, kvList[i].Value, val)
   242  	}
   243  
   244  	wn := 0
   245  	for i := 20; i < num; i++ {
   246  		if i < 90 {
   247  			if i%2 == 0 {
   248  				kvList[i].Value = nil
   249  				kvList[i].Key.SetSeqNum(seqNum)
   250  				kvList[i].Key.SetKind(internalKeyKindDelete)
   251  				seqNum++
   252  				writeKV(i)
   253  				wn++
   254  			} else if i%3 == 0 {
   255  				kvList[i].Value = utils.FuncRandBytes(20)
   256  				kvList[i].Key.SetSeqNum(seqNum)
   257  				seqNum++
   258  				writeKV(i)
   259  				wn++
   260  			}
   261  		} else {
   262  			writeKV(i)
   263  			wn++
   264  		}
   265  	}
   266  	require.Equal(t, wn, len(st.pending))
   267  	require.NoError(t, st.mergeIndexes())
   268  	require.Equal(t, 0, len(st.pending))
   269  	indexes = st.readIndexes()
   270  	require.Equal(t, 100, len(indexes))
   271  	fmt.Println("update 20-99")
   272  
   273  	for i := 0; i < num; i++ {
   274  		val, found, kind, _ = st.get(kvList[i].Key.UserKey, 0)
   275  		require.Equal(t, true, found)
   276  		if i >= 20 && i < 90 && i%2 == 0 {
   277  			require.Equal(t, internalKeyKindDelete, kind)
   278  			require.Equal(t, 0, len(val))
   279  		} else {
   280  			require.Equal(t, internalKeyKindSet, kind)
   281  			require.Equal(t, kvList[i].Value, val)
   282  		}
   283  	}
   284  
   285  	wn = 0
   286  	for i := 30; i < 50; i++ {
   287  		if i%2 == 0 {
   288  			kvList[i].Value = nil
   289  			kvList[i].Key.SetSeqNum(seqNum)
   290  			kvList[i].Key.SetKind(internalKeyKindDelete)
   291  			seqNum++
   292  			writeKV(i)
   293  			wn++
   294  		} else if i%3 == 0 {
   295  			kvList[i].Value = utils.FuncRandBytes(20)
   296  			kvList[i].Key.SetSeqNum(seqNum)
   297  			seqNum++
   298  			writeKV(i)
   299  			wn++
   300  		}
   301  	}
   302  	require.Equal(t, wn, len(st.pending))
   303  	require.NoError(t, st.mergeIndexes())
   304  	require.Equal(t, 0, len(st.pending))
   305  	indexes = st.readIndexes()
   306  	require.Equal(t, 100, len(indexes))
   307  	fmt.Println("update 30-49")
   308  
   309  	read := func(s *superTable) {
   310  		for i := 0; i < num; i++ {
   311  			val, found, kind, _ = s.get(kvList[i].Key.UserKey, 0)
   312  			require.Equal(t, true, found)
   313  			if i >= 20 && i < 90 && i%2 == 0 {
   314  				require.Equal(t, internalKeyKindDelete, kind)
   315  				require.Equal(t, 0, len(val))
   316  			} else {
   317  				require.Equal(t, internalKeyKindSet, kind)
   318  				require.Equal(t, kvList[i].Value, val)
   319  			}
   320  		}
   321  	}
   322  
   323  	read(st)
   324  	require.NoError(t, st.close())
   325  
   326  	st = testNewSuperTable(t, true)
   327  	read(st)
   328  	require.NoError(t, st.close())
   329  	st = testNewSuperTable(t, true)
   330  	read(st)
   331  	require.NoError(t, st.close())
   332  }
   333  
   334  func TestSuperTable_Iter(t *testing.T) {
   335  	defer os.RemoveAll(testDir)
   336  	os.RemoveAll(testDir)
   337  
   338  	st := testNewSuperTable(t, false)
   339  	num := 100
   340  	seqNum := uint64(0)
   341  	kvList := testMakeSortedKV(num, seqNum, 10)
   342  	seqNum += uint64(num)
   343  
   344  	checkKV := func(ik *internalKey, iv []byte, i int) {
   345  		if i == -1 {
   346  			require.Equal(t, nilInternalKey, ik)
   347  			require.Equal(t, []byte(nil), iv)
   348  		} else {
   349  			require.Equal(t, kvList[i].Key.String(), ik.String())
   350  			require.Equal(t, kvList[i].Value, iv)
   351  		}
   352  	}
   353  
   354  	iter := st.newIter(nil)
   355  	itKey, itVal := iter.First()
   356  	if itKey != nil || itVal != nil {
   357  		t.Fatal("empty iter First fail")
   358  	}
   359  	itKey, itVal = iter.Last()
   360  	if itKey != nil || itVal != nil {
   361  		t.Fatal("empty iter Last fail")
   362  	}
   363  	require.NoError(t, iter.Close())
   364  
   365  	for i := 0; i < num; i++ {
   366  		if i%2 == 0 {
   367  			kvList[i].Key.SetKind(internalKeyKindDelete)
   368  			kvList[i].Value = []byte{}
   369  		}
   370  		require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
   371  	}
   372  	require.NoError(t, st.mergeIndexes())
   373  
   374  	seek := func(s *superTable) {
   375  		iter = s.newIter(nil)
   376  		itKey, itVal = iter.First()
   377  		checkKV(itKey, itVal, 0)
   378  		itKey, itVal = iter.Next()
   379  		checkKV(itKey, itVal, 1)
   380  		itKey, itVal = iter.Next()
   381  		checkKV(itKey, itVal, 2)
   382  		itKey, itVal = iter.Prev()
   383  		checkKV(itKey, itVal, 1)
   384  		itKey, itVal = iter.Prev()
   385  		checkKV(itKey, itVal, 0)
   386  		itKey, itVal = iter.Last()
   387  		checkKV(itKey, itVal, 99)
   388  		itKey, itVal = iter.Prev()
   389  		checkKV(itKey, itVal, 98)
   390  		itKey, itVal = iter.Next()
   391  		checkKV(itKey, itVal, 99)
   392  
   393  		itKey, itVal = iter.SeekGE(kvList[51].Key.UserKey)
   394  		checkKV(itKey, itVal, 51)
   395  		itKey, itVal = iter.Next()
   396  		checkKV(itKey, itVal, 52)
   397  		itKey, itVal = iter.SeekGE(kvList[99].Key.UserKey)
   398  		checkKV(itKey, itVal, 99)
   399  		itKey, itVal = iter.Next()
   400  		checkKV(itKey, itVal, -1)
   401  
   402  		itKey, itVal = iter.SeekLT(kvList[43].Key.UserKey)
   403  		checkKV(itKey, itVal, 42)
   404  		itKey, itVal = iter.Prev()
   405  		checkKV(itKey, itVal, 41)
   406  		itKey, itVal = iter.SeekLT(kvList[1].Key.UserKey)
   407  		checkKV(itKey, itVal, 0)
   408  		itKey, itVal = iter.Prev()
   409  		checkKV(itKey, itVal, -1)
   410  		itKey, itVal = iter.SeekLT(kvList[0].Key.UserKey)
   411  		checkKV(itKey, itVal, -1)
   412  
   413  		itKey, itVal = iter.SeekLT(sortedkv.MakeSortedKey(99999))
   414  		checkKV(itKey, itVal, 99)
   415  		itKey, itVal = iter.SeekLT(sortedkv.MakeSortedKey(-1))
   416  		checkKV(itKey, itVal, -1)
   417  		itKey, itVal = iter.SeekGE(sortedkv.MakeSortedKey(99999))
   418  		checkKV(itKey, itVal, -1)
   419  		itKey, itVal = iter.SeekGE(sortedkv.MakeSortedKey(-1))
   420  		checkKV(itKey, itVal, 0)
   421  	}
   422  
   423  	seek(st)
   424  	require.NoError(t, st.close())
   425  	st = testNewSuperTable(t, true)
   426  	seek(st)
   427  	require.NoError(t, st.close())
   428  	st = testNewSuperTable(t, true)
   429  	seek(st)
   430  	require.NoError(t, st.close())
   431  }
   432  
   433  func TestSuperTableIndex_Empty(t *testing.T) {
   434  	defer os.RemoveAll(testDir)
   435  	os.RemoveAll(testDir)
   436  
   437  	st := testNewSuperTable(t, false)
   438  	require.Equal(t, true, st.empty())
   439  	require.NoError(t, st.close())
   440  	st1 := testNewSuperTable(t, true)
   441  	require.Equal(t, true, st1.empty())
   442  	require.NoError(t, st1.close())
   443  	st2 := testNewSuperTable(t, true)
   444  	num := 100
   445  	seqNum := uint64(0)
   446  	kvList := testMakeSortedKV(num, seqNum, 10)
   447  	seqNum += uint64(num)
   448  	for i := 0; i < num; i++ {
   449  		require.NoError(t, st2.set(*kvList[i].Key, kvList[i].Value))
   450  	}
   451  	require.Equal(t, false, st2.empty())
   452  	require.NoError(t, st2.mergeIndexes())
   453  	checkKV := func(s *superTable) {
   454  		for i := 0; i < num; i++ {
   455  			val, found, kind, _ := s.get(kvList[i].Key.UserKey, 0)
   456  			require.Equal(t, true, found)
   457  			require.Equal(t, internalKeyKindSet, kind)
   458  			require.Equal(t, kvList[i].Value, val)
   459  		}
   460  	}
   461  	checkKV(st2)
   462  	require.NoError(t, st2.close())
   463  	st3 := testNewSuperTable(t, true)
   464  	require.Equal(t, false, st3.empty())
   465  	checkKV(st3)
   466  	require.NoError(t, st3.close())
   467  }
   468  
   469  func TestSuperTableIndex_Rebuild(t *testing.T) {
   470  	defer os.RemoveAll(testDir)
   471  	os.RemoveAll(testDir)
   472  
   473  	fmt.Println("open st 1")
   474  	st := testNewSuperTable(t, false)
   475  	num := 100
   476  	seqNum := uint64(0)
   477  	kvList := testMakeSortedKV(num, seqNum, 10)
   478  	seqNum += uint64(num)
   479  
   480  	writeData := func(start, end int) {
   481  		if end > num {
   482  			end = num
   483  		}
   484  		for i := start; i < end; i++ {
   485  			if i%5 == 0 {
   486  				kvList[i].Key.SetKind(internalKeyKindDelete)
   487  				kvList[i].Value = []byte{}
   488  			} else {
   489  				kvList[i].Value = utils.FuncRandBytes(20)
   490  			}
   491  			kvList[i].Key.SetSeqNum(seqNum)
   492  			seqNum++
   493  			require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
   494  		}
   495  	}
   496  	step := 20
   497  	for pos := 0; pos < num; pos += step {
   498  		writeData(pos, pos+step)
   499  		pos -= 10
   500  	}
   501  	for i := 0; i < 50; i++ {
   502  		if i%5 == 0 {
   503  			kvList[i].Key.SetKind(internalKeyKindSet)
   504  			kvList[i].Value = utils.FuncRandBytes(20)
   505  			kvList[i].Key.SetSeqNum(seqNum)
   506  			seqNum++
   507  			require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
   508  		}
   509  	}
   510  	require.NoError(t, st.writer.fdatasync())
   511  	require.NoError(t, st.close())
   512  
   513  	checkKV := func(s *superTable) {
   514  		for i := 0; i < num; i++ {
   515  			val, found, kind, _ := s.get(kvList[i].Key.UserKey, 0)
   516  			require.Equal(t, true, found)
   517  			if i >= 50 && i%5 == 0 {
   518  				require.Equal(t, internalKeyKindDelete, kind)
   519  				require.Equal(t, 0, len(val))
   520  			} else {
   521  				require.Equal(t, internalKeyKindSet, kind)
   522  				require.Equal(t, kvList[i].Value, val)
   523  			}
   524  		}
   525  	}
   526  
   527  	fmt.Println("open st 2")
   528  	st = testNewSuperTable(t, true)
   529  	checkKV(st)
   530  	require.Equal(t, true, st.indexModified)
   531  	require.NoError(t, st.close())
   532  	fmt.Println("open st 3")
   533  	st = testNewSuperTable(t, true)
   534  	checkKV(st)
   535  	require.Equal(t, false, st.indexModified)
   536  	require.NoError(t, st.close())
   537  }
   538  
   539  func TestSuperTableIndex_Rebuild1(t *testing.T) {
   540  	defer os.RemoveAll(testDir)
   541  	os.RemoveAll(testDir)
   542  
   543  	st := testNewSuperTable(t, false)
   544  	num := 100
   545  	seqNum := uint64(0)
   546  	kvList := testMakeSortedKV(num, seqNum, 10)
   547  	seqNum += uint64(num)
   548  
   549  	writeData := func(s *superTable, start, end int) {
   550  		if end > num {
   551  			end = num
   552  		}
   553  		for i := start; i < end; i++ {
   554  			if i%5 == 0 {
   555  				kvList[i].Key.SetKind(internalKeyKindDelete)
   556  				kvList[i].Value = []byte{}
   557  			} else {
   558  				kvList[i].Value = utils.FuncRandBytes(20)
   559  			}
   560  			kvList[i].Key.SetSeqNum(seqNum)
   561  			seqNum++
   562  			require.NoError(t, s.set(*kvList[i].Key, kvList[i].Value))
   563  		}
   564  	}
   565  	writeData(st, 0, 30)
   566  	writeData(st, 70, 100)
   567  	writeData(st, 50, 75)
   568  	writeData(st, 35, 60)
   569  	writeData(st, 12, 50)
   570  	wn, err := st.writer.writer.Write([]byte("panic"))
   571  	require.NoError(t, err)
   572  	require.Equal(t, 5, wn)
   573  	require.NoError(t, st.writer.fdatasync())
   574  	require.Equal(t, int64(7411), st.tbl.fileStatSize())
   575  	require.NoError(t, st.close())
   576  
   577  	checkKV := func(s *superTable) {
   578  		for i := 0; i < num; i++ {
   579  			val, found, kind, _ := s.get(kvList[i].Key.UserKey, 0)
   580  			require.Equal(t, true, found)
   581  			if i%5 == 0 {
   582  				require.Equal(t, internalKeyKindDelete, kind)
   583  				require.Equal(t, 0, len(val))
   584  			} else {
   585  				require.Equal(t, internalKeyKindSet, kind)
   586  				require.Equal(t, kvList[i].Value, val)
   587  			}
   588  		}
   589  	}
   590  
   591  	st1 := testNewSuperTable(t, true)
   592  	require.Equal(t, uint32(7406), st1.tbl.Size())
   593  	checkKV(st1)
   594  	kvList1 := testMakeSortedKV(num, seqNum, 10)
   595  	for i := 0; i < 10; i++ {
   596  		require.NoError(t, st1.set(*kvList1[i].Key, kvList1[i].Value))
   597  	}
   598  	require.NoError(t, st1.writer.fdatasync())
   599  	require.NoError(t, st1.close())
   600  	st2 := testNewSuperTable(t, true)
   601  	checkKV(st2)
   602  	require.NoError(t, st2.close())
   603  }
   604  
   605  func TestSuperTableIndex_Rebuild2(t *testing.T) {
   606  	defer os.RemoveAll(testDir)
   607  
   608  	num := 100
   609  	seqNum := uint64(0)
   610  	for loop := 0; loop < 10; loop++ {
   611  		os.RemoveAll(testDir)
   612  		st := testNewSuperTable(t, false)
   613  		kvList := testMakeSortedKV(num, seqNum, 10)
   614  		seqNum += uint64(num)
   615  		writeData := func(s *superTable, start, end int) {
   616  			if end > num {
   617  				end = num
   618  			}
   619  			for i := start; i < end; i++ {
   620  				if i%5 == 0 {
   621  					kvList[i].Key.SetKind(internalKeyKindDelete)
   622  					kvList[i].Value = []byte{}
   623  				} else {
   624  					kvList[i].Value = utils.FuncRandBytes(20)
   625  				}
   626  				kvList[i].Key.SetSeqNum(seqNum)
   627  				seqNum++
   628  				require.NoError(t, s.set(*kvList[i].Key, kvList[i].Value))
   629  			}
   630  		}
   631  		step := 20
   632  		for pos := 0; pos < num; pos += step {
   633  			writeData(st, pos, pos+step)
   634  			pos -= 10
   635  		}
   636  		require.NoError(t, st.writer.fdatasync())
   637  		require.NoError(t, st.close())
   638  		require.Equal(t, false, utils.IsFileExist(st.getIdxFilePath()))
   639  
   640  		st = testNewSuperTable(t, true)
   641  		for i := 0; i < num; i++ {
   642  			val, found, kind, _ := st.get(kvList[i].Key.UserKey, 0)
   643  			require.Equal(t, true, found)
   644  			if i%5 == 0 {
   645  				require.Equal(t, internalKeyKindDelete, kind)
   646  				require.Equal(t, 0, len(val))
   647  			} else {
   648  				require.Equal(t, internalKeyKindSet, kind)
   649  				require.Equal(t, kvList[i].Value, val)
   650  			}
   651  		}
   652  		require.NoError(t, st.close())
   653  		require.Equal(t, true, utils.IsFileExist(st.getIdxFilePath()))
   654  	}
   655  }
   656  
   657  func TestSuperTableIndex_Rebuild_Perf(t *testing.T) {
   658  	if !testRunPerf {
   659  		return
   660  	}
   661  
   662  	defer os.RemoveAll(testDir)
   663  	os.RemoveAll(testDir)
   664  
   665  	st := testNewSuperTable(t, false)
   666  	num := 6000000
   667  	seqNum := uint64(0)
   668  	kvList := testMakeSortedKV(num, seqNum, 10)
   669  	seqNum += uint64(num)
   670  
   671  	writeData := func(start, end int) {
   672  		if end > num {
   673  			end = num
   674  		}
   675  		for i := start; i < end; i++ {
   676  			require.NoError(t, st.set(*kvList[i].Key, kvList[i].Value))
   677  		}
   678  	}
   679  	step := 500000
   680  	for pos := 0; pos < num; pos += step {
   681  		writeData(pos, pos+step)
   682  	}
   683  	require.NoError(t, st.writer.fdatasync())
   684  	require.NoError(t, st.close())
   685  
   686  	checkKV := func(s *superTable) {
   687  		for i := 0; i < num; i++ {
   688  			val, found, kind, _ := s.get(kvList[i].Key.UserKey, 0)
   689  			require.Equal(t, true, found)
   690  			require.Equal(t, internalKeyKindSet, kind)
   691  			require.Equal(t, kvList[i].Value, val)
   692  		}
   693  	}
   694  
   695  	st1 := testNewSuperTable(t, true)
   696  	startTime := time.Now()
   697  	checkKV(st1)
   698  	check1Cost := time.Since(startTime).Seconds()
   699  	fmt.Println("checkKV 1", check1Cost)
   700  	require.NoError(t, st1.close())
   701  	st1 = testNewSuperTable(t, true)
   702  	reopenCost := time.Since(startTime).Seconds()
   703  	fmt.Println("reopen", reopenCost-check1Cost)
   704  	checkKV(st1)
   705  	check2Cost := time.Since(startTime).Seconds()
   706  	fmt.Println("checkKV 2", check2Cost-reopenCost)
   707  	require.NoError(t, st1.close())
   708  }