github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitable_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 bitalosdb
    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/utils"
    25  )
    26  
    27  var defaultLargeVal = testRandBytes(1024)
    28  
    29  func bdbWriteKVRange(t *testing.T, db *DB, start, end int, kprefix, vprefix string) {
    30  	for i := start; i <= end; i++ {
    31  		key := makeTestKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    32  		value := []byte(fmt.Sprintf("%s_%s%s", key, defaultLargeVal, vprefix))
    33  		require.NoError(t, db.Set(key, value, nil))
    34  	}
    35  	require.NoError(t, db.Flush())
    36  }
    37  
    38  func bdbReadKV(t *testing.T, db *DB, num int, kprefix, vprefix string) {
    39  	for i := 1; i <= num; i++ {
    40  		key := makeTestKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    41  		value := []byte(fmt.Sprintf("%s_%s%s", key, defaultLargeVal, vprefix))
    42  		require.NoError(t, verifyGet(db, key, value))
    43  	}
    44  }
    45  
    46  func bdbWriteSameKVRange(t *testing.T, db *DB, start, end int, kprefix, vprefix string) {
    47  	for i := start; i <= end; i++ {
    48  		key := makeTestSlotKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    49  		value := []byte(fmt.Sprintf("%s_%s%s", key, defaultLargeVal, vprefix))
    50  		require.NoError(t, db.Set(key, value, nil))
    51  	}
    52  	require.NoError(t, db.Flush())
    53  }
    54  
    55  func bdbReadSameKV(t *testing.T, db *DB, num int, kprefix, vprefix string) {
    56  	for i := 1; i <= num; i++ {
    57  		key := makeTestSlotKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    58  		value := []byte(fmt.Sprintf("%s_%s%s", key, defaultLargeVal, vprefix))
    59  		require.NoError(t, verifyGet(db, key, value))
    60  	}
    61  }
    62  
    63  func bdbDeleteKV(t *testing.T, db *DB, num int, kprefix string) {
    64  	for i := 1; i <= num; i++ {
    65  		if i%2 == 0 {
    66  			continue
    67  		}
    68  		key := makeTestKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    69  		require.NoError(t, db.Delete(key, nil))
    70  	}
    71  	require.NoError(t, db.Flush())
    72  }
    73  
    74  func bdbDeleteSameKV(t *testing.T, db *DB, num int, kprefix string) {
    75  	for i := 1; i <= num; i++ {
    76  		if i%2 == 0 {
    77  			continue
    78  		}
    79  		key := makeTestSlotKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    80  		require.NoError(t, db.Delete(key, nil))
    81  	}
    82  	require.NoError(t, db.Flush())
    83  }
    84  
    85  func bdbReadDeleteKV(t *testing.T, db *DB, num int, kprefix, vprefix string) {
    86  	for i := 1; i <= num; i++ {
    87  		newKey := makeTestKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
    88  		newValue := []byte(fmt.Sprintf("%s_%s%s", newKey, defaultLargeVal, vprefix))
    89  		v, closer, err := db.Get(newKey)
    90  		if i%2 == 0 {
    91  			require.NoError(t, err)
    92  			require.Equal(t, newValue, v)
    93  		} else {
    94  			require.Equal(t, ErrNotFound, err)
    95  		}
    96  
    97  		if closer != nil {
    98  			closer()
    99  		}
   100  	}
   101  }
   102  
   103  func bdbReadDeleteSameKV(t *testing.T, db *DB, num int, kprefix, vprefix string) {
   104  	for i := 1; i <= num; i++ {
   105  		newKey := makeTestSlotKey([]byte(fmt.Sprintf("key_%d%s", i, kprefix)))
   106  		newValue := []byte(fmt.Sprintf("%s_%s%s", newKey, defaultLargeVal, vprefix))
   107  		v, closer, err := db.Get(newKey)
   108  		if i%2 == 0 {
   109  			require.NoError(t, err)
   110  			require.Equal(t, newValue, v)
   111  		} else {
   112  			require.Equal(t, ErrNotFound, err)
   113  		}
   114  
   115  		if closer != nil {
   116  			closer()
   117  		}
   118  	}
   119  }
   120  
   121  func TestBitableWriteRead(t *testing.T) {
   122  	defer os.RemoveAll(testDirname)
   123  	os.RemoveAll(testDirname)
   124  
   125  	testOptsUseBitable = true
   126  	db := openTestDB(testDirname, nil)
   127  	num := 100
   128  	bdbWriteKVRange(t, db, 1, num, "bitableKey1", "bitableValue1")
   129  	bdbReadKV(t, db, num, "bitableKey1", "bitableValue1")
   130  	require.Equal(t, false, db.isFlushedBitable())
   131  	db.compactToBitable(1)
   132  	bdbReadKV(t, db, num, "bitableKey1", "bitableValue1")
   133  	bdbWriteKVRange(t, db, 1, num, "bdbKey1", "bdbValue1")
   134  	require.Equal(t, true, db.isFlushedBitable())
   135  	require.NoError(t, db.Close())
   136  	testOptsUseBitable = true
   137  	db = openTestDB(testDirname, nil)
   138  	require.Equal(t, true, db.isFlushedBitable())
   139  	bdbReadKV(t, db, num, "bitableKey1", "bitableValue1")
   140  	bdbReadKV(t, db, num, "bdbKey1", "bdbValue1")
   141  	require.NoError(t, db.Close())
   142  }
   143  
   144  func TestBitableDelete(t *testing.T) {
   145  	defer os.RemoveAll(testDirname)
   146  	os.RemoveAll(testDirname)
   147  	testOptsUseBitable = true
   148  	db := openTestDB(testDirname, nil)
   149  	num := 1000
   150  	bdbWriteKVRange(t, db, 1, 500, "", "")
   151  	db.compactToBitable(1)
   152  	bdbWriteKVRange(t, db, 501, num, "", "")
   153  	bdbDeleteKV(t, db, num, "")
   154  	bdbReadDeleteKV(t, db, num, "", "")
   155  	require.NoError(t, db.Close())
   156  }
   157  
   158  func TestBitableIter(t *testing.T) {
   159  	defer os.RemoveAll(testDirname)
   160  	os.RemoveAll(testDirname)
   161  	testOptsUseBitable = true
   162  	db := openTestDB(testDirname, nil)
   163  	num := 100
   164  	bdbWriteSameKVRange(t, db, 1, 50, "", "")
   165  	db.compactToBitable(1)
   166  	bdbWriteSameKVRange(t, db, 51, 100, "", "")
   167  	bdbReadSameKV(t, db, num, "", "")
   168  	require.NoError(t, db.Close())
   169  	testOptsUseBitable = true
   170  	testIterSeek(t)
   171  	testOptsUseBitable = true
   172  	testIter(t)
   173  }
   174  
   175  func TestBitableIterSeek(t *testing.T) {
   176  	defer os.RemoveAll(testDirname)
   177  	os.RemoveAll(testDirname)
   178  	testOptsUseBitable = true
   179  	db := openTestDB(testDirname, nil)
   180  	defer func() {
   181  		require.NoError(t, db.Close())
   182  	}()
   183  
   184  	makeKey := func(i int) []byte {
   185  		return makeTestSlotKey([]byte(fmt.Sprintf("key_%d", i)))
   186  	}
   187  
   188  	value := utils.FuncRandBytes(520)
   189  	num := 100
   190  	writeKV := func(filter int) {
   191  		for i := 0; i < num; i++ {
   192  			if i >= 1 && i < 10 {
   193  				continue
   194  			}
   195  			if i%2 == filter {
   196  				continue
   197  			}
   198  			newKey := makeKey(i)
   199  			require.NoError(t, db.Set(newKey, value, nil))
   200  		}
   201  		require.NoError(t, db.Flush())
   202  	}
   203  
   204  	writeKV(0)
   205  	db.compactToBitable(1)
   206  	writeKV(1)
   207  
   208  	seekGE := func(it *Iterator, seek, want int) {
   209  		exist := it.SeekGE(makeKey(seek))
   210  		if want == -1 {
   211  			require.Equal(t, false, exist)
   212  			require.Equal(t, false, it.Valid())
   213  		} else {
   214  			require.Equal(t, true, exist)
   215  			require.Equal(t, true, it.Valid())
   216  			require.Equal(t, makeKey(want), it.Key())
   217  			require.Equal(t, value, it.Value())
   218  		}
   219  	}
   220  	iter := db.NewIter(&IterOptions{SlotId: uint32(testSlotId)})
   221  	seekGE(iter, 14, 14)
   222  	seekGE(iter, 141, 15)
   223  	seekGE(iter, 29, 29)
   224  	seekGE(iter, 290, 30)
   225  	seekGE(iter, 491, 50)
   226  	seekGE(iter, 990, -1)
   227  	require.NoError(t, iter.Close())
   228  
   229  	seekLT := func(it *Iterator, seek, want int) {
   230  		exist := it.SeekLT(makeKey(seek))
   231  		if want == -1 {
   232  			require.Equal(t, false, exist)
   233  			require.Equal(t, false, it.Valid())
   234  		} else {
   235  			require.Equal(t, true, exist)
   236  			require.Equal(t, true, it.Valid())
   237  			require.Equal(t, makeKey(want), it.Key())
   238  			require.Equal(t, value, it.Value())
   239  		}
   240  	}
   241  	iter = db.NewIter(&IterOptions{SlotId: uint32(testSlotId)})
   242  	seekLT(iter, 14, 13)
   243  	seekLT(iter, 141, 14)
   244  	seekLT(iter, 30, 29)
   245  	seekLT(iter, 31, 30)
   246  	seekLT(iter, 50, 49)
   247  	seekLT(iter, 990, 99)
   248  	seekLT(iter, 0, -1)
   249  	require.NoError(t, iter.Close())
   250  
   251  	for i := 0; i < num; i++ {
   252  		if i > 0 && i < 90 {
   253  			continue
   254  		}
   255  		newKey := makeKey(i)
   256  		if err := db.Delete(newKey, nil); err != nil {
   257  			t.Fatal("delete err", string(newKey), err)
   258  		}
   259  	}
   260  	require.NoError(t, db.Flush())
   261  
   262  	searchKV := func(it *Iterator) {
   263  		defer func() {
   264  			require.NoError(t, iter.Close())
   265  		}()
   266  		require.Equal(t, true, iter.First())
   267  		require.Equal(t, makeKey(10), iter.Key())
   268  		require.Equal(t, value, iter.Value())
   269  		require.Equal(t, true, iter.Next())
   270  		require.Equal(t, makeKey(11), iter.Key())
   271  		require.Equal(t, value, iter.Value())
   272  		seekGE(iter, 2, 20)
   273  		require.Equal(t, true, iter.Prev())
   274  		require.Equal(t, makeKey(19), iter.Key())
   275  		require.Equal(t, value, iter.Value())
   276  		require.Equal(t, true, iter.Next())
   277  		require.Equal(t, makeKey(20), iter.Key())
   278  		require.Equal(t, value, iter.Value())
   279  		require.Equal(t, true, iter.Last())
   280  		require.Equal(t, makeKey(89), iter.Key())
   281  		require.Equal(t, value, iter.Value())
   282  		require.Equal(t, true, iter.Prev())
   283  		require.Equal(t, makeKey(88), iter.Key())
   284  		require.Equal(t, value, iter.Value())
   285  		seekLT(iter, 60, 59)
   286  		require.Equal(t, true, iter.Next())
   287  		require.Equal(t, makeKey(60), iter.Key())
   288  		require.Equal(t, value, iter.Value())
   289  		require.Equal(t, true, iter.Prev())
   290  		require.Equal(t, makeKey(59), iter.Key())
   291  		require.Equal(t, value, iter.Value())
   292  	}
   293  
   294  	iter = db.NewIter(&IterOptions{SlotId: uint32(testSlotId)})
   295  	searchKV(iter)
   296  	iter = db.NewIter(&IterOptions{IsAll: true})
   297  	searchKV(iter)
   298  
   299  	require.NoError(t, db.Flush())
   300  	iter = db.NewIter(&IterOptions{SlotId: uint32(testSlotId)})
   301  	searchKV(iter)
   302  	iter = db.NewIter(&IterOptions{IsAll: true})
   303  	searchKV(iter)
   304  }
   305  
   306  func TestBitableSameDelete(t *testing.T) {
   307  	defer os.RemoveAll(testDirname)
   308  	os.RemoveAll(testDirname)
   309  	testOptsUseBitable = true
   310  	db := openTestDB(testDirname, nil)
   311  	defer func() {
   312  		require.NoError(t, db.Close())
   313  	}()
   314  
   315  	num := 1000
   316  	bdbWriteSameKVRange(t, db, 1, 500, "", "")
   317  	db.compactToBitable(1)
   318  	bdbWriteSameKVRange(t, db, 501, num, "", "")
   319  	bdbDeleteSameKV(t, db, num, "")
   320  	bdbReadDeleteSameKV(t, db, num, "", "")
   321  }
   322  
   323  func TestBitableCompactDelete(t *testing.T) {
   324  	defer os.RemoveAll(testDirname)
   325  	os.RemoveAll(testDirname)
   326  
   327  	db := testOpenDB(false)
   328  	bw, err := db.newFlushWriter()
   329  	require.NoError(t, err)
   330  	largeValue := utils.FuncRandBytes(1900)
   331  	smallValue := utils.FuncRandBytes(2100)
   332  	seqNum := uint64(0)
   333  	keyCount := 10000
   334  	kvList := testMakeSortedKVList(0, keyCount, seqNum, 1)
   335  	seqNum += uint64(keyCount)
   336  
   337  	for i := 0; i < keyCount; i++ {
   338  		if i%2 == 0 {
   339  			kvList[i].Value = smallValue
   340  		} else {
   341  			kvList[i].Value = largeValue
   342  		}
   343  		require.NoError(t, bw.Set(*kvList[i].Key, kvList[i].Value))
   344  	}
   345  	require.NoError(t, bw.Finish())
   346  
   347  	readKV := func(hasDel bool) {
   348  		for i := 0; i < keyCount; i++ {
   349  			v, vcloser, err := db.Get(kvList[i].Key.UserKey)
   350  			if hasDel && i%9 == 0 {
   351  				require.Equal(t, ErrNotFound, err)
   352  				require.Equal(t, 0, len(v))
   353  			} else {
   354  				require.Equal(t, kvList[i].Value, v)
   355  				vcloser()
   356  			}
   357  		}
   358  	}
   359  
   360  	readKV(false)
   361  	db.compactToBitable(1)
   362  	readKV(false)
   363  
   364  	bw, err = db.newFlushWriter()
   365  	require.NoError(t, err)
   366  	largeValue = utils.FuncRandBytes(1900)
   367  	smallValue = utils.FuncRandBytes(2100)
   368  	for i := 0; i < keyCount; i++ {
   369  		if i%9 == 0 {
   370  			kvList[i].Key.SetKind(base.InternalKeyKindDelete)
   371  			kvList[i].Key.SetSeqNum(seqNum)
   372  			kvList[i].Value = []byte(nil)
   373  		} else {
   374  			if i%2 == 0 {
   375  				kvList[i].Value = smallValue
   376  			} else {
   377  				kvList[i].Value = largeValue
   378  			}
   379  			kvList[i].Key.SetKind(base.InternalKeyKindSet)
   380  			kvList[i].Key.SetSeqNum(seqNum)
   381  		}
   382  		seqNum++
   383  		require.NoError(t, bw.Set(*kvList[i].Key, kvList[i].Value))
   384  	}
   385  	require.NoError(t, bw.Finish())
   386  
   387  	readKV(true)
   388  
   389  	require.NoError(t, db.Close())
   390  }