github.com/lbryio/lbcd@v0.22.119/database/interface.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 // Parts of this interface were inspired heavily by the excellent boltdb project 6 // at https://github.com/boltdb/bolt by Ben B. Johnson. 7 8 package database 9 10 import ( 11 "github.com/lbryio/lbcd/chaincfg/chainhash" 12 btcutil "github.com/lbryio/lbcutil" 13 ) 14 15 // Cursor represents a cursor over key/value pairs and nested buckets of a 16 // bucket. 17 // 18 // Note that open cursors are not tracked on bucket changes and any 19 // modifications to the bucket, with the exception of Cursor.Delete, invalidates 20 // the cursor. After invalidation, the cursor must be repositioned, or the keys 21 // and values returned may be unpredictable. 22 type Cursor interface { 23 // Bucket returns the bucket the cursor was created for. 24 Bucket() Bucket 25 26 // Delete removes the current key/value pair the cursor is at without 27 // invalidating the cursor. 28 // 29 // The interface contract guarantees at least the following errors will 30 // be returned (other implementation-specific errors are possible): 31 // - ErrIncompatibleValue if attempted when the cursor points to a 32 // nested bucket 33 // - ErrTxNotWritable if attempted against a read-only transaction 34 // - ErrTxClosed if the transaction has already been closed 35 Delete() error 36 37 // First positions the cursor at the first key/value pair and returns 38 // whether or not the pair exists. 39 First() bool 40 41 // Last positions the cursor at the last key/value pair and returns 42 // whether or not the pair exists. 43 Last() bool 44 45 // Next moves the cursor one key/value pair forward and returns whether 46 // or not the pair exists. 47 Next() bool 48 49 // Prev moves the cursor one key/value pair backward and returns whether 50 // or not the pair exists. 51 Prev() bool 52 53 // Seek positions the cursor at the first key/value pair that is greater 54 // than or equal to the passed seek key. Returns whether or not the 55 // pair exists. 56 Seek(seek []byte) bool 57 58 // Key returns the current key the cursor is pointing to. 59 Key() []byte 60 61 // Value returns the current value the cursor is pointing to. This will 62 // be nil for nested buckets. 63 Value() []byte 64 } 65 66 // Bucket represents a collection of key/value pairs. 67 type Bucket interface { 68 // Bucket retrieves a nested bucket with the given key. Returns nil if 69 // the bucket does not exist. 70 Bucket(key []byte) Bucket 71 72 // CreateBucket creates and returns a new nested bucket with the given 73 // key. 74 // 75 // The interface contract guarantees at least the following errors will 76 // be returned (other implementation-specific errors are possible): 77 // - ErrBucketExists if the bucket already exists 78 // - ErrBucketNameRequired if the key is empty 79 // - ErrIncompatibleValue if the key is otherwise invalid for the 80 // particular implementation 81 // - ErrTxNotWritable if attempted against a read-only transaction 82 // - ErrTxClosed if the transaction has already been closed 83 CreateBucket(key []byte) (Bucket, error) 84 85 // CreateBucketIfNotExists creates and returns a new nested bucket with 86 // the given key if it does not already exist. 87 // 88 // The interface contract guarantees at least the following errors will 89 // be returned (other implementation-specific errors are possible): 90 // - ErrBucketNameRequired if the key is empty 91 // - ErrIncompatibleValue if the key is otherwise invalid for the 92 // particular implementation 93 // - ErrTxNotWritable if attempted against a read-only transaction 94 // - ErrTxClosed if the transaction has already been closed 95 CreateBucketIfNotExists(key []byte) (Bucket, error) 96 97 // DeleteBucket removes a nested bucket with the given key. This also 98 // includes removing all nested buckets and keys under the bucket being 99 // deleted. 100 // 101 // The interface contract guarantees at least the following errors will 102 // be returned (other implementation-specific errors are possible): 103 // - ErrBucketNotFound if the specified bucket does not exist 104 // - ErrTxNotWritable if attempted against a read-only transaction 105 // - ErrTxClosed if the transaction has already been closed 106 DeleteBucket(key []byte) error 107 108 // ForEach invokes the passed function with every key/value pair in the 109 // bucket. This does not include nested buckets or the key/value pairs 110 // within those nested buckets. 111 // 112 // WARNING: It is not safe to mutate data while iterating with this 113 // method. Doing so may cause the underlying cursor to be invalidated 114 // and return unexpected keys and/or values. 115 // 116 // The interface contract guarantees at least the following errors will 117 // be returned (other implementation-specific errors are possible): 118 // - ErrTxClosed if the transaction has already been closed 119 // 120 // NOTE: The slices returned by this function are only valid during a 121 // transaction. Attempting to access them after a transaction has ended 122 // results in undefined behavior. Additionally, the slices must NOT 123 // be modified by the caller. These constraints prevent additional data 124 // copies and allows support for memory-mapped database implementations. 125 ForEach(func(k, v []byte) error) error 126 127 // ForEachBucket invokes the passed function with the key of every 128 // nested bucket in the current bucket. This does not include any 129 // nested buckets within those nested buckets. 130 // 131 // WARNING: It is not safe to mutate data while iterating with this 132 // method. Doing so may cause the underlying cursor to be invalidated 133 // and return unexpected keys and/or values. 134 // 135 // The interface contract guarantees at least the following errors will 136 // be returned (other implementation-specific errors are possible): 137 // - ErrTxClosed if the transaction has already been closed 138 // 139 // NOTE: The keys returned by this function are only valid during a 140 // transaction. Attempting to access them after a transaction has ended 141 // results in undefined behavior. This constraint prevents additional 142 // data copies and allows support for memory-mapped database 143 // implementations. 144 ForEachBucket(func(k []byte) error) error 145 146 // Cursor returns a new cursor, allowing for iteration over the bucket's 147 // key/value pairs and nested buckets in forward or backward order. 148 // 149 // You must seek to a position using the First, Last, or Seek functions 150 // before calling the Next, Prev, Key, or Value functions. Failure to 151 // do so will result in the same return values as an exhausted cursor, 152 // which is false for the Prev and Next functions and nil for Key and 153 // Value functions. 154 Cursor() Cursor 155 156 // Writable returns whether or not the bucket is writable. 157 Writable() bool 158 159 // Put saves the specified key/value pair to the bucket. Keys that do 160 // not already exist are added and keys that already exist are 161 // overwritten. 162 // 163 // The interface contract guarantees at least the following errors will 164 // be returned (other implementation-specific errors are possible): 165 // - ErrKeyRequired if the key is empty 166 // - ErrIncompatibleValue if the key is the same as an existing bucket 167 // - ErrTxNotWritable if attempted against a read-only transaction 168 // - ErrTxClosed if the transaction has already been closed 169 // 170 // NOTE: The slices passed to this function must NOT be modified by the 171 // caller. This constraint prevents the requirement for additional data 172 // copies and allows support for memory-mapped database implementations. 173 Put(key, value []byte) error 174 175 // Get returns the value for the given key. Returns nil if the key does 176 // not exist in this bucket. An empty slice is returned for keys that 177 // exist but have no value assigned. 178 // 179 // NOTE: The value returned by this function is only valid during a 180 // transaction. Attempting to access it after a transaction has ended 181 // results in undefined behavior. Additionally, the value must NOT 182 // be modified by the caller. These constraints prevent additional data 183 // copies and allows support for memory-mapped database implementations. 184 Get(key []byte) []byte 185 186 // Delete removes the specified key from the bucket. Deleting a key 187 // that does not exist does not return an error. 188 // 189 // The interface contract guarantees at least the following errors will 190 // be returned (other implementation-specific errors are possible): 191 // - ErrKeyRequired if the key is empty 192 // - ErrIncompatibleValue if the key is the same as an existing bucket 193 // - ErrTxNotWritable if attempted against a read-only transaction 194 // - ErrTxClosed if the transaction has already been closed 195 Delete(key []byte) error 196 } 197 198 // BlockRegion specifies a particular region of a block identified by the 199 // specified hash, given an offset and length. 200 type BlockRegion struct { 201 Hash *chainhash.Hash 202 Offset uint32 203 Len uint32 204 } 205 206 // Tx represents a database transaction. It can either by read-only or 207 // read-write. The transaction provides a metadata bucket against which all 208 // read and writes occur. 209 // 210 // As would be expected with a transaction, no changes will be saved to the 211 // database until it has been committed. The transaction will only provide a 212 // view of the database at the time it was created. Transactions should not be 213 // long running operations. 214 type Tx interface { 215 // Metadata returns the top-most bucket for all metadata storage. 216 Metadata() Bucket 217 218 // StoreBlock stores the provided block into the database. There are no 219 // checks to ensure the block connects to a previous block, contains 220 // double spends, or any additional functionality such as transaction 221 // indexing. It simply stores the block in the database. 222 // 223 // The interface contract guarantees at least the following errors will 224 // be returned (other implementation-specific errors are possible): 225 // - ErrBlockExists when the block hash already exists 226 // - ErrTxNotWritable if attempted against a read-only transaction 227 // - ErrTxClosed if the transaction has already been closed 228 // 229 // Other errors are possible depending on the implementation. 230 StoreBlock(block *btcutil.Block) error 231 232 // HasBlock returns whether or not a block with the given hash exists 233 // in the database. 234 // 235 // The interface contract guarantees at least the following errors will 236 // be returned (other implementation-specific errors are possible): 237 // - ErrTxClosed if the transaction has already been closed 238 // 239 // Other errors are possible depending on the implementation. 240 HasBlock(hash *chainhash.Hash) (bool, error) 241 242 // HasBlocks returns whether or not the blocks with the provided hashes 243 // exist in the database. 244 // 245 // The interface contract guarantees at least the following errors will 246 // be returned (other implementation-specific errors are possible): 247 // - ErrTxClosed if the transaction has already been closed 248 // 249 // Other errors are possible depending on the implementation. 250 HasBlocks(hashes []chainhash.Hash) ([]bool, error) 251 252 // FetchBlockHeader returns the raw serialized bytes for the block 253 // header identified by the given hash. The raw bytes are in the format 254 // returned by Serialize on a wire.BlockHeader. 255 // 256 // It is highly recommended to use this function (or FetchBlockHeaders) 257 // to obtain block headers over the FetchBlockRegion(s) functions since 258 // it provides the backend drivers the freedom to perform very specific 259 // optimizations which can result in significant speed advantages when 260 // working with headers. 261 // 262 // The interface contract guarantees at least the following errors will 263 // be returned (other implementation-specific errors are possible): 264 // - ErrBlockNotFound if the requested block hash does not exist 265 // - ErrTxClosed if the transaction has already been closed 266 // - ErrCorruption if the database has somehow become corrupted 267 // 268 // NOTE: The data returned by this function is only valid during a 269 // database transaction. Attempting to access it after a transaction 270 // has ended results in undefined behavior. This constraint prevents 271 // additional data copies and allows support for memory-mapped database 272 // implementations. 273 FetchBlockHeader(hash *chainhash.Hash) ([]byte, error) 274 275 // FetchBlockHeaders returns the raw serialized bytes for the block 276 // headers identified by the given hashes. The raw bytes are in the 277 // format returned by Serialize on a wire.BlockHeader. 278 // 279 // It is highly recommended to use this function (or FetchBlockHeader) 280 // to obtain block headers over the FetchBlockRegion(s) functions since 281 // it provides the backend drivers the freedom to perform very specific 282 // optimizations which can result in significant speed advantages when 283 // working with headers. 284 // 285 // Furthermore, depending on the specific implementation, this function 286 // can be more efficient for bulk loading multiple block headers than 287 // loading them one-by-one with FetchBlockHeader. 288 // 289 // The interface contract guarantees at least the following errors will 290 // be returned (other implementation-specific errors are possible): 291 // - ErrBlockNotFound if any of the request block hashes do not exist 292 // - ErrTxClosed if the transaction has already been closed 293 // - ErrCorruption if the database has somehow become corrupted 294 // 295 // NOTE: The data returned by this function is only valid during a 296 // database transaction. Attempting to access it after a transaction 297 // has ended results in undefined behavior. This constraint prevents 298 // additional data copies and allows support for memory-mapped database 299 // implementations. 300 FetchBlockHeaders(hashes []chainhash.Hash) ([][]byte, error) 301 302 // FetchBlock returns the raw serialized bytes for the block identified 303 // by the given hash. The raw bytes are in the format returned by 304 // Serialize on a wire.MsgBlock. 305 // 306 // The interface contract guarantees at least the following errors will 307 // be returned (other implementation-specific errors are possible): 308 // - ErrBlockNotFound if the requested block hash does not exist 309 // - ErrTxClosed if the transaction has already been closed 310 // - ErrCorruption if the database has somehow become corrupted 311 // 312 // NOTE: The data returned by this function is only valid during a 313 // database transaction. Attempting to access it after a transaction 314 // has ended results in undefined behavior. This constraint prevents 315 // additional data copies and allows support for memory-mapped database 316 // implementations. 317 FetchBlock(hash *chainhash.Hash) ([]byte, error) 318 319 // FetchBlocks returns the raw serialized bytes for the blocks 320 // identified by the given hashes. The raw bytes are in the format 321 // returned by Serialize on a wire.MsgBlock. 322 // 323 // The interface contract guarantees at least the following errors will 324 // be returned (other implementation-specific errors are possible): 325 // - ErrBlockNotFound if the any of the requested block hashes do not 326 // exist 327 // - ErrTxClosed if the transaction has already been closed 328 // - ErrCorruption if the database has somehow become corrupted 329 // 330 // NOTE: The data returned by this function is only valid during a 331 // database transaction. Attempting to access it after a transaction 332 // has ended results in undefined behavior. This constraint prevents 333 // additional data copies and allows support for memory-mapped database 334 // implementations. 335 FetchBlocks(hashes []chainhash.Hash) ([][]byte, error) 336 337 // FetchBlockRegion returns the raw serialized bytes for the given 338 // block region. 339 // 340 // For example, it is possible to directly extract Bitcoin transactions 341 // and/or scripts from a block with this function. Depending on the 342 // backend implementation, this can provide significant savings by 343 // avoiding the need to load entire blocks. 344 // 345 // The raw bytes are in the format returned by Serialize on a 346 // wire.MsgBlock and the Offset field in the provided BlockRegion is 347 // zero-based and relative to the start of the block (byte 0). 348 // 349 // The interface contract guarantees at least the following errors will 350 // be returned (other implementation-specific errors are possible): 351 // - ErrBlockNotFound if the requested block hash does not exist 352 // - ErrBlockRegionInvalid if the region exceeds the bounds of the 353 // associated block 354 // - ErrTxClosed if the transaction has already been closed 355 // - ErrCorruption if the database has somehow become corrupted 356 // 357 // NOTE: The data returned by this function is only valid during a 358 // database transaction. Attempting to access it after a transaction 359 // has ended results in undefined behavior. This constraint prevents 360 // additional data copies and allows support for memory-mapped database 361 // implementations. 362 FetchBlockRegion(region *BlockRegion) ([]byte, error) 363 364 // FetchBlockRegions returns the raw serialized bytes for the given 365 // block regions. 366 // 367 // For example, it is possible to directly extract Bitcoin transactions 368 // and/or scripts from various blocks with this function. Depending on 369 // the backend implementation, this can provide significant savings by 370 // avoiding the need to load entire blocks. 371 // 372 // The raw bytes are in the format returned by Serialize on a 373 // wire.MsgBlock and the Offset fields in the provided BlockRegions are 374 // zero-based and relative to the start of the block (byte 0). 375 // 376 // The interface contract guarantees at least the following errors will 377 // be returned (other implementation-specific errors are possible): 378 // - ErrBlockNotFound if any of the requested block hashed do not 379 // exist 380 // - ErrBlockRegionInvalid if one or more region exceed the bounds of 381 // the associated block 382 // - ErrTxClosed if the transaction has already been closed 383 // - ErrCorruption if the database has somehow become corrupted 384 // 385 // NOTE: The data returned by this function is only valid during a 386 // database transaction. Attempting to access it after a transaction 387 // has ended results in undefined behavior. This constraint prevents 388 // additional data copies and allows support for memory-mapped database 389 // implementations. 390 FetchBlockRegions(regions []BlockRegion) ([][]byte, error) 391 392 // ****************************************************************** 393 // Methods related to both atomic metadata storage and block storage. 394 // ****************************************************************** 395 396 // Commit commits all changes that have been made to the metadata or 397 // block storage. Depending on the backend implementation this could be 398 // to a cache that is periodically synced to persistent storage or 399 // directly to persistent storage. In any case, all transactions which 400 // are started after the commit finishes will include all changes made 401 // by this transaction. Calling this function on a managed transaction 402 // will result in a panic. 403 Commit() error 404 405 // Rollback undoes all changes that have been made to the metadata or 406 // block storage. Calling this function on a managed transaction will 407 // result in a panic. 408 Rollback() error 409 } 410 411 // DB provides a generic interface that is used to store bitcoin blocks and 412 // related metadata. This interface is intended to be agnostic to the actual 413 // mechanism used for backend data storage. The RegisterDriver function can be 414 // used to add a new backend data storage method. 415 // 416 // This interface is divided into two distinct categories of functionality. 417 // 418 // The first category is atomic metadata storage with bucket support. This is 419 // accomplished through the use of database transactions. 420 // 421 // The second category is generic block storage. This functionality is 422 // intentionally separate because the mechanism used for block storage may or 423 // may not be the same mechanism used for metadata storage. For example, it is 424 // often more efficient to store the block data as flat files while the metadata 425 // is kept in a database. However, this interface aims to be generic enough to 426 // support blocks in the database too, if needed by a particular backend. 427 type DB interface { 428 // Type returns the database driver type the current database instance 429 // was created with. 430 Type() string 431 432 // Begin starts a transaction which is either read-only or read-write 433 // depending on the specified flag. Multiple read-only transactions 434 // can be started simultaneously while only a single read-write 435 // transaction can be started at a time. The call will block when 436 // starting a read-write transaction when one is already open. 437 // 438 // NOTE: The transaction must be closed by calling Rollback or Commit on 439 // it when it is no longer needed. Failure to do so can result in 440 // unclaimed memory and/or inablity to close the database due to locks 441 // depending on the specific database implementation. 442 Begin(writable bool) (Tx, error) 443 444 // View invokes the passed function in the context of a managed 445 // read-only transaction. Any errors returned from the user-supplied 446 // function are returned from this function. 447 // 448 // Calling Rollback or Commit on the transaction passed to the 449 // user-supplied function will result in a panic. 450 View(fn func(tx Tx) error) error 451 452 // Update invokes the passed function in the context of a managed 453 // read-write transaction. Any errors returned from the user-supplied 454 // function will cause the transaction to be rolled back and are 455 // returned from this function. Otherwise, the transaction is committed 456 // when the user-supplied function returns a nil error. 457 // 458 // Calling Rollback or Commit on the transaction passed to the 459 // user-supplied function will result in a panic. 460 Update(fn func(tx Tx) error) error 461 462 // Close cleanly shuts down the database and syncs all data. It will 463 // block until all database transactions have been finalized (rolled 464 // back or committed). 465 Close() error 466 }