github.com/cockroachdb/pebble@v1.1.2/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 }