github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/objstorage/remote/localfs.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 remote 6 7 import ( 8 "context" 9 "io" 10 "os" 11 "path" 12 13 "github.com/cockroachdb/pebble/vfs" 14 ) 15 16 // NewLocalFS returns a vfs-backed implementation of the remote.Storage 17 // interface (for testing). All objects will be stored at the directory 18 // dirname. 19 func NewLocalFS(dirname string, fs vfs.FS) Storage { 20 store := &localFSStore{ 21 dirname: dirname, 22 vfs: fs, 23 } 24 return store 25 } 26 27 // localFSStore is a vfs-backed implementation of the remote.Storage 28 // interface (for testing). 29 type localFSStore struct { 30 dirname string 31 vfs vfs.FS 32 } 33 34 var _ Storage = (*localFSStore)(nil) 35 36 // Close is part of the remote.Storage interface. 37 func (s *localFSStore) Close() error { 38 *s = localFSStore{} 39 return nil 40 } 41 42 // ReadObject is part of the remote.Storage interface. 43 func (s *localFSStore) ReadObject( 44 ctx context.Context, objName string, 45 ) (_ ObjectReader, objSize int64, _ error) { 46 f, err := s.vfs.Open(path.Join(s.dirname, objName)) 47 if err != nil { 48 return nil, 0, err 49 } 50 stat, err := f.Stat() 51 if err != nil { 52 return nil, 0, err 53 } 54 55 return &localFSReader{f}, stat.Size(), nil 56 } 57 58 type localFSReader struct { 59 file vfs.File 60 } 61 62 var _ ObjectReader = (*localFSReader)(nil) 63 64 // ReadAt is part of the shared.ObjectReader interface. 65 func (r *localFSReader) ReadAt(_ context.Context, p []byte, offset int64) error { 66 n, err := r.file.ReadAt(p, offset) 67 // https://pkg.go.dev/io#ReaderAt 68 if err == io.EOF && n == len(p) { 69 return nil 70 } 71 return err 72 } 73 74 // Close is part of the shared.ObjectReader interface. 75 func (r *localFSReader) Close() error { 76 r.file.Close() 77 r.file = nil 78 return nil 79 } 80 81 // CreateObject is part of the remote.Storage interface. 82 func (s *localFSStore) CreateObject(objName string) (io.WriteCloser, error) { 83 file, err := s.vfs.Create(path.Join(s.dirname, objName)) 84 return file, err 85 } 86 87 // List is part of the remote.Storage interface. 88 func (s *localFSStore) List(prefix, delimiter string) ([]string, error) { 89 // TODO(josh): For the intended use case of localfs.go of running 'pebble bench', 90 // List can always return <nil, nil>, since this indicates a file has only one ref, 91 // and since `pebble bench` implies running in a single-pebble-instance context. 92 // https://github.com/cockroachdb/pebble/blob/a9a079d4fb6bf4a9ebc52e4d83a76ad4cbf676cb/objstorage/objstorageprovider/shared.go#L292 93 return nil, nil 94 } 95 96 // Delete is part of the remote.Storage interface. 97 func (s *localFSStore) Delete(objName string) error { 98 return s.vfs.Remove(path.Join(s.dirname, objName)) 99 } 100 101 // Size is part of the remote.Storage interface. 102 func (s *localFSStore) Size(objName string) (int64, error) { 103 f, err := s.vfs.Open(path.Join(s.dirname, objName)) 104 if err != nil { 105 return 0, err 106 } 107 defer f.Close() 108 stat, err := f.Stat() 109 if err != nil { 110 return 0, err 111 } 112 return stat.Size(), nil 113 } 114 115 // IsNotExistError is part of the remote.Storage interface. 116 func (s *localFSStore) IsNotExistError(err error) bool { 117 return err == os.ErrNotExist 118 }