github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/objstorage/remote/storage.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  )
    11  
    12  // Locator is an opaque string identifying a remote.Storage implementation.
    13  //
    14  // The Locator must not contain secrets (like authentication keys). Locators are
    15  // stored on disk in the shared object catalog and are passed around as part of
    16  // RemoteObjectBacking; they can also appear in error messages.
    17  type Locator string
    18  
    19  // StorageFactory is used to return Storage implementations based on locators. A
    20  // Pebble store that uses shared storage is configured with a StorageFactory.
    21  type StorageFactory interface {
    22  	CreateStorage(locator Locator) (Storage, error)
    23  }
    24  
    25  // SharedLevelsStart denotes the highest (i.e. lowest numbered) level that will
    26  // have sstables shared across Pebble instances when doing skip-shared
    27  // iteration (see db.ScanInternal) or shared file ingestion (see
    28  // db.IngestAndExcise).
    29  const SharedLevelsStart = 5
    30  
    31  // CreateOnSharedStrategy specifies what table files should be created on shared
    32  // storage. For use with CreateOnShared in options.
    33  type CreateOnSharedStrategy int
    34  
    35  const (
    36  	// CreateOnSharedNone denotes no files being created on shared storage.
    37  	CreateOnSharedNone CreateOnSharedStrategy = iota
    38  	// CreateOnSharedLower denotes the creation of files in lower levels of the
    39  	// LSM (specifically, L5 and L6 as they're below SharedLevelsStart) on
    40  	// shared storage, and higher levels on local storage.
    41  	CreateOnSharedLower
    42  	// CreateOnSharedAll denotes the creation of all sstables on shared storage.
    43  	CreateOnSharedAll
    44  )
    45  
    46  // ShouldCreateShared returns whether new table files at the specified level
    47  // should be created on shared storage.
    48  func ShouldCreateShared(strategy CreateOnSharedStrategy, level int) bool {
    49  	switch strategy {
    50  	case CreateOnSharedAll:
    51  		return true
    52  	case CreateOnSharedNone:
    53  		return false
    54  	case CreateOnSharedLower:
    55  		return level >= SharedLevelsStart
    56  	default:
    57  		panic("unexpected CreateOnSharedStrategy value")
    58  	}
    59  }
    60  
    61  // Storage is an interface for a blob storage driver. This is lower-level
    62  // than an FS-like interface, however FS/File-like abstractions can be built on
    63  // top of these methods.
    64  //
    65  // TODO(bilal): Consider pushing shared file obsoletion as well as path
    66  // generation behind this interface.
    67  type Storage interface {
    68  	io.Closer
    69  
    70  	// ReadObject returns an ObjectReader that can be used to perform reads on an
    71  	// object, along with the total size of the object.
    72  	ReadObject(ctx context.Context, objName string) (_ ObjectReader, objSize int64, _ error)
    73  
    74  	// CreateObject returns a writer for the object at the request name. A new
    75  	// empty object is created if CreateObject is called on an existing object.
    76  	//
    77  	// A Writer *must* be closed via either Close, and if closing returns a
    78  	// non-nil error, that error should be handled or reported to the user -- an
    79  	// implementation may buffer written data until Close and only then return
    80  	// an error, or Write may return an opaque io.EOF with the underlying cause
    81  	// returned by the subsequent Close().
    82  	//
    83  	// TODO(radu): if we encounter some unrelated error while writing to the
    84  	// WriteCloser, we'd want to abort the whole thing rather than letting Close
    85  	// finalize the upload.
    86  	CreateObject(objName string) (io.WriteCloser, error)
    87  
    88  	// List enumerates files within the supplied prefix, returning a list of
    89  	// objects within that prefix. If delimiter is non-empty, names which have the
    90  	// same prefix, prior to the delimiter but after the prefix, are grouped into a
    91  	// single result which is that prefix. The order that results are returned is
    92  	// undefined. If a prefix is specified, the prefix is trimmed from the result
    93  	// list.
    94  	//
    95  	// An example would be, if the storage contains objects a, b/4, b/5 and b/6,
    96  	// these would be the return values:
    97  	//   List("", "") -> ["a", "b/4", "b/5", "b/6"]
    98  	//   List("", "/") -> ["a", "b"]
    99  	//   List("b", "/") -> ["4", "5", "6"]
   100  	//   List("b", "") -> ["/4", "/5", "/6"]
   101  	List(prefix, delimiter string) ([]string, error)
   102  
   103  	// Delete removes the named object from the store.
   104  	Delete(objName string) error
   105  
   106  	// Size returns the length of the named object in bytesWritten.
   107  	Size(objName string) (int64, error)
   108  
   109  	// IsNotExistError returns true if the given error (returned by a method in
   110  	// this interface) indicates that the object does not exist.
   111  	IsNotExistError(err error) bool
   112  }
   113  
   114  // ObjectReader is used to perform reads on an object.
   115  type ObjectReader interface {
   116  	// ReadAt reads len(p) bytes into p starting at offset off.
   117  	//
   118  	// Does not return partial results; if offset + len(p) is past the end of the
   119  	// object, an error is returned.
   120  	//
   121  	// Clients of ReadAt can execute parallel ReadAt calls on the same
   122  	// ObjectReader.
   123  	ReadAt(ctx context.Context, p []byte, offset int64) error
   124  
   125  	Close() error
   126  }