github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/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  }