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