github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/compaction_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  	"testing"
    21  
    22  	"github.com/stretchr/testify/require"
    23  	"github.com/zuoyebang/bitalosdb/internal/base"
    24  	"github.com/zuoyebang/bitalosdb/internal/hash"
    25  	"github.com/zuoyebang/bitalosdb/internal/sortedkv"
    26  	"github.com/zuoyebang/bitalosdb/internal/utils"
    27  )
    28  
    29  func TestBitpageCompact_Flush(t *testing.T) {
    30  	testcase(func(index int, params []bool) {
    31  		dir := testDir
    32  		defer os.RemoveAll(dir)
    33  		os.RemoveAll(dir)
    34  
    35  		var endIndex int
    36  		num := 10
    37  		stepCount := 10
    38  		seqNum := uint64(1)
    39  		count := (num + 2) * stepCount
    40  		kvList := testMakeSortedKV(count, seqNum, 10)
    41  		seqNum += uint64(count)
    42  
    43  		writeData := func(bp *Bitpage, pn PageNum) {
    44  			wr := bp.GetPageWriter(pn, nil)
    45  
    46  			startIndex := endIndex
    47  			endIndex = startIndex + stepCount
    48  
    49  			for i := startIndex; i < endIndex; i++ {
    50  				if i%3 == 0 {
    51  					kvList[i].Key.SetKind(internalKeyKindDelete)
    52  					kvList[i].Value = []byte{}
    53  				}
    54  				require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
    55  			}
    56  			require.NoError(t, wr.FlushFinish())
    57  		}
    58  
    59  		readData := func(pg *page) {
    60  			for i := 0; i < endIndex; i++ {
    61  				key := kvList[i].Key.UserKey
    62  				v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key))
    63  				if i%3 == 0 {
    64  					require.Equal(t, false, vexist)
    65  				} else {
    66  					require.Equal(t, kvList[i].Value, v)
    67  					require.Equal(t, internalKeyKindSet, kind)
    68  					vcloser()
    69  				}
    70  			}
    71  		}
    72  
    73  		bp, err := testOpenBitpage(true)
    74  		require.NoError(t, err)
    75  		pn, err1 := bp.NewPage()
    76  		require.NoError(t, err1)
    77  
    78  		writeData(bp, pn)
    79  		p := bp.GetPage(pn)
    80  
    81  		iter := p.newIter(nil)
    82  		require.NoError(t, p.flush(nil, ""))
    83  		require.NoError(t, iter.Close())
    84  
    85  		writeData(bp, pn)
    86  		readData(p)
    87  		testCloseBitpage(t, bp)
    88  
    89  		for i := 0; i < num; i++ {
    90  			fmt.Println("for start", i)
    91  			bp2, err2 := testOpenBitpage(true)
    92  			require.NoError(t, err2)
    93  			writeData(bp2, pn)
    94  			p2 := bp2.GetPage(pn)
    95  			require.NoError(t, p2.flush(nil, ""))
    96  			readData(bp2.GetPage(pn))
    97  			testCloseBitpage(t, bp2)
    98  		}
    99  	})
   100  }
   101  
   102  func TestBitpageCompact_Flush_TableFull(t *testing.T) {
   103  	testcase(func(index int, params []bool) {
   104  		dir := testDir
   105  		defer os.RemoveAll(dir)
   106  		os.RemoveAll(dir)
   107  
   108  		var endIndex int
   109  		stepCount := 15000
   110  		seqNum := uint64(1)
   111  		count := 2 * stepCount
   112  		kvList := testMakeSortedKV(count, seqNum, 100)
   113  		seqNum += uint64(count)
   114  
   115  		writeData := func(bp *Bitpage, pn PageNum) {
   116  			wr := bp.GetPageWriter(pn, nil)
   117  
   118  			startIndex := endIndex
   119  			endIndex = startIndex + stepCount
   120  			for i := startIndex; i < endIndex; i++ {
   121  				if i%3 == 0 {
   122  					kvList[i].Key.SetKind(internalKeyKindDelete)
   123  					kvList[i].Value = []byte{}
   124  				}
   125  				require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   126  			}
   127  			require.NoError(t, wr.FlushFinish())
   128  			require.Equal(t, true, wr.MaybePageFlush(1<<20))
   129  		}
   130  
   131  		readData := func(pg *page) {
   132  			for i := 0; i < endIndex; i++ {
   133  				key := kvList[i].Key.UserKey
   134  				v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key))
   135  				if i%3 == 0 {
   136  					require.Equal(t, false, vexist)
   137  				} else {
   138  					require.Equal(t, kvList[i].Value, v)
   139  					require.Equal(t, internalKeyKindSet, kind)
   140  					vcloser()
   141  				}
   142  			}
   143  		}
   144  
   145  		bp, err := testOpenBitpage(true)
   146  		require.NoError(t, err)
   147  		pn, err1 := bp.NewPage()
   148  		require.NoError(t, err1)
   149  		p := bp.GetPage(pn)
   150  
   151  		require.Equal(t, 1, len(p.mu.stQueue))
   152  		writeData(bp, pn)
   153  		require.NoError(t, p.flush(nil, ""))
   154  		require.Equal(t, 1, len(p.mu.stQueue))
   155  		require.Equal(t, pageFlushStateFinish, p.getFlushState())
   156  		p.setFlushState(pageFlushStateNone)
   157  		writeData(bp, pn)
   158  		require.NoError(t, p.flush(nil, ""))
   159  		require.Equal(t, 1, len(p.mu.stQueue))
   160  		require.Equal(t, pageFlushStateFinish, p.getFlushState())
   161  		readData(p)
   162  		testCloseBitpage(t, bp)
   163  
   164  		bp1, err2 := testOpenBitpage(true)
   165  		require.NoError(t, err2)
   166  		p1 := bp1.GetPage(pn)
   167  		readData(p1)
   168  		testCloseBitpage(t, bp1)
   169  	})
   170  }
   171  
   172  func TestBitpageCompact_Split(t *testing.T) {
   173  	testcase(func(index int, params []bool) {
   174  		dir := testDir
   175  		defer os.RemoveAll(dir)
   176  		os.RemoveAll(dir)
   177  
   178  		bp, err := testOpenBitpage2(dir, params[0], params[1], params[2])
   179  		require.NoError(t, err)
   180  		pn, err1 := bp.NewPage()
   181  		require.NoError(t, err1)
   182  
   183  		seqNum := uint64(1)
   184  		count := 50000
   185  		kvList := testMakeSortedKV(count, seqNum, 100)
   186  		seqNum += uint64(count)
   187  		wr := bp.GetPageWriter(pn, nil)
   188  
   189  		for i := 0; i < count; i++ {
   190  			require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   191  		}
   192  		require.NoError(t, wr.FlushFinish())
   193  
   194  		p := bp.GetPage(pn)
   195  		require.NoError(t, p.flush(nil, ""))
   196  
   197  		bp.opts.BitpageSplitSize = 1 << 18
   198  		sps, err2 := bp.PageSplitStart(pn, "test")
   199  		require.NoError(t, err2)
   200  		bp.PageSplitEnd(pn, sps, nil)
   201  
   202  		spsPn := 2
   203  		for i := range sps {
   204  			require.Equal(t, PageNum(spsPn), sps[i].Pn)
   205  			spsPn++
   206  			fmt.Println("sp:", i, spsPn, string(sps[i].Sentinel))
   207  		}
   208  
   209  		pfiles := p.getFilesPath()
   210  		require.NoError(t, bp.FreePage(pn, true))
   211  		bp.opts.DeleteFilePacer.Flush()
   212  		for i := range pfiles {
   213  			if utils.IsFileExist(pfiles[i]) {
   214  				t.Fatalf("%s is not delete", pfiles[i])
   215  			}
   216  		}
   217  
   218  		testCloseBitpage(t, bp)
   219  	})
   220  }
   221  
   222  func TestBitpageCompact_FlushArrayTableEmpty(t *testing.T) {
   223  	testcase(func(index int, params []bool) {
   224  		dir := testDir
   225  		defer os.RemoveAll(dir)
   226  		os.RemoveAll(dir)
   227  
   228  		bp, err := testOpenBitpage(true)
   229  		require.NoError(t, err)
   230  		pn, err1 := bp.NewPage()
   231  		require.NoError(t, err1)
   232  
   233  		seqNum := uint64(1)
   234  		count := 100
   235  		kvList := testMakeSortedKV(count, seqNum, 10)
   236  		seqNum += uint64(count)
   237  		wr := bp.GetPageWriter(pn, nil)
   238  
   239  		for i := 0; i < 100; i++ {
   240  			require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   241  		}
   242  		require.NoError(t, wr.FlushFinish())
   243  
   244  		p := bp.GetPage(pn)
   245  
   246  		require.NoError(t, p.flush(nil, "111"))
   247  
   248  		wr = bp.GetPageWriter(pn, nil)
   249  		for i := 0; i < 100; i++ {
   250  			kvList[i].Key.SetKind(internalKeyKindDelete)
   251  			kvList[i].Key.SetSeqNum(seqNum)
   252  			seqNum++
   253  			require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   254  		}
   255  		require.NoError(t, wr.FlushFinish())
   256  
   257  		require.NoError(t, p.flush(nil, "222"))
   258  		if p.mu.arrtable != nil {
   259  			t.Fatal("arrtable is not nil")
   260  		}
   261  
   262  		for i := 0; i < 100; i++ {
   263  			key := makeTestKey(i)
   264  			_, vexist, vcloser, _ := p.get(key, hash.Crc32(key))
   265  			require.Equal(t, false, vexist)
   266  			if vcloser != nil {
   267  				vcloser()
   268  			}
   269  		}
   270  
   271  		wr = bp.GetPageWriter(pn, nil)
   272  		for i := 0; i < 100; i++ {
   273  			kvList[i].Key.SetKind(internalKeyKindSet)
   274  			kvList[i].Key.SetSeqNum(seqNum)
   275  			seqNum++
   276  			require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   277  		}
   278  		require.NoError(t, wr.FlushFinish())
   279  
   280  		require.NoError(t, p.flush(nil, "333"))
   281  
   282  		for i := 0; i < 100; i++ {
   283  			key := kvList[i].Key.UserKey
   284  			v, vexist, vcloser, kind := p.get(key, hash.Crc32(key))
   285  			require.Equal(t, kvList[i].Value, v)
   286  			require.Equal(t, true, vexist)
   287  			require.Equal(t, internalKeyKindSet, kind)
   288  			vcloser()
   289  		}
   290  
   291  		testCloseBitpage(t, bp)
   292  	})
   293  }
   294  
   295  func TestBitpageCompact_PrefixDeleteKey(t *testing.T) {
   296  	testcase(func(index int, params []bool) {
   297  		dir := testDir
   298  		defer os.RemoveAll(dir)
   299  		os.RemoveAll(dir)
   300  
   301  		var endIndex int
   302  		num := 5
   303  		stepCount := 30
   304  		seqNum := uint64(1)
   305  		count := (num + 2) * stepCount
   306  		kvList := sortedkv.MakeSortedSamePrefixDeleteKVList(0, count, seqNum, 10, testSlotId)
   307  		seqNum += uint64(count)
   308  
   309  		writeData := func(bp *Bitpage, pn PageNum) {
   310  			wr := bp.GetPageWriter(pn, nil)
   311  			startIndex := endIndex
   312  			endIndex = startIndex + stepCount
   313  			for i := startIndex; i < endIndex; i++ {
   314  				if i%3 == 0 && kvList[i].Key.Kind() != internalKeyKindPrefixDelete {
   315  					kvList[i].Key.SetKind(internalKeyKindDelete)
   316  					kvList[i].Value = []byte{}
   317  				}
   318  				require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   319  			}
   320  			require.NoError(t, wr.FlushFinish())
   321  		}
   322  
   323  		readData := func(pg *page) {
   324  			for i := 0; i < endIndex; i++ {
   325  				key := kvList[i].Key.UserKey
   326  				v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key))
   327  				pd := pg.bp.opts.KeyPrefixDeleteFunc(kvList[i].Key.UserKey)
   328  				if sortedkv.IsPrefixDeleteKey(pd) || i%3 == 0 {
   329  					if vexist {
   330  						t.Log(pd, i, kvList[i].Key.String())
   331  					}
   332  					require.Equal(t, false, vexist)
   333  				} else {
   334  					require.Equal(t, kvList[i].Value, v)
   335  					require.Equal(t, internalKeyKindSet, kind)
   336  					vcloser()
   337  				}
   338  			}
   339  		}
   340  
   341  		bp, err := testOpenBitpage(true)
   342  		require.NoError(t, err)
   343  		pn, err1 := bp.NewPage()
   344  		require.NoError(t, err1)
   345  		writeData(bp, pn)
   346  		p := bp.GetPage(pn)
   347  		require.NoError(t, p.flush(nil, ""))
   348  		readData(p)
   349  		testCloseBitpage(t, bp)
   350  
   351  		for i := 0; i < num; i++ {
   352  			bp2, err2 := testOpenBitpage(true)
   353  			require.NoError(t, err2)
   354  			writeData(bp2, pn)
   355  			p2 := bp2.GetPage(pn)
   356  			require.NoError(t, p2.flush(nil, ""))
   357  			readData(p2)
   358  			testCloseBitpage(t, bp2)
   359  		}
   360  	})
   361  }
   362  
   363  func TestBitpageCompact_PrefixDeleteKey2(t *testing.T) {
   364  	testcase(func(index int, params []bool) {
   365  		dir := testDir
   366  		defer os.RemoveAll(dir)
   367  		os.RemoveAll(dir)
   368  
   369  		var endIndex int
   370  		var pdVers []uint64
   371  		stepCount := 100
   372  		seqNum := uint64(1)
   373  		count := 2 * stepCount
   374  		kvList := sortedkv.MakeSlotSortedKVList2(0, count, seqNum, 10, testSlotId)
   375  		seqNum += uint64(count)
   376  
   377  		isPrefixDelete := func(v uint64) bool {
   378  			if len(pdVers) == 0 {
   379  				return false
   380  			}
   381  			for i := range pdVers {
   382  				if pdVers[i] == v {
   383  					return true
   384  				}
   385  			}
   386  			return false
   387  		}
   388  
   389  		writeData := func(bp *Bitpage, pn PageNum) {
   390  			wr := bp.GetPageWriter(pn, nil)
   391  			startIndex := endIndex
   392  			endIndex = startIndex + stepCount
   393  			for i := startIndex; i < endIndex; i++ {
   394  				require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value))
   395  			}
   396  			require.NoError(t, wr.FlushFinish())
   397  		}
   398  
   399  		writePrefixDeleteKey := func(bp *Bitpage, pn PageNum, versions []uint64) {
   400  			if len(versions) == 0 {
   401  				return
   402  			}
   403  			wr := bp.GetPageWriter(pn, nil)
   404  			for _, version := range versions {
   405  				key := sortedkv.MakeKey2(nil, testSlotId, version)
   406  				seqNum++
   407  				ikey := base.MakeInternalKey(key, seqNum, base.InternalKeyKindPrefixDelete)
   408  				require.NoError(t, wr.Set(ikey, []byte{}))
   409  			}
   410  			require.NoError(t, wr.FlushFinish())
   411  		}
   412  
   413  		readData := func(pg *page) {
   414  			for i := 0; i < endIndex; i++ {
   415  				key := kvList[i].Key.UserKey
   416  				v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key))
   417  				pd := pg.bp.opts.KeyPrefixDeleteFunc(kvList[i].Key.UserKey)
   418  				if isPrefixDelete(pd) {
   419  					if vexist {
   420  						t.Log(pd, i, kvList[i].Key.String())
   421  					}
   422  					require.Equal(t, false, vexist)
   423  				} else {
   424  					require.Equal(t, kvList[i].Value, v)
   425  					require.Equal(t, internalKeyKindSet, kind)
   426  					vcloser()
   427  				}
   428  			}
   429  		}
   430  
   431  		bp, err := testOpenBitpage(true)
   432  		require.NoError(t, err)
   433  		pn, err1 := bp.NewPage()
   434  		require.NoError(t, err1)
   435  		writeData(bp, pn)
   436  		p := bp.GetPage(pn)
   437  		require.NoError(t, p.flush(nil, ""))
   438  		readData(p)
   439  
   440  		pdVers = []uint64{101, 103, 105}
   441  		writePrefixDeleteKey(bp, pn, pdVers)
   442  		require.NoError(t, p.flush(nil, ""))
   443  		readData(p)
   444  
   445  		testCloseBitpage(t, bp)
   446  	})
   447  }