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  }