github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/objstorage/objstorageprovider/remote_backing_test.go (about)

     1  // Copyright 2023 The LevelDB-Go and Pebble 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 objstorageprovider
     6  
     7  import (
     8  	"encoding/binary"
     9  	"testing"
    10  
    11  	"github.com/cockroachdb/pebble/internal/base"
    12  	"github.com/cockroachdb/pebble/objstorage"
    13  	"github.com/cockroachdb/pebble/objstorage/remote"
    14  	"github.com/cockroachdb/pebble/vfs"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestSharedObjectBacking(t *testing.T) {
    19  	for _, cleanup := range []objstorage.SharedCleanupMethod{objstorage.SharedRefTracking, objstorage.SharedNoCleanup} {
    20  		name := "ref-tracking"
    21  		if cleanup == objstorage.SharedNoCleanup {
    22  			name = "no-cleanup"
    23  		}
    24  		t.Run(name, func(t *testing.T) {
    25  			st := DefaultSettings(vfs.NewMem(), "")
    26  			sharedStorage := remote.NewInMem()
    27  			st.Remote.StorageFactory = remote.MakeSimpleFactory(map[remote.Locator]remote.Storage{
    28  				"foo": sharedStorage,
    29  			})
    30  			p, err := Open(st)
    31  			require.NoError(t, err)
    32  			defer p.Close()
    33  
    34  			const creatorID = objstorage.CreatorID(99)
    35  			require.NoError(t, p.SetCreatorID(creatorID))
    36  			meta := objstorage.ObjectMetadata{
    37  				DiskFileNum: base.FileNum(1).DiskFileNum(),
    38  				FileType:    base.FileTypeTable,
    39  			}
    40  			meta.Remote.CreatorID = 100
    41  			meta.Remote.CreatorFileNum = base.FileNum(200).DiskFileNum()
    42  			meta.Remote.CleanupMethod = cleanup
    43  			meta.Remote.Locator = "foo"
    44  			meta.Remote.CustomObjectName = "obj-name"
    45  			meta.Remote.Storage = sharedStorage
    46  
    47  			h, err := p.RemoteObjectBacking(&meta)
    48  			require.NoError(t, err)
    49  			buf, err := h.Get()
    50  			require.NoError(t, err)
    51  			h.Close()
    52  			_, err = h.Get()
    53  			require.Error(t, err)
    54  
    55  			d1, err := decodeRemoteObjectBacking(base.FileTypeTable, base.FileNum(100).DiskFileNum(), buf)
    56  			require.NoError(t, err)
    57  			require.Equal(t, uint64(100), uint64(d1.meta.DiskFileNum.FileNum()))
    58  			require.Equal(t, base.FileTypeTable, d1.meta.FileType)
    59  			d1.meta.Remote.Storage = sharedStorage
    60  			require.Equal(t, meta.Remote, d1.meta.Remote)
    61  			if cleanup == objstorage.SharedRefTracking {
    62  				require.Equal(t, creatorID, d1.refToCheck.creatorID)
    63  				require.Equal(t, base.FileNum(1).DiskFileNum(), d1.refToCheck.fileNum)
    64  			} else {
    65  				require.Equal(t, objstorage.CreatorID(0), d1.refToCheck.creatorID)
    66  				require.Equal(t, base.FileNum(0).DiskFileNum(), d1.refToCheck.fileNum)
    67  			}
    68  
    69  			t.Run("unknown-tags", func(t *testing.T) {
    70  				// Append a tag that is safe to ignore.
    71  				buf2 := buf
    72  				buf2 = binary.AppendUvarint(buf2, 13)
    73  				buf2 = binary.AppendUvarint(buf2, 2)
    74  				buf2 = append(buf2, 1, 1)
    75  
    76  				d2, err := decodeRemoteObjectBacking(base.FileTypeTable, base.FileNum(100).DiskFileNum(), buf2)
    77  				require.NoError(t, err)
    78  				require.Equal(t, uint64(100), uint64(d2.meta.DiskFileNum.FileNum()))
    79  				require.Equal(t, base.FileTypeTable, d2.meta.FileType)
    80  				d2.meta.Remote.Storage = sharedStorage
    81  				require.Equal(t, meta.Remote, d2.meta.Remote)
    82  				if cleanup == objstorage.SharedRefTracking {
    83  					require.Equal(t, creatorID, d2.refToCheck.creatorID)
    84  					require.Equal(t, base.FileNum(1).DiskFileNum(), d2.refToCheck.fileNum)
    85  				} else {
    86  					require.Equal(t, objstorage.CreatorID(0), d2.refToCheck.creatorID)
    87  					require.Equal(t, base.FileNum(0).DiskFileNum(), d2.refToCheck.fileNum)
    88  				}
    89  
    90  				buf3 := buf2
    91  				buf3 = binary.AppendUvarint(buf3, tagNotSafeToIgnoreMask+5)
    92  				_, err = decodeRemoteObjectBacking(meta.FileType, meta.DiskFileNum, buf3)
    93  				require.Error(t, err)
    94  				require.Contains(t, err.Error(), "unknown tag")
    95  			})
    96  		})
    97  	}
    98  }
    99  
   100  func TestCreateSharedObjectBacking(t *testing.T) {
   101  	st := DefaultSettings(vfs.NewMem(), "")
   102  	sharedStorage := remote.NewInMem()
   103  	st.Remote.StorageFactory = remote.MakeSimpleFactory(map[remote.Locator]remote.Storage{
   104  		"foo": sharedStorage,
   105  	})
   106  	p, err := Open(st)
   107  	require.NoError(t, err)
   108  	defer p.Close()
   109  
   110  	require.NoError(t, p.SetCreatorID(1))
   111  
   112  	backing, err := p.CreateExternalObjectBacking("foo", "custom-obj-name")
   113  	require.NoError(t, err)
   114  	d, err := decodeRemoteObjectBacking(base.FileTypeTable, base.FileNum(100).DiskFileNum(), backing)
   115  	require.NoError(t, err)
   116  	require.Equal(t, uint64(100), uint64(d.meta.DiskFileNum.FileNum()))
   117  	require.Equal(t, base.FileTypeTable, d.meta.FileType)
   118  	require.Equal(t, remote.Locator("foo"), d.meta.Remote.Locator)
   119  	require.Equal(t, "custom-obj-name", d.meta.Remote.CustomObjectName)
   120  	require.Equal(t, objstorage.SharedNoCleanup, d.meta.Remote.CleanupMethod)
   121  }
   122  
   123  func TestAttachRemoteObjects(t *testing.T) {
   124  	st := DefaultSettings(vfs.NewMem(), "")
   125  	sharedStorage := remote.NewInMem()
   126  	st.Remote.StorageFactory = remote.MakeSimpleFactory(map[remote.Locator]remote.Storage{
   127  		"foo": sharedStorage,
   128  	})
   129  	p, err := Open(st)
   130  	require.NoError(t, err)
   131  	defer p.Close()
   132  	require.NoError(t, p.SetCreatorID(1))
   133  	backing, err := p.CreateExternalObjectBacking("foo", "custom-obj-name")
   134  	require.NoError(t, err)
   135  	_, err = p.AttachRemoteObjects([]objstorage.RemoteObjectToAttach{{
   136  		FileType: base.FileTypeTable,
   137  		FileNum:  base.FileNum(100).DiskFileNum(),
   138  		Backing:  backing,
   139  	}})
   140  	require.NoError(t, err)
   141  
   142  	// Sync, close, and reopen the provider and expect that we see
   143  	// our object.
   144  	require.NoError(t, p.Sync())
   145  	require.NoError(t, p.Close())
   146  
   147  	p, err = Open(st)
   148  	require.NoError(t, err)
   149  	defer p.Close()
   150  	require.NoError(t, p.SetCreatorID(1))
   151  	objs := p.List()
   152  	require.Len(t, objs, 1)
   153  	o := objs[0]
   154  	require.Equal(t, remote.Locator("foo"), o.Remote.Locator)
   155  	require.Equal(t, "custom-obj-name", o.Remote.CustomObjectName)
   156  	require.Equal(t, uint64(100), uint64(o.DiskFileNum.FileNum()))
   157  	require.Equal(t, base.FileTypeTable, o.FileType)
   158  }