github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/version_set_test.go (about) 1 // Copyright 2020 The LevelDB-Go and Pebble and Bitalostored Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package bitalostable 6 7 import ( 8 "io" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "github.com/zuoyebang/bitalostable/internal/base" 13 "github.com/zuoyebang/bitalostable/record" 14 "github.com/zuoyebang/bitalostable/sstable" 15 "github.com/zuoyebang/bitalostable/vfs" 16 ) 17 18 func writeAndIngest(t *testing.T, mem vfs.FS, d *DB, k InternalKey, v []byte, filename string) { 19 path := mem.PathJoin("ext", filename) 20 f, err := mem.Create(path) 21 require.NoError(t, err) 22 w := sstable.NewWriter(f, sstable.WriterOptions{}) 23 require.NoError(t, w.Add(k, v)) 24 require.NoError(t, w.Close()) 25 require.NoError(t, d.Ingest([]string{path})) 26 } 27 28 func TestVersionSetCheckpoint(t *testing.T) { 29 mem := vfs.NewMem() 30 require.NoError(t, mem.MkdirAll("ext", 0755)) 31 32 opts := &Options{ 33 FS: mem, 34 MaxManifestFileSize: 1, 35 } 36 d, err := Open("", opts) 37 require.NoError(t, err) 38 39 // Multiple manifest files are created such that the latest one must have a correct snapshot 40 // of the preceding state for the DB to be opened correctly and see the written data. 41 writeAndIngest(t, mem, d, base.MakeInternalKey([]byte("a"), 0, InternalKeyKindSet), []byte("b"), "a") 42 writeAndIngest(t, mem, d, base.MakeInternalKey([]byte("c"), 0, InternalKeyKindSet), []byte("d"), "c") 43 require.NoError(t, d.Close()) 44 d, err = Open("", opts) 45 require.NoError(t, err) 46 checkValue := func(k string, expected string) { 47 v, closer, err := d.Get([]byte(k)) 48 require.NoError(t, err) 49 require.Equal(t, expected, string(v)) 50 closer.Close() 51 } 52 checkValue("a", "b") 53 checkValue("c", "d") 54 require.NoError(t, d.Close()) 55 } 56 57 func TestVersionSetSeqNums(t *testing.T) { 58 mem := vfs.NewMem() 59 require.NoError(t, mem.MkdirAll("ext", 0755)) 60 61 opts := &Options{ 62 FS: mem, 63 MaxManifestFileSize: 1, 64 } 65 d, err := Open("", opts) 66 require.NoError(t, err) 67 68 writeAndIngest(t, mem, d, base.MakeInternalKey([]byte("a"), 0, InternalKeyKindSet), []byte("b"), "a") 69 writeAndIngest(t, mem, d, base.MakeInternalKey([]byte("c"), 0, InternalKeyKindSet), []byte("d"), "c") 70 require.NoError(t, d.Close()) 71 d, err = Open("", opts) 72 require.NoError(t, err) 73 defer d.Close() 74 75 // Check that the manifest has the correct LastSeqNum, equalling the highest 76 // observed SeqNum. 77 filenames, err := mem.List("") 78 require.NoError(t, err) 79 var manifest vfs.File 80 for _, filename := range filenames { 81 fileType, _, ok := base.ParseFilename(mem, filename) 82 if ok && fileType == fileTypeManifest { 83 manifest, err = mem.Open(filename) 84 require.NoError(t, err) 85 } 86 } 87 require.NotNil(t, manifest) 88 defer manifest.Close() 89 rr := record.NewReader(manifest, 0 /* logNum */) 90 lastSeqNum := uint64(0) 91 for { 92 r, err := rr.Next() 93 if err == io.EOF { 94 break 95 } 96 require.NoError(t, err) 97 var ve versionEdit 98 err = ve.Decode(r) 99 require.NoError(t, err) 100 if ve.LastSeqNum != 0 { 101 lastSeqNum = ve.LastSeqNum 102 } 103 } 104 // 2 ingestions happened, so LastSeqNum should equal 2. 105 require.Equal(t, uint64(2), lastSeqNum) 106 // logSeqNum is always one greater than the last assigned sequence number. 107 require.Equal(t, d.mu.versions.atomic.logSeqNum, lastSeqNum+1) 108 }