github.com/btcsuite/btcd@v0.24.0/database/ffldb/db.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 package ffldb 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "fmt" 11 "os" 12 "path/filepath" 13 "runtime" 14 "sort" 15 "sync" 16 17 "github.com/btcsuite/btcd/btcutil" 18 "github.com/btcsuite/btcd/chaincfg/chainhash" 19 "github.com/btcsuite/btcd/database" 20 "github.com/btcsuite/btcd/database/internal/treap" 21 "github.com/btcsuite/btcd/wire" 22 "github.com/syndtr/goleveldb/leveldb" 23 "github.com/syndtr/goleveldb/leveldb/comparer" 24 ldberrors "github.com/syndtr/goleveldb/leveldb/errors" 25 "github.com/syndtr/goleveldb/leveldb/filter" 26 "github.com/syndtr/goleveldb/leveldb/iterator" 27 "github.com/syndtr/goleveldb/leveldb/opt" 28 "github.com/syndtr/goleveldb/leveldb/util" 29 ) 30 31 const ( 32 // metadataDbName is the name used for the metadata database. 33 metadataDbName = "metadata" 34 35 // blockHdrSize is the size of a block header. This is simply the 36 // constant from wire and is only provided here for convenience since 37 // wire.MaxBlockHeaderPayload is quite long. 38 blockHdrSize = wire.MaxBlockHeaderPayload 39 40 // blockHdrOffset defines the offsets into a block index row for the 41 // block header. 42 // 43 // The serialized block index row format is: 44 // <blocklocation><blockheader> 45 blockHdrOffset = blockLocSize 46 ) 47 48 var ( 49 // byteOrder is the preferred byte order used through the database and 50 // block files. Sometimes big endian will be used to allow ordered byte 51 // sortable integer values. 52 byteOrder = binary.LittleEndian 53 54 // bucketIndexPrefix is the prefix used for all entries in the bucket 55 // index. 56 bucketIndexPrefix = []byte("bidx") 57 58 // curBucketIDKeyName is the name of the key used to keep track of the 59 // current bucket ID counter. 60 curBucketIDKeyName = []byte("bidx-cbid") 61 62 // metadataBucketID is the ID of the top-level metadata bucket. 63 // It is the value 0 encoded as an unsigned big-endian uint32. 64 metadataBucketID = [4]byte{} 65 66 // blockIdxBucketID is the ID of the internal block metadata bucket. 67 // It is the value 1 encoded as an unsigned big-endian uint32. 68 blockIdxBucketID = [4]byte{0x00, 0x00, 0x00, 0x01} 69 70 // blockIdxBucketName is the bucket used internally to track block 71 // metadata. 72 blockIdxBucketName = []byte("ffldb-blockidx") 73 74 // writeLocKeyName is the key used to store the current write file 75 // location. 76 writeLocKeyName = []byte("ffldb-writeloc") 77 ) 78 79 // Common error strings. 80 const ( 81 // errDbNotOpenStr is the text to use for the database.ErrDbNotOpen 82 // error code. 83 errDbNotOpenStr = "database is not open" 84 85 // errTxClosedStr is the text to use for the database.ErrTxClosed error 86 // code. 87 errTxClosedStr = "database tx is closed" 88 ) 89 90 // bulkFetchData is allows a block location to be specified along with the 91 // index it was requested from. This in turn allows the bulk data loading 92 // functions to sort the data accesses based on the location to improve 93 // performance while keeping track of which result the data is for. 94 type bulkFetchData struct { 95 *blockLocation 96 replyIndex int 97 } 98 99 // bulkFetchDataSorter implements sort.Interface to allow a slice of 100 // bulkFetchData to be sorted. In particular it sorts by file and then 101 // offset so that reads from files are grouped and linear. 102 type bulkFetchDataSorter []bulkFetchData 103 104 // Len returns the number of items in the slice. It is part of the 105 // sort.Interface implementation. 106 func (s bulkFetchDataSorter) Len() int { 107 return len(s) 108 } 109 110 // Swap swaps the items at the passed indices. It is part of the 111 // sort.Interface implementation. 112 func (s bulkFetchDataSorter) Swap(i, j int) { 113 s[i], s[j] = s[j], s[i] 114 } 115 116 // Less returns whether the item with index i should sort before the item with 117 // index j. It is part of the sort.Interface implementation. 118 func (s bulkFetchDataSorter) Less(i, j int) bool { 119 if s[i].blockFileNum < s[j].blockFileNum { 120 return true 121 } 122 if s[i].blockFileNum > s[j].blockFileNum { 123 return false 124 } 125 126 return s[i].fileOffset < s[j].fileOffset 127 } 128 129 // makeDbErr creates a database.Error given a set of arguments. 130 func makeDbErr(c database.ErrorCode, desc string, err error) database.Error { 131 return database.Error{ErrorCode: c, Description: desc, Err: err} 132 } 133 134 // convertErr converts the passed leveldb error into a database error with an 135 // equivalent error code and the passed description. It also sets the passed 136 // error as the underlying error. 137 func convertErr(desc string, ldbErr error) database.Error { 138 // Use the driver-specific error code by default. The code below will 139 // update this with the converted error if it's recognized. 140 var code = database.ErrDriverSpecific 141 142 switch { 143 // Database corruption errors. 144 case ldberrors.IsCorrupted(ldbErr): 145 code = database.ErrCorruption 146 147 // Database open/create errors. 148 case ldbErr == leveldb.ErrClosed: 149 code = database.ErrDbNotOpen 150 151 // Transaction errors. 152 case ldbErr == leveldb.ErrSnapshotReleased: 153 code = database.ErrTxClosed 154 case ldbErr == leveldb.ErrIterReleased: 155 code = database.ErrTxClosed 156 } 157 158 return database.Error{ErrorCode: code, Description: desc, Err: ldbErr} 159 } 160 161 // copySlice returns a copy of the passed slice. This is mostly used to copy 162 // leveldb iterator keys and values since they are only valid until the iterator 163 // is moved instead of during the entirety of the transaction. 164 func copySlice(slice []byte) []byte { 165 ret := make([]byte, len(slice)) 166 copy(ret, slice) 167 return ret 168 } 169 170 // cursor is an internal type used to represent a cursor over key/value pairs 171 // and nested buckets of a bucket and implements the database.Cursor interface. 172 type cursor struct { 173 bucket *bucket 174 dbIter iterator.Iterator 175 pendingIter iterator.Iterator 176 currentIter iterator.Iterator 177 } 178 179 // Enforce cursor implements the database.Cursor interface. 180 var _ database.Cursor = (*cursor)(nil) 181 182 // Bucket returns the bucket the cursor was created for. 183 // 184 // This function is part of the database.Cursor interface implementation. 185 func (c *cursor) Bucket() database.Bucket { 186 // Ensure transaction state is valid. 187 if err := c.bucket.tx.checkClosed(); err != nil { 188 return nil 189 } 190 191 return c.bucket 192 } 193 194 // Delete removes the current key/value pair the cursor is at without 195 // invalidating the cursor. 196 // 197 // Returns the following errors as required by the interface contract: 198 // - ErrIncompatibleValue if attempted when the cursor points to a nested 199 // bucket 200 // - ErrTxNotWritable if attempted against a read-only transaction 201 // - ErrTxClosed if the transaction has already been closed 202 // 203 // This function is part of the database.Cursor interface implementation. 204 func (c *cursor) Delete() error { 205 // Ensure transaction state is valid. 206 if err := c.bucket.tx.checkClosed(); err != nil { 207 return err 208 } 209 210 // Error if the cursor is exhausted. 211 if c.currentIter == nil { 212 str := "cursor is exhausted" 213 return makeDbErr(database.ErrIncompatibleValue, str, nil) 214 } 215 216 // Do not allow buckets to be deleted via the cursor. 217 key := c.currentIter.Key() 218 if bytes.HasPrefix(key, bucketIndexPrefix) { 219 str := "buckets may not be deleted from a cursor" 220 return makeDbErr(database.ErrIncompatibleValue, str, nil) 221 } 222 223 c.bucket.tx.deleteKey(copySlice(key), true) 224 return nil 225 } 226 227 // skipPendingUpdates skips any keys at the current database iterator position 228 // that are being updated by the transaction. The forwards flag indicates the 229 // direction the cursor is moving. 230 func (c *cursor) skipPendingUpdates(forwards bool) { 231 for c.dbIter.Valid() { 232 var skip bool 233 key := c.dbIter.Key() 234 if c.bucket.tx.pendingRemove.Has(key) { 235 skip = true 236 } else if c.bucket.tx.pendingKeys.Has(key) { 237 skip = true 238 } 239 if !skip { 240 break 241 } 242 243 if forwards { 244 c.dbIter.Next() 245 } else { 246 c.dbIter.Prev() 247 } 248 } 249 } 250 251 // chooseIterator first skips any entries in the database iterator that are 252 // being updated by the transaction and sets the current iterator to the 253 // appropriate iterator depending on their validity and the order they compare 254 // in while taking into account the direction flag. When the cursor is being 255 // moved forwards and both iterators are valid, the iterator with the smaller 256 // key is chosen and vice versa when the cursor is being moved backwards. 257 func (c *cursor) chooseIterator(forwards bool) bool { 258 // Skip any keys at the current database iterator position that are 259 // being updated by the transaction. 260 c.skipPendingUpdates(forwards) 261 262 // When both iterators are exhausted, the cursor is exhausted too. 263 if !c.dbIter.Valid() && !c.pendingIter.Valid() { 264 c.currentIter = nil 265 return false 266 } 267 268 // Choose the database iterator when the pending keys iterator is 269 // exhausted. 270 if !c.pendingIter.Valid() { 271 c.currentIter = c.dbIter 272 return true 273 } 274 275 // Choose the pending keys iterator when the database iterator is 276 // exhausted. 277 if !c.dbIter.Valid() { 278 c.currentIter = c.pendingIter 279 return true 280 } 281 282 // Both iterators are valid, so choose the iterator with either the 283 // smaller or larger key depending on the forwards flag. 284 compare := bytes.Compare(c.dbIter.Key(), c.pendingIter.Key()) 285 if (forwards && compare > 0) || (!forwards && compare < 0) { 286 c.currentIter = c.pendingIter 287 } else { 288 c.currentIter = c.dbIter 289 } 290 return true 291 } 292 293 // First positions the cursor at the first key/value pair and returns whether or 294 // not the pair exists. 295 // 296 // This function is part of the database.Cursor interface implementation. 297 func (c *cursor) First() bool { 298 // Ensure transaction state is valid. 299 if err := c.bucket.tx.checkClosed(); err != nil { 300 return false 301 } 302 303 // Seek to the first key in both the database and pending iterators and 304 // choose the iterator that is both valid and has the smaller key. 305 c.dbIter.First() 306 c.pendingIter.First() 307 return c.chooseIterator(true) 308 } 309 310 // Last positions the cursor at the last key/value pair and returns whether or 311 // not the pair exists. 312 // 313 // This function is part of the database.Cursor interface implementation. 314 func (c *cursor) Last() bool { 315 // Ensure transaction state is valid. 316 if err := c.bucket.tx.checkClosed(); err != nil { 317 return false 318 } 319 320 // Seek to the last key in both the database and pending iterators and 321 // choose the iterator that is both valid and has the larger key. 322 c.dbIter.Last() 323 c.pendingIter.Last() 324 return c.chooseIterator(false) 325 } 326 327 // Next moves the cursor one key/value pair forward and returns whether or not 328 // the pair exists. 329 // 330 // This function is part of the database.Cursor interface implementation. 331 func (c *cursor) Next() bool { 332 // Ensure transaction state is valid. 333 if err := c.bucket.tx.checkClosed(); err != nil { 334 return false 335 } 336 337 // Nothing to return if cursor is exhausted. 338 if c.currentIter == nil { 339 return false 340 } 341 342 // Move the current iterator to the next entry and choose the iterator 343 // that is both valid and has the smaller key. 344 c.currentIter.Next() 345 return c.chooseIterator(true) 346 } 347 348 // Prev moves the cursor one key/value pair backward and returns whether or not 349 // the pair exists. 350 // 351 // This function is part of the database.Cursor interface implementation. 352 func (c *cursor) Prev() bool { 353 // Ensure transaction state is valid. 354 if err := c.bucket.tx.checkClosed(); err != nil { 355 return false 356 } 357 358 // Nothing to return if cursor is exhausted. 359 if c.currentIter == nil { 360 return false 361 } 362 363 // Move the current iterator to the previous entry and choose the 364 // iterator that is both valid and has the larger key. 365 c.currentIter.Prev() 366 return c.chooseIterator(false) 367 } 368 369 // Seek positions the cursor at the first key/value pair that is greater than or 370 // equal to the passed seek key. Returns false if no suitable key was found. 371 // 372 // This function is part of the database.Cursor interface implementation. 373 func (c *cursor) Seek(seek []byte) bool { 374 // Ensure transaction state is valid. 375 if err := c.bucket.tx.checkClosed(); err != nil { 376 return false 377 } 378 379 // Seek to the provided key in both the database and pending iterators 380 // then choose the iterator that is both valid and has the larger key. 381 seekKey := bucketizedKey(c.bucket.id, seek) 382 c.dbIter.Seek(seekKey) 383 c.pendingIter.Seek(seekKey) 384 return c.chooseIterator(true) 385 } 386 387 // rawKey returns the current key the cursor is pointing to without stripping 388 // the current bucket prefix or bucket index prefix. 389 func (c *cursor) rawKey() []byte { 390 // Nothing to return if cursor is exhausted. 391 if c.currentIter == nil { 392 return nil 393 } 394 395 return copySlice(c.currentIter.Key()) 396 } 397 398 // Key returns the current key the cursor is pointing to. 399 // 400 // This function is part of the database.Cursor interface implementation. 401 func (c *cursor) Key() []byte { 402 // Ensure transaction state is valid. 403 if err := c.bucket.tx.checkClosed(); err != nil { 404 return nil 405 } 406 407 // Nothing to return if cursor is exhausted. 408 if c.currentIter == nil { 409 return nil 410 } 411 412 // Slice out the actual key name and make a copy since it is no longer 413 // valid after iterating to the next item. 414 // 415 // The key is after the bucket index prefix and parent ID when the 416 // cursor is pointing to a nested bucket. 417 key := c.currentIter.Key() 418 if bytes.HasPrefix(key, bucketIndexPrefix) { 419 key = key[len(bucketIndexPrefix)+4:] 420 return copySlice(key) 421 } 422 423 // The key is after the bucket ID when the cursor is pointing to a 424 // normal entry. 425 key = key[len(c.bucket.id):] 426 return copySlice(key) 427 } 428 429 // rawValue returns the current value the cursor is pointing to without 430 // stripping without filtering bucket index values. 431 func (c *cursor) rawValue() []byte { 432 // Nothing to return if cursor is exhausted. 433 if c.currentIter == nil { 434 return nil 435 } 436 437 return copySlice(c.currentIter.Value()) 438 } 439 440 // Value returns the current value the cursor is pointing to. This will be nil 441 // for nested buckets. 442 // 443 // This function is part of the database.Cursor interface implementation. 444 func (c *cursor) Value() []byte { 445 // Ensure transaction state is valid. 446 if err := c.bucket.tx.checkClosed(); err != nil { 447 return nil 448 } 449 450 // Nothing to return if cursor is exhausted. 451 if c.currentIter == nil { 452 return nil 453 } 454 455 // Return nil for the value when the cursor is pointing to a nested 456 // bucket. 457 if bytes.HasPrefix(c.currentIter.Key(), bucketIndexPrefix) { 458 return nil 459 } 460 461 return copySlice(c.currentIter.Value()) 462 } 463 464 // cursorType defines the type of cursor to create. 465 type cursorType int 466 467 // The following constants define the allowed cursor types. 468 const ( 469 // ctKeys iterates through all of the keys in a given bucket. 470 ctKeys cursorType = iota 471 472 // ctBuckets iterates through all directly nested buckets in a given 473 // bucket. 474 ctBuckets 475 476 // ctFull iterates through both the keys and the directly nested buckets 477 // in a given bucket. 478 ctFull 479 ) 480 481 // cursorFinalizer is either invoked when a cursor is being garbage collected or 482 // called manually to ensure the underlying cursor iterators are released. 483 func cursorFinalizer(c *cursor) { 484 c.dbIter.Release() 485 c.pendingIter.Release() 486 } 487 488 // newCursor returns a new cursor for the given bucket, bucket ID, and cursor 489 // type. 490 // 491 // NOTE: The caller is responsible for calling the cursorFinalizer function on 492 // the returned cursor. 493 func newCursor(b *bucket, bucketID []byte, cursorTyp cursorType) *cursor { 494 var dbIter, pendingIter iterator.Iterator 495 switch cursorTyp { 496 case ctKeys: 497 keyRange := util.BytesPrefix(bucketID) 498 dbIter = b.tx.snapshot.NewIterator(keyRange) 499 pendingKeyIter := newLdbTreapIter(b.tx, keyRange) 500 pendingIter = pendingKeyIter 501 502 case ctBuckets: 503 // The serialized bucket index key format is: 504 // <bucketindexprefix><parentbucketid><bucketname> 505 506 // Create an iterator for the both the database and the pending 507 // keys which are prefixed by the bucket index identifier and 508 // the provided bucket ID. 509 prefix := make([]byte, len(bucketIndexPrefix)+4) 510 copy(prefix, bucketIndexPrefix) 511 copy(prefix[len(bucketIndexPrefix):], bucketID) 512 bucketRange := util.BytesPrefix(prefix) 513 514 dbIter = b.tx.snapshot.NewIterator(bucketRange) 515 pendingBucketIter := newLdbTreapIter(b.tx, bucketRange) 516 pendingIter = pendingBucketIter 517 518 case ctFull: 519 fallthrough 520 default: 521 // The serialized bucket index key format is: 522 // <bucketindexprefix><parentbucketid><bucketname> 523 prefix := make([]byte, len(bucketIndexPrefix)+4) 524 copy(prefix, bucketIndexPrefix) 525 copy(prefix[len(bucketIndexPrefix):], bucketID) 526 bucketRange := util.BytesPrefix(prefix) 527 keyRange := util.BytesPrefix(bucketID) 528 529 // Since both keys and buckets are needed from the database, 530 // create an individual iterator for each prefix and then create 531 // a merged iterator from them. 532 dbKeyIter := b.tx.snapshot.NewIterator(keyRange) 533 dbBucketIter := b.tx.snapshot.NewIterator(bucketRange) 534 iters := []iterator.Iterator{dbKeyIter, dbBucketIter} 535 dbIter = iterator.NewMergedIterator(iters, 536 comparer.DefaultComparer, true) 537 538 // Since both keys and buckets are needed from the pending keys, 539 // create an individual iterator for each prefix and then create 540 // a merged iterator from them. 541 pendingKeyIter := newLdbTreapIter(b.tx, keyRange) 542 pendingBucketIter := newLdbTreapIter(b.tx, bucketRange) 543 iters = []iterator.Iterator{pendingKeyIter, pendingBucketIter} 544 pendingIter = iterator.NewMergedIterator(iters, 545 comparer.DefaultComparer, true) 546 } 547 548 // Create the cursor using the iterators. 549 return &cursor{bucket: b, dbIter: dbIter, pendingIter: pendingIter} 550 } 551 552 // bucket is an internal type used to represent a collection of key/value pairs 553 // and implements the database.Bucket interface. 554 type bucket struct { 555 tx *transaction 556 id [4]byte 557 } 558 559 // Enforce bucket implements the database.Bucket interface. 560 var _ database.Bucket = (*bucket)(nil) 561 562 // bucketIndexKey returns the actual key to use for storing and retrieving a 563 // child bucket in the bucket index. This is required because additional 564 // information is needed to distinguish nested buckets with the same name. 565 func bucketIndexKey(parentID [4]byte, key []byte) []byte { 566 // The serialized bucket index key format is: 567 // <bucketindexprefix><parentbucketid><bucketname> 568 indexKey := make([]byte, len(bucketIndexPrefix)+4+len(key)) 569 copy(indexKey, bucketIndexPrefix) 570 copy(indexKey[len(bucketIndexPrefix):], parentID[:]) 571 copy(indexKey[len(bucketIndexPrefix)+4:], key) 572 return indexKey 573 } 574 575 // bucketizedKey returns the actual key to use for storing and retrieving a key 576 // for the provided bucket ID. This is required because bucketizing is handled 577 // through the use of a unique prefix per bucket. 578 func bucketizedKey(bucketID [4]byte, key []byte) []byte { 579 // The serialized block index key format is: 580 // <bucketid><key> 581 bKey := make([]byte, 4+len(key)) 582 copy(bKey, bucketID[:]) 583 copy(bKey[4:], key) 584 return bKey 585 } 586 587 // Bucket retrieves a nested bucket with the given key. Returns nil if 588 // the bucket does not exist. 589 // 590 // This function is part of the database.Bucket interface implementation. 591 func (b *bucket) Bucket(key []byte) database.Bucket { 592 // Ensure transaction state is valid. 593 if err := b.tx.checkClosed(); err != nil { 594 return nil 595 } 596 597 // Attempt to fetch the ID for the child bucket. The bucket does not 598 // exist if the bucket index entry does not exist. 599 childID := b.tx.fetchKey(bucketIndexKey(b.id, key)) 600 if childID == nil { 601 return nil 602 } 603 604 childBucket := &bucket{tx: b.tx} 605 copy(childBucket.id[:], childID) 606 return childBucket 607 } 608 609 // CreateBucket creates and returns a new nested bucket with the given key. 610 // 611 // Returns the following errors as required by the interface contract: 612 // - ErrBucketExists if the bucket already exists 613 // - ErrBucketNameRequired if the key is empty 614 // - ErrIncompatibleValue if the key is otherwise invalid for the particular 615 // implementation 616 // - ErrTxNotWritable if attempted against a read-only transaction 617 // - ErrTxClosed if the transaction has already been closed 618 // 619 // This function is part of the database.Bucket interface implementation. 620 func (b *bucket) CreateBucket(key []byte) (database.Bucket, error) { 621 // Ensure transaction state is valid. 622 if err := b.tx.checkClosed(); err != nil { 623 return nil, err 624 } 625 626 // Ensure the transaction is writable. 627 if !b.tx.writable { 628 str := "create bucket requires a writable database transaction" 629 return nil, makeDbErr(database.ErrTxNotWritable, str, nil) 630 } 631 632 // Ensure a key was provided. 633 if len(key) == 0 { 634 str := "create bucket requires a key" 635 return nil, makeDbErr(database.ErrBucketNameRequired, str, nil) 636 } 637 638 // Ensure bucket does not already exist. 639 bidxKey := bucketIndexKey(b.id, key) 640 if b.tx.hasKey(bidxKey) { 641 str := "bucket already exists" 642 return nil, makeDbErr(database.ErrBucketExists, str, nil) 643 } 644 645 // Find the appropriate next bucket ID to use for the new bucket. In 646 // the case of the special internal block index, keep the fixed ID. 647 var childID [4]byte 648 if b.id == metadataBucketID && bytes.Equal(key, blockIdxBucketName) { 649 childID = blockIdxBucketID 650 } else { 651 var err error 652 childID, err = b.tx.nextBucketID() 653 if err != nil { 654 return nil, err 655 } 656 } 657 658 // Add the new bucket to the bucket index. 659 if err := b.tx.putKey(bidxKey, childID[:]); err != nil { 660 str := fmt.Sprintf("failed to create bucket with key %q", key) 661 return nil, convertErr(str, err) 662 } 663 return &bucket{tx: b.tx, id: childID}, nil 664 } 665 666 // CreateBucketIfNotExists creates and returns a new nested bucket with the 667 // given key if it does not already exist. 668 // 669 // Returns the following errors as required by the interface contract: 670 // - ErrBucketNameRequired if the key is empty 671 // - ErrIncompatibleValue if the key is otherwise invalid for the particular 672 // implementation 673 // - ErrTxNotWritable if attempted against a read-only transaction 674 // - ErrTxClosed if the transaction has already been closed 675 // 676 // This function is part of the database.Bucket interface implementation. 677 func (b *bucket) CreateBucketIfNotExists(key []byte) (database.Bucket, error) { 678 // Ensure transaction state is valid. 679 if err := b.tx.checkClosed(); err != nil { 680 return nil, err 681 } 682 683 // Ensure the transaction is writable. 684 if !b.tx.writable { 685 str := "create bucket requires a writable database transaction" 686 return nil, makeDbErr(database.ErrTxNotWritable, str, nil) 687 } 688 689 // Return existing bucket if it already exists, otherwise create it. 690 if bucket := b.Bucket(key); bucket != nil { 691 return bucket, nil 692 } 693 return b.CreateBucket(key) 694 } 695 696 // DeleteBucket removes a nested bucket with the given key. 697 // 698 // Returns the following errors as required by the interface contract: 699 // - ErrBucketNotFound if the specified bucket does not exist 700 // - ErrTxNotWritable if attempted against a read-only transaction 701 // - ErrTxClosed if the transaction has already been closed 702 // 703 // This function is part of the database.Bucket interface implementation. 704 func (b *bucket) DeleteBucket(key []byte) error { 705 // Ensure transaction state is valid. 706 if err := b.tx.checkClosed(); err != nil { 707 return err 708 } 709 710 // Ensure the transaction is writable. 711 if !b.tx.writable { 712 str := "delete bucket requires a writable database transaction" 713 return makeDbErr(database.ErrTxNotWritable, str, nil) 714 } 715 716 // Attempt to fetch the ID for the child bucket. The bucket does not 717 // exist if the bucket index entry does not exist. In the case of the 718 // special internal block index, keep the fixed ID. 719 bidxKey := bucketIndexKey(b.id, key) 720 childID := b.tx.fetchKey(bidxKey) 721 if childID == nil { 722 str := fmt.Sprintf("bucket %q does not exist", key) 723 return makeDbErr(database.ErrBucketNotFound, str, nil) 724 } 725 726 // Remove all nested buckets and their keys. 727 childIDs := [][]byte{childID} 728 for len(childIDs) > 0 { 729 childID = childIDs[len(childIDs)-1] 730 childIDs = childIDs[:len(childIDs)-1] 731 732 // Delete all keys in the nested bucket. 733 keyCursor := newCursor(b, childID, ctKeys) 734 for ok := keyCursor.First(); ok; ok = keyCursor.Next() { 735 b.tx.deleteKey(keyCursor.rawKey(), false) 736 } 737 cursorFinalizer(keyCursor) 738 739 // Iterate through all nested buckets. 740 bucketCursor := newCursor(b, childID, ctBuckets) 741 for ok := bucketCursor.First(); ok; ok = bucketCursor.Next() { 742 // Push the id of the nested bucket onto the stack for 743 // the next iteration. 744 childID := bucketCursor.rawValue() 745 childIDs = append(childIDs, childID) 746 747 // Remove the nested bucket from the bucket index. 748 b.tx.deleteKey(bucketCursor.rawKey(), false) 749 } 750 cursorFinalizer(bucketCursor) 751 } 752 753 // Remove the nested bucket from the bucket index. Any buckets nested 754 // under it were already removed above. 755 b.tx.deleteKey(bidxKey, true) 756 return nil 757 } 758 759 // Cursor returns a new cursor, allowing for iteration over the bucket's 760 // key/value pairs and nested buckets in forward or backward order. 761 // 762 // You must seek to a position using the First, Last, or Seek functions before 763 // calling the Next, Prev, Key, or Value functions. Failure to do so will 764 // result in the same return values as an exhausted cursor, which is false for 765 // the Prev and Next functions and nil for Key and Value functions. 766 // 767 // This function is part of the database.Bucket interface implementation. 768 func (b *bucket) Cursor() database.Cursor { 769 // Ensure transaction state is valid. 770 if err := b.tx.checkClosed(); err != nil { 771 return &cursor{bucket: b} 772 } 773 774 // Create the cursor and setup a runtime finalizer to ensure the 775 // iterators are released when the cursor is garbage collected. 776 c := newCursor(b, b.id[:], ctFull) 777 runtime.SetFinalizer(c, cursorFinalizer) 778 return c 779 } 780 781 // ForEach invokes the passed function with every key/value pair in the bucket. 782 // This does not include nested buckets or the key/value pairs within those 783 // nested buckets. 784 // 785 // WARNING: It is not safe to mutate data while iterating with this method. 786 // Doing so may cause the underlying cursor to be invalidated and return 787 // unexpected keys and/or values. 788 // 789 // Returns the following errors as required by the interface contract: 790 // - ErrTxClosed if the transaction has already been closed 791 // 792 // NOTE: The values returned by this function are only valid during a 793 // transaction. Attempting to access them after a transaction has ended will 794 // likely result in an access violation. 795 // 796 // This function is part of the database.Bucket interface implementation. 797 func (b *bucket) ForEach(fn func(k, v []byte) error) error { 798 // Ensure transaction state is valid. 799 if err := b.tx.checkClosed(); err != nil { 800 return err 801 } 802 803 // Invoke the callback for each cursor item. Return the error returned 804 // from the callback when it is non-nil. 805 c := newCursor(b, b.id[:], ctKeys) 806 defer cursorFinalizer(c) 807 for ok := c.First(); ok; ok = c.Next() { 808 err := fn(c.Key(), c.Value()) 809 if err != nil { 810 return err 811 } 812 } 813 814 return nil 815 } 816 817 // ForEachBucket invokes the passed function with the key of every nested bucket 818 // in the current bucket. This does not include any nested buckets within those 819 // nested buckets. 820 // 821 // WARNING: It is not safe to mutate data while iterating with this method. 822 // Doing so may cause the underlying cursor to be invalidated and return 823 // unexpected keys. 824 // 825 // Returns the following errors as required by the interface contract: 826 // - ErrTxClosed if the transaction has already been closed 827 // 828 // NOTE: The values returned by this function are only valid during a 829 // transaction. Attempting to access them after a transaction has ended will 830 // likely result in an access violation. 831 // 832 // This function is part of the database.Bucket interface implementation. 833 func (b *bucket) ForEachBucket(fn func(k []byte) error) error { 834 // Ensure transaction state is valid. 835 if err := b.tx.checkClosed(); err != nil { 836 return err 837 } 838 839 // Invoke the callback for each cursor item. Return the error returned 840 // from the callback when it is non-nil. 841 c := newCursor(b, b.id[:], ctBuckets) 842 defer cursorFinalizer(c) 843 for ok := c.First(); ok; ok = c.Next() { 844 err := fn(c.Key()) 845 if err != nil { 846 return err 847 } 848 } 849 850 return nil 851 } 852 853 // Writable returns whether or not the bucket is writable. 854 // 855 // This function is part of the database.Bucket interface implementation. 856 func (b *bucket) Writable() bool { 857 return b.tx.writable 858 } 859 860 // Put saves the specified key/value pair to the bucket. Keys that do not 861 // already exist are added and keys that already exist are overwritten. 862 // 863 // Returns the following errors as required by the interface contract: 864 // - ErrKeyRequired if the key is empty 865 // - ErrIncompatibleValue if the key is the same as an existing bucket 866 // - ErrTxNotWritable if attempted against a read-only transaction 867 // - ErrTxClosed if the transaction has already been closed 868 // 869 // This function is part of the database.Bucket interface implementation. 870 func (b *bucket) Put(key, value []byte) error { 871 // Ensure transaction state is valid. 872 if err := b.tx.checkClosed(); err != nil { 873 return err 874 } 875 876 // Ensure the transaction is writable. 877 if !b.tx.writable { 878 str := "setting a key requires a writable database transaction" 879 return makeDbErr(database.ErrTxNotWritable, str, nil) 880 } 881 882 // Ensure a key was provided. 883 if len(key) == 0 { 884 str := "put requires a key" 885 return makeDbErr(database.ErrKeyRequired, str, nil) 886 } 887 888 return b.tx.putKey(bucketizedKey(b.id, key), value) 889 } 890 891 // Get returns the value for the given key. Returns nil if the key does not 892 // exist in this bucket. An empty slice is returned for keys that exist but 893 // have no value assigned. 894 // 895 // NOTE: The value returned by this function is only valid during a transaction. 896 // Attempting to access it after a transaction has ended results in undefined 897 // behavior. Additionally, the value must NOT be modified by the caller. 898 // 899 // This function is part of the database.Bucket interface implementation. 900 func (b *bucket) Get(key []byte) []byte { 901 // Ensure transaction state is valid. 902 if err := b.tx.checkClosed(); err != nil { 903 return nil 904 } 905 906 // Nothing to return if there is no key. 907 if len(key) == 0 { 908 return nil 909 } 910 911 return b.tx.fetchKey(bucketizedKey(b.id, key)) 912 } 913 914 // Delete removes the specified key from the bucket. Deleting a key that does 915 // not exist does not return an error. 916 // 917 // Returns the following errors as required by the interface contract: 918 // - ErrKeyRequired if the key is empty 919 // - ErrIncompatibleValue if the key is the same as an existing bucket 920 // - ErrTxNotWritable if attempted against a read-only transaction 921 // - ErrTxClosed if the transaction has already been closed 922 // 923 // This function is part of the database.Bucket interface implementation. 924 func (b *bucket) Delete(key []byte) error { 925 // Ensure transaction state is valid. 926 if err := b.tx.checkClosed(); err != nil { 927 return err 928 } 929 930 // Ensure the transaction is writable. 931 if !b.tx.writable { 932 str := "deleting a value requires a writable database transaction" 933 return makeDbErr(database.ErrTxNotWritable, str, nil) 934 } 935 936 // Nothing to do if there is no key. 937 if len(key) == 0 { 938 return nil 939 } 940 941 b.tx.deleteKey(bucketizedKey(b.id, key), true) 942 return nil 943 } 944 945 // pendingBlock houses a block that will be written to disk when the database 946 // transaction is committed. 947 type pendingBlock struct { 948 hash *chainhash.Hash 949 bytes []byte 950 } 951 952 // transaction represents a database transaction. It can either be read-only or 953 // read-write and implements the database.Tx interface. The transaction 954 // provides a root bucket against which all read and writes occur. 955 type transaction struct { 956 managed bool // Is the transaction managed? 957 closed bool // Is the transaction closed? 958 writable bool // Is the transaction writable? 959 db *db // DB instance the tx was created from. 960 snapshot *dbCacheSnapshot // Underlying snapshot for txns. 961 metaBucket *bucket // The root metadata bucket. 962 blockIdxBucket *bucket // The block index bucket. 963 964 // Blocks that need to be stored on commit. The pendingBlocks map is 965 // kept to allow quick lookups of pending data by block hash. 966 pendingBlocks map[chainhash.Hash]int 967 pendingBlockData []pendingBlock 968 969 // Files that need to be deleted on commit. These are the files that 970 // are marked as files to be deleted during pruning. 971 pendingDelFileNums []uint32 972 973 // Keys that need to be stored or deleted on commit. 974 pendingKeys *treap.Mutable 975 pendingRemove *treap.Mutable 976 977 // Active iterators that need to be notified when the pending keys have 978 // been updated so the cursors can properly handle updates to the 979 // transaction state. 980 activeIterLock sync.RWMutex 981 activeIters []*treap.Iterator 982 } 983 984 // Enforce transaction implements the database.Tx interface. 985 var _ database.Tx = (*transaction)(nil) 986 987 // removeActiveIter removes the passed iterator from the list of active 988 // iterators against the pending keys treap. 989 func (tx *transaction) removeActiveIter(iter *treap.Iterator) { 990 // An indexing for loop is intentionally used over a range here as range 991 // does not reevaluate the slice on each iteration nor does it adjust 992 // the index for the modified slice. 993 tx.activeIterLock.Lock() 994 for i := 0; i < len(tx.activeIters); i++ { 995 if tx.activeIters[i] == iter { 996 copy(tx.activeIters[i:], tx.activeIters[i+1:]) 997 tx.activeIters[len(tx.activeIters)-1] = nil 998 tx.activeIters = tx.activeIters[:len(tx.activeIters)-1] 999 } 1000 } 1001 tx.activeIterLock.Unlock() 1002 } 1003 1004 // addActiveIter adds the passed iterator to the list of active iterators for 1005 // the pending keys treap. 1006 func (tx *transaction) addActiveIter(iter *treap.Iterator) { 1007 tx.activeIterLock.Lock() 1008 tx.activeIters = append(tx.activeIters, iter) 1009 tx.activeIterLock.Unlock() 1010 } 1011 1012 // notifyActiveIters notifies all of the active iterators for the pending keys 1013 // treap that it has been updated. 1014 func (tx *transaction) notifyActiveIters() { 1015 tx.activeIterLock.RLock() 1016 for _, iter := range tx.activeIters { 1017 iter.ForceReseek() 1018 } 1019 tx.activeIterLock.RUnlock() 1020 } 1021 1022 // checkClosed returns an error if the database or transaction is closed. 1023 func (tx *transaction) checkClosed() error { 1024 // The transaction is no longer valid if it has been closed. 1025 if tx.closed { 1026 return makeDbErr(database.ErrTxClosed, errTxClosedStr, nil) 1027 } 1028 1029 return nil 1030 } 1031 1032 // hasKey returns whether or not the provided key exists in the database while 1033 // taking into account the current transaction state. 1034 func (tx *transaction) hasKey(key []byte) bool { 1035 // When the transaction is writable, check the pending transaction 1036 // state first. 1037 if tx.writable { 1038 if tx.pendingRemove.Has(key) { 1039 return false 1040 } 1041 if tx.pendingKeys.Has(key) { 1042 return true 1043 } 1044 } 1045 1046 // Consult the database cache and underlying database. 1047 return tx.snapshot.Has(key) 1048 } 1049 1050 // putKey adds the provided key to the list of keys to be updated in the 1051 // database when the transaction is committed. 1052 // 1053 // NOTE: This function must only be called on a writable transaction. Since it 1054 // is an internal helper function, it does not check. 1055 func (tx *transaction) putKey(key, value []byte) error { 1056 // Prevent the key from being deleted if it was previously scheduled 1057 // to be deleted on transaction commit. 1058 tx.pendingRemove.Delete(key) 1059 1060 // Add the key/value pair to the list to be written on transaction 1061 // commit. 1062 tx.pendingKeys.Put(key, value) 1063 tx.notifyActiveIters() 1064 return nil 1065 } 1066 1067 // fetchKey attempts to fetch the provided key from the database cache (and 1068 // hence underlying database) while taking into account the current transaction 1069 // state. Returns nil if the key does not exist. 1070 func (tx *transaction) fetchKey(key []byte) []byte { 1071 // When the transaction is writable, check the pending transaction 1072 // state first. 1073 if tx.writable { 1074 if tx.pendingRemove.Has(key) { 1075 return nil 1076 } 1077 if value := tx.pendingKeys.Get(key); value != nil { 1078 return value 1079 } 1080 } 1081 1082 // Consult the database cache and underlying database. 1083 return tx.snapshot.Get(key) 1084 } 1085 1086 // deleteKey adds the provided key to the list of keys to be deleted from the 1087 // database when the transaction is committed. The notify iterators flag is 1088 // useful to delay notifying iterators about the changes during bulk deletes. 1089 // 1090 // NOTE: This function must only be called on a writable transaction. Since it 1091 // is an internal helper function, it does not check. 1092 func (tx *transaction) deleteKey(key []byte, notifyIterators bool) { 1093 // Remove the key from the list of pendings keys to be written on 1094 // transaction commit if needed. 1095 tx.pendingKeys.Delete(key) 1096 1097 // Add the key to the list to be deleted on transaction commit. 1098 tx.pendingRemove.Put(key, nil) 1099 1100 // Notify the active iterators about the change if the flag is set. 1101 if notifyIterators { 1102 tx.notifyActiveIters() 1103 } 1104 } 1105 1106 // nextBucketID returns the next bucket ID to use for creating a new bucket. 1107 // 1108 // NOTE: This function must only be called on a writable transaction. Since it 1109 // is an internal helper function, it does not check. 1110 func (tx *transaction) nextBucketID() ([4]byte, error) { 1111 // Load the currently highest used bucket ID. 1112 curIDBytes := tx.fetchKey(curBucketIDKeyName) 1113 curBucketNum := binary.BigEndian.Uint32(curIDBytes) 1114 1115 // Increment and update the current bucket ID and return it. 1116 var nextBucketID [4]byte 1117 binary.BigEndian.PutUint32(nextBucketID[:], curBucketNum+1) 1118 if err := tx.putKey(curBucketIDKeyName, nextBucketID[:]); err != nil { 1119 return [4]byte{}, err 1120 } 1121 return nextBucketID, nil 1122 } 1123 1124 // Metadata returns the top-most bucket for all metadata storage. 1125 // 1126 // This function is part of the database.Tx interface implementation. 1127 func (tx *transaction) Metadata() database.Bucket { 1128 return tx.metaBucket 1129 } 1130 1131 // hasBlock returns whether or not a block with the given hash exists. 1132 func (tx *transaction) hasBlock(hash *chainhash.Hash) bool { 1133 // Return true if the block is pending to be written on commit since 1134 // it exists from the viewpoint of this transaction. 1135 if _, exists := tx.pendingBlocks[*hash]; exists { 1136 return true 1137 } 1138 1139 return tx.hasKey(bucketizedKey(blockIdxBucketID, hash[:])) 1140 } 1141 1142 // StoreBlock stores the provided block into the database. There are no checks 1143 // to ensure the block connects to a previous block, contains double spends, or 1144 // any additional functionality such as transaction indexing. It simply stores 1145 // the block in the database. 1146 // 1147 // Returns the following errors as required by the interface contract: 1148 // - ErrBlockExists when the block hash already exists 1149 // - ErrTxNotWritable if attempted against a read-only transaction 1150 // - ErrTxClosed if the transaction has already been closed 1151 // 1152 // This function is part of the database.Tx interface implementation. 1153 func (tx *transaction) StoreBlock(block *btcutil.Block) error { 1154 // Ensure transaction state is valid. 1155 if err := tx.checkClosed(); err != nil { 1156 return err 1157 } 1158 1159 // Ensure the transaction is writable. 1160 if !tx.writable { 1161 str := "store block requires a writable database transaction" 1162 return makeDbErr(database.ErrTxNotWritable, str, nil) 1163 } 1164 1165 // Reject the block if it already exists. 1166 blockHash := block.Hash() 1167 if tx.hasBlock(blockHash) { 1168 str := fmt.Sprintf("block %s already exists", blockHash) 1169 return makeDbErr(database.ErrBlockExists, str, nil) 1170 } 1171 1172 blockBytes, err := block.Bytes() 1173 if err != nil { 1174 str := fmt.Sprintf("failed to get serialized bytes for block %s", 1175 blockHash) 1176 return makeDbErr(database.ErrDriverSpecific, str, err) 1177 } 1178 1179 // Add the block to be stored to the list of pending blocks to store 1180 // when the transaction is committed. Also, add it to pending blocks 1181 // map so it is easy to determine the block is pending based on the 1182 // block hash. 1183 if tx.pendingBlocks == nil { 1184 tx.pendingBlocks = make(map[chainhash.Hash]int) 1185 } 1186 tx.pendingBlocks[*blockHash] = len(tx.pendingBlockData) 1187 tx.pendingBlockData = append(tx.pendingBlockData, pendingBlock{ 1188 hash: blockHash, 1189 bytes: blockBytes, 1190 }) 1191 log.Tracef("Added block %s to pending blocks", blockHash) 1192 1193 return nil 1194 } 1195 1196 // HasBlock returns whether or not a block with the given hash exists in the 1197 // database. 1198 // 1199 // Returns the following errors as required by the interface contract: 1200 // - ErrTxClosed if the transaction has already been closed 1201 // 1202 // This function is part of the database.Tx interface implementation. 1203 func (tx *transaction) HasBlock(hash *chainhash.Hash) (bool, error) { 1204 // Ensure transaction state is valid. 1205 if err := tx.checkClosed(); err != nil { 1206 return false, err 1207 } 1208 1209 return tx.hasBlock(hash), nil 1210 } 1211 1212 // HasBlocks returns whether or not the blocks with the provided hashes 1213 // exist in the database. 1214 // 1215 // Returns the following errors as required by the interface contract: 1216 // - ErrTxClosed if the transaction has already been closed 1217 // 1218 // This function is part of the database.Tx interface implementation. 1219 func (tx *transaction) HasBlocks(hashes []chainhash.Hash) ([]bool, error) { 1220 // Ensure transaction state is valid. 1221 if err := tx.checkClosed(); err != nil { 1222 return nil, err 1223 } 1224 1225 results := make([]bool, len(hashes)) 1226 for i := range hashes { 1227 results[i] = tx.hasBlock(&hashes[i]) 1228 } 1229 1230 return results, nil 1231 } 1232 1233 // fetchBlockRow fetches the metadata stored in the block index for the provided 1234 // hash. It will return ErrBlockNotFound if there is no entry. 1235 func (tx *transaction) fetchBlockRow(hash *chainhash.Hash) ([]byte, error) { 1236 blockRow := tx.blockIdxBucket.Get(hash[:]) 1237 if blockRow == nil { 1238 str := fmt.Sprintf("block %s does not exist", hash) 1239 return nil, makeDbErr(database.ErrBlockNotFound, str, nil) 1240 } 1241 1242 return blockRow, nil 1243 } 1244 1245 // FetchBlockHeader returns the raw serialized bytes for the block header 1246 // identified by the given hash. The raw bytes are in the format returned by 1247 // Serialize on a wire.BlockHeader. 1248 // 1249 // Returns the following errors as required by the interface contract: 1250 // - ErrBlockNotFound if the requested block hash does not exist 1251 // - ErrTxClosed if the transaction has already been closed 1252 // - ErrCorruption if the database has somehow become corrupted 1253 // 1254 // NOTE: The data returned by this function is only valid during a 1255 // database transaction. Attempting to access it after a transaction 1256 // has ended results in undefined behavior. This constraint prevents 1257 // additional data copies and allows support for memory-mapped database 1258 // implementations. 1259 // 1260 // This function is part of the database.Tx interface implementation. 1261 func (tx *transaction) FetchBlockHeader(hash *chainhash.Hash) ([]byte, error) { 1262 return tx.FetchBlockRegion(&database.BlockRegion{ 1263 Hash: hash, 1264 Offset: 0, 1265 Len: blockHdrSize, 1266 }) 1267 } 1268 1269 // FetchBlockHeaders returns the raw serialized bytes for the block headers 1270 // identified by the given hashes. The raw bytes are in the format returned by 1271 // Serialize on a wire.BlockHeader. 1272 // 1273 // Returns the following errors as required by the interface contract: 1274 // - ErrBlockNotFound if the any of the requested block hashes do not exist 1275 // - ErrTxClosed if the transaction has already been closed 1276 // - ErrCorruption if the database has somehow become corrupted 1277 // 1278 // NOTE: The data returned by this function is only valid during a database 1279 // transaction. Attempting to access it after a transaction has ended results 1280 // in undefined behavior. This constraint prevents additional data copies and 1281 // allows support for memory-mapped database implementations. 1282 // 1283 // This function is part of the database.Tx interface implementation. 1284 func (tx *transaction) FetchBlockHeaders(hashes []chainhash.Hash) ([][]byte, error) { 1285 regions := make([]database.BlockRegion, len(hashes)) 1286 for i := range hashes { 1287 regions[i].Hash = &hashes[i] 1288 regions[i].Offset = 0 1289 regions[i].Len = blockHdrSize 1290 } 1291 return tx.FetchBlockRegions(regions) 1292 } 1293 1294 // FetchBlock returns the raw serialized bytes for the block identified by the 1295 // given hash. The raw bytes are in the format returned by Serialize on a 1296 // wire.MsgBlock. 1297 // 1298 // Returns the following errors as required by the interface contract: 1299 // - ErrBlockNotFound if the requested block hash does not exist 1300 // - ErrTxClosed if the transaction has already been closed 1301 // - ErrCorruption if the database has somehow become corrupted 1302 // 1303 // In addition, returns ErrDriverSpecific if any failures occur when reading the 1304 // block files. 1305 // 1306 // NOTE: The data returned by this function is only valid during a database 1307 // transaction. Attempting to access it after a transaction has ended results 1308 // in undefined behavior. This constraint prevents additional data copies and 1309 // allows support for memory-mapped database implementations. 1310 // 1311 // This function is part of the database.Tx interface implementation. 1312 func (tx *transaction) FetchBlock(hash *chainhash.Hash) ([]byte, error) { 1313 // Ensure transaction state is valid. 1314 if err := tx.checkClosed(); err != nil { 1315 return nil, err 1316 } 1317 1318 // When the block is pending to be written on commit return the bytes 1319 // from there. 1320 if idx, exists := tx.pendingBlocks[*hash]; exists { 1321 return tx.pendingBlockData[idx].bytes, nil 1322 } 1323 1324 // Lookup the location of the block in the files from the block index. 1325 blockRow, err := tx.fetchBlockRow(hash) 1326 if err != nil { 1327 return nil, err 1328 } 1329 location := deserializeBlockLoc(blockRow) 1330 1331 // Read the block from the appropriate location. The function also 1332 // performs a checksum over the data to detect data corruption. 1333 blockBytes, err := tx.db.store.readBlock(hash, location) 1334 if err != nil { 1335 return nil, err 1336 } 1337 1338 return blockBytes, nil 1339 } 1340 1341 // FetchBlocks returns the raw serialized bytes for the blocks identified by the 1342 // given hashes. The raw bytes are in the format returned by Serialize on a 1343 // wire.MsgBlock. 1344 // 1345 // Returns the following errors as required by the interface contract: 1346 // - ErrBlockNotFound if any of the requested block hashed do not exist 1347 // - ErrTxClosed if the transaction has already been closed 1348 // - ErrCorruption if the database has somehow become corrupted 1349 // 1350 // In addition, returns ErrDriverSpecific if any failures occur when reading the 1351 // block files. 1352 // 1353 // NOTE: The data returned by this function is only valid during a database 1354 // transaction. Attempting to access it after a transaction has ended results 1355 // in undefined behavior. This constraint prevents additional data copies and 1356 // allows support for memory-mapped database implementations. 1357 // 1358 // This function is part of the database.Tx interface implementation. 1359 func (tx *transaction) FetchBlocks(hashes []chainhash.Hash) ([][]byte, error) { 1360 // Ensure transaction state is valid. 1361 if err := tx.checkClosed(); err != nil { 1362 return nil, err 1363 } 1364 1365 // NOTE: This could check for the existence of all blocks before loading 1366 // any of them which would be faster in the failure case, however 1367 // callers will not typically be calling this function with invalid 1368 // values, so optimize for the common case. 1369 1370 // Load the blocks. 1371 blocks := make([][]byte, len(hashes)) 1372 for i := range hashes { 1373 var err error 1374 blocks[i], err = tx.FetchBlock(&hashes[i]) 1375 if err != nil { 1376 return nil, err 1377 } 1378 } 1379 1380 return blocks, nil 1381 } 1382 1383 // fetchPendingRegion attempts to fetch the provided region from any block which 1384 // are pending to be written on commit. It will return nil for the byte slice 1385 // when the region references a block which is not pending. When the region 1386 // does reference a pending block, it is bounds checked and returns 1387 // ErrBlockRegionInvalid if invalid. 1388 func (tx *transaction) fetchPendingRegion(region *database.BlockRegion) ([]byte, error) { 1389 // Nothing to do if the block is not pending to be written on commit. 1390 idx, exists := tx.pendingBlocks[*region.Hash] 1391 if !exists { 1392 return nil, nil 1393 } 1394 1395 // Ensure the region is within the bounds of the block. 1396 blockBytes := tx.pendingBlockData[idx].bytes 1397 blockLen := uint32(len(blockBytes)) 1398 endOffset := region.Offset + region.Len 1399 if endOffset < region.Offset || endOffset > blockLen { 1400 str := fmt.Sprintf("block %s region offset %d, length %d "+ 1401 "exceeds block length of %d", region.Hash, 1402 region.Offset, region.Len, blockLen) 1403 return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil) 1404 } 1405 1406 // Return the bytes from the pending block. 1407 return blockBytes[region.Offset:endOffset:endOffset], nil 1408 } 1409 1410 // FetchBlockRegion returns the raw serialized bytes for the given block region. 1411 // 1412 // For example, it is possible to directly extract Bitcoin transactions and/or 1413 // scripts from a block with this function. Depending on the backend 1414 // implementation, this can provide significant savings by avoiding the need to 1415 // load entire blocks. 1416 // 1417 // The raw bytes are in the format returned by Serialize on a wire.MsgBlock and 1418 // the Offset field in the provided BlockRegion is zero-based and relative to 1419 // the start of the block (byte 0). 1420 // 1421 // Returns the following errors as required by the interface contract: 1422 // - ErrBlockNotFound if the requested block hash does not exist 1423 // - ErrBlockRegionInvalid if the region exceeds the bounds of the associated 1424 // block 1425 // - ErrTxClosed if the transaction has already been closed 1426 // - ErrCorruption if the database has somehow become corrupted 1427 // 1428 // In addition, returns ErrDriverSpecific if any failures occur when reading the 1429 // block files. 1430 // 1431 // NOTE: The data returned by this function is only valid during a database 1432 // transaction. Attempting to access it after a transaction has ended results 1433 // in undefined behavior. This constraint prevents additional data copies and 1434 // allows support for memory-mapped database implementations. 1435 // 1436 // This function is part of the database.Tx interface implementation. 1437 func (tx *transaction) FetchBlockRegion(region *database.BlockRegion) ([]byte, error) { 1438 // Ensure transaction state is valid. 1439 if err := tx.checkClosed(); err != nil { 1440 return nil, err 1441 } 1442 1443 // When the block is pending to be written on commit return the bytes 1444 // from there. 1445 if tx.pendingBlocks != nil { 1446 regionBytes, err := tx.fetchPendingRegion(region) 1447 if err != nil { 1448 return nil, err 1449 } 1450 if regionBytes != nil { 1451 return regionBytes, nil 1452 } 1453 } 1454 1455 // Lookup the location of the block in the files from the block index. 1456 blockRow, err := tx.fetchBlockRow(region.Hash) 1457 if err != nil { 1458 return nil, err 1459 } 1460 location := deserializeBlockLoc(blockRow) 1461 1462 // Ensure the region is within the bounds of the block. 1463 endOffset := region.Offset + region.Len 1464 if endOffset < region.Offset || endOffset > location.blockLen { 1465 str := fmt.Sprintf("block %s region offset %d, length %d "+ 1466 "exceeds block length of %d", region.Hash, 1467 region.Offset, region.Len, location.blockLen) 1468 return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil) 1469 1470 } 1471 1472 // Read the region from the appropriate disk block file. 1473 regionBytes, err := tx.db.store.readBlockRegion(location, region.Offset, 1474 region.Len) 1475 if err != nil { 1476 return nil, err 1477 } 1478 1479 return regionBytes, nil 1480 } 1481 1482 // FetchBlockRegions returns the raw serialized bytes for the given block 1483 // regions. 1484 // 1485 // For example, it is possible to directly extract Bitcoin transactions and/or 1486 // scripts from various blocks with this function. Depending on the backend 1487 // implementation, this can provide significant savings by avoiding the need to 1488 // load entire blocks. 1489 // 1490 // The raw bytes are in the format returned by Serialize on a wire.MsgBlock and 1491 // the Offset fields in the provided BlockRegions are zero-based and relative to 1492 // the start of the block (byte 0). 1493 // 1494 // Returns the following errors as required by the interface contract: 1495 // - ErrBlockNotFound if any of the request block hashes do not exist 1496 // - ErrBlockRegionInvalid if one or more region exceed the bounds of the 1497 // associated block 1498 // - ErrTxClosed if the transaction has already been closed 1499 // - ErrCorruption if the database has somehow become corrupted 1500 // 1501 // In addition, returns ErrDriverSpecific if any failures occur when reading the 1502 // block files. 1503 // 1504 // NOTE: The data returned by this function is only valid during a database 1505 // transaction. Attempting to access it after a transaction has ended results 1506 // in undefined behavior. This constraint prevents additional data copies and 1507 // allows support for memory-mapped database implementations. 1508 // 1509 // This function is part of the database.Tx interface implementation. 1510 func (tx *transaction) FetchBlockRegions(regions []database.BlockRegion) ([][]byte, error) { 1511 // Ensure transaction state is valid. 1512 if err := tx.checkClosed(); err != nil { 1513 return nil, err 1514 } 1515 1516 // NOTE: This could check for the existence of all blocks before 1517 // deserializing the locations and building up the fetch list which 1518 // would be faster in the failure case, however callers will not 1519 // typically be calling this function with invalid values, so optimize 1520 // for the common case. 1521 1522 // NOTE: A potential optimization here would be to combine adjacent 1523 // regions to reduce the number of reads. 1524 1525 // In order to improve efficiency of loading the bulk data, first grab 1526 // the block location for all of the requested block hashes and sort 1527 // the reads by filenum:offset so that all reads are grouped by file 1528 // and linear within each file. This can result in quite a significant 1529 // performance increase depending on how spread out the requested hashes 1530 // are by reducing the number of file open/closes and random accesses 1531 // needed. The fetchList is intentionally allocated with a cap because 1532 // some of the regions might be fetched from the pending blocks and 1533 // hence there is no need to fetch those from disk. 1534 blockRegions := make([][]byte, len(regions)) 1535 fetchList := make([]bulkFetchData, 0, len(regions)) 1536 for i := range regions { 1537 region := ®ions[i] 1538 1539 // When the block is pending to be written on commit grab the 1540 // bytes from there. 1541 if tx.pendingBlocks != nil { 1542 regionBytes, err := tx.fetchPendingRegion(region) 1543 if err != nil { 1544 return nil, err 1545 } 1546 if regionBytes != nil { 1547 blockRegions[i] = regionBytes 1548 continue 1549 } 1550 } 1551 1552 // Lookup the location of the block in the files from the block 1553 // index. 1554 blockRow, err := tx.fetchBlockRow(region.Hash) 1555 if err != nil { 1556 return nil, err 1557 } 1558 location := deserializeBlockLoc(blockRow) 1559 1560 // Ensure the region is within the bounds of the block. 1561 endOffset := region.Offset + region.Len 1562 if endOffset < region.Offset || endOffset > location.blockLen { 1563 str := fmt.Sprintf("block %s region offset %d, length "+ 1564 "%d exceeds block length of %d", region.Hash, 1565 region.Offset, region.Len, location.blockLen) 1566 return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil) 1567 } 1568 1569 fetchList = append(fetchList, bulkFetchData{&location, i}) 1570 } 1571 sort.Sort(bulkFetchDataSorter(fetchList)) 1572 1573 // Read all of the regions in the fetch list and set the results. 1574 for i := range fetchList { 1575 fetchData := &fetchList[i] 1576 ri := fetchData.replyIndex 1577 region := ®ions[ri] 1578 location := fetchData.blockLocation 1579 regionBytes, err := tx.db.store.readBlockRegion(*location, 1580 region.Offset, region.Len) 1581 if err != nil { 1582 return nil, err 1583 } 1584 blockRegions[ri] = regionBytes 1585 } 1586 1587 return blockRegions, nil 1588 } 1589 1590 // close marks the transaction closed then releases any pending data, the 1591 // underlying snapshot, the transaction read lock, and the write lock when the 1592 // transaction is writable. 1593 func (tx *transaction) close() { 1594 tx.closed = true 1595 1596 // Clear pending blocks that would have been written on commit. 1597 tx.pendingBlocks = nil 1598 tx.pendingBlockData = nil 1599 1600 // Clear pending file deletions. 1601 tx.pendingDelFileNums = nil 1602 1603 // Clear pending keys that would have been written or deleted on commit. 1604 tx.pendingKeys = nil 1605 tx.pendingRemove = nil 1606 1607 // Release the snapshot. 1608 if tx.snapshot != nil { 1609 tx.snapshot.Release() 1610 tx.snapshot = nil 1611 } 1612 1613 tx.db.closeLock.RUnlock() 1614 1615 // Release the writer lock for writable transactions to unblock any 1616 // other write transaction which are possibly waiting. 1617 if tx.writable { 1618 tx.db.writeLock.Unlock() 1619 } 1620 } 1621 1622 // writePendingAndCommit writes pending block data to the flat block files, 1623 // updates the metadata with their locations as well as the new current write 1624 // location, and commits the metadata to the memory database cache. It also 1625 // properly handles rollback in the case of failures. 1626 // 1627 // This function MUST only be called when there is pending data to be written. 1628 func (tx *transaction) writePendingAndCommit() error { 1629 // Loop through all the pending file deletions and delete them. 1630 // We do this first before doing any of the writes as we can't undo 1631 // deletions of files. 1632 for _, fileNum := range tx.pendingDelFileNums { 1633 err := tx.db.store.deleteFileFunc(fileNum) 1634 if err != nil { 1635 // Nothing we can do if we fail to delete blocks besides 1636 // return an error. 1637 return err 1638 } 1639 } 1640 1641 // Save the current block store write position for potential rollback. 1642 // These variables are only updated here in this function and there can 1643 // only be one write transaction active at a time, so it's safe to store 1644 // them for potential rollback. 1645 wc := tx.db.store.writeCursor 1646 wc.RLock() 1647 oldBlkFileNum := wc.curFileNum 1648 oldBlkOffset := wc.curOffset 1649 wc.RUnlock() 1650 1651 // rollback is a closure that is used to rollback all writes to the 1652 // block files. 1653 rollback := func() { 1654 // Rollback any modifications made to the block files if needed. 1655 tx.db.store.handleRollback(oldBlkFileNum, oldBlkOffset) 1656 } 1657 1658 // Loop through all of the pending blocks to store and write them. 1659 for _, blockData := range tx.pendingBlockData { 1660 log.Tracef("Storing block %s", blockData.hash) 1661 location, err := tx.db.store.writeBlock(blockData.bytes) 1662 if err != nil { 1663 rollback() 1664 return err 1665 } 1666 1667 // Add a record in the block index for the block. The record 1668 // includes the location information needed to locate the block 1669 // on the filesystem as well as the block header since they are 1670 // so commonly needed. 1671 blockRow := serializeBlockLoc(location) 1672 err = tx.blockIdxBucket.Put(blockData.hash[:], blockRow) 1673 if err != nil { 1674 rollback() 1675 return err 1676 } 1677 } 1678 1679 // Update the metadata for the current write file and offset. 1680 writeRow := serializeWriteRow(wc.curFileNum, wc.curOffset) 1681 if err := tx.metaBucket.Put(writeLocKeyName, writeRow); err != nil { 1682 rollback() 1683 return convertErr("failed to store write cursor", err) 1684 } 1685 1686 // Atomically update the database cache. The cache automatically 1687 // handles flushing to the underlying persistent storage database. 1688 return tx.db.cache.commitTx(tx) 1689 } 1690 1691 // PruneBlocks deletes the block files until it reaches the target size 1692 // (specified in bytes). Throws an error if the target size is below 1693 // the maximum size of a single block file. 1694 // 1695 // This function is part of the database.Tx interface implementation. 1696 func (tx *transaction) PruneBlocks(targetSize uint64) ([]chainhash.Hash, error) { 1697 // Ensure transaction state is valid. 1698 if err := tx.checkClosed(); err != nil { 1699 return nil, err 1700 } 1701 1702 // Ensure the transaction is writable. 1703 if !tx.writable { 1704 str := "prune blocks requires a writable database transaction" 1705 return nil, makeDbErr(database.ErrTxNotWritable, str, nil) 1706 } 1707 1708 // Make a local alias for the maxBlockFileSize. 1709 maxSize := uint64(tx.db.store.maxBlockFileSize) 1710 if targetSize < maxSize { 1711 return nil, fmt.Errorf("got target size of %d but it must be greater "+ 1712 "than %d, the max size of a single block file", 1713 targetSize, maxSize) 1714 } 1715 1716 first, last, lastFileSize, err := scanBlockFiles(tx.db.store.basePath) 1717 if err != nil { 1718 return nil, err 1719 } 1720 1721 // If we have no files on disk or just a single file on disk, return early. 1722 if first == last { 1723 return nil, nil 1724 } 1725 1726 // Last file number minus the first file number gives us the count of files 1727 // on disk minus 1. We don't want to count the last file since we can't assume 1728 // that it is of max size. 1729 maxSizeFileCount := last - first 1730 1731 // If the total size of block files are under the target, return early and 1732 // don't prune. 1733 totalSize := uint64(lastFileSize) + (maxSize * uint64(maxSizeFileCount)) 1734 if totalSize <= targetSize { 1735 return nil, nil 1736 } 1737 1738 log.Tracef("Using %d more bytes than the target of %d MiB. Pruning files...", 1739 totalSize-targetSize, 1740 targetSize/(1024*1024)) 1741 1742 deletedFiles := make(map[uint32]struct{}) 1743 1744 // We use < not <= so that the last file is never deleted. There are other checks in place 1745 // but setting it to < here doesn't hurt. 1746 for i := uint32(first); i < uint32(last); i++ { 1747 // Add the block file to be deleted to the list of files pending deletion to 1748 // delete when the transaction is committed. 1749 if tx.pendingDelFileNums == nil { 1750 tx.pendingDelFileNums = make([]uint32, 0, 1) 1751 } 1752 tx.pendingDelFileNums = append(tx.pendingDelFileNums, i) 1753 1754 // Add the file index to the deleted files map so that we can later 1755 // delete the block location index. 1756 deletedFiles[i] = struct{}{} 1757 1758 // If we're already at or below the target usage, break and don't 1759 // try to delete more files. 1760 totalSize -= maxSize 1761 if totalSize <= targetSize { 1762 break 1763 } 1764 } 1765 1766 // Delete the indexed block locations for the files that we've just deleted. 1767 var deletedBlockHashes []chainhash.Hash 1768 cursor := tx.blockIdxBucket.Cursor() 1769 for ok := cursor.First(); ok; ok = cursor.Next() { 1770 loc := deserializeBlockLoc(cursor.Value()) 1771 1772 _, found := deletedFiles[loc.blockFileNum] 1773 if found { 1774 deletedBlockHashes = append(deletedBlockHashes, *(*chainhash.Hash)(cursor.Key())) 1775 err := cursor.Delete() 1776 if err != nil { 1777 return nil, err 1778 } 1779 } 1780 } 1781 1782 log.Tracef("Finished pruning. Database now at %d bytes", totalSize) 1783 1784 return deletedBlockHashes, nil 1785 } 1786 1787 // BeenPruned returns if the block storage has ever been pruned. 1788 // 1789 // This function is part of the database.Tx interface implementation. 1790 func (tx *transaction) BeenPruned() (bool, error) { 1791 first, last, _, err := scanBlockFiles(tx.db.store.basePath) 1792 if err != nil { 1793 return false, err 1794 } 1795 1796 // If the database is pruned, then the first .fdb will not be there. 1797 // We also check that there isn't just 1 file on disk or if there are 1798 // no files on disk by checking if first != last. 1799 return first != 0 && (first != last), nil 1800 } 1801 1802 // Commit commits all changes that have been made to the root metadata bucket 1803 // and all of its sub-buckets to the database cache which is periodically synced 1804 // to persistent storage. In addition, it commits all new blocks directly to 1805 // persistent storage bypassing the db cache. Blocks can be rather large, so 1806 // this help increase the amount of cache available for the metadata updates and 1807 // is safe since blocks are immutable. 1808 // 1809 // This function is part of the database.Tx interface implementation. 1810 func (tx *transaction) Commit() error { 1811 // Prevent commits on managed transactions. 1812 if tx.managed { 1813 tx.close() 1814 panic("managed transaction commit not allowed") 1815 } 1816 1817 // Ensure transaction state is valid. 1818 if err := tx.checkClosed(); err != nil { 1819 return err 1820 } 1821 1822 // Regardless of whether the commit succeeds, the transaction is closed 1823 // on return. 1824 defer tx.close() 1825 1826 // Ensure the transaction is writable. 1827 if !tx.writable { 1828 str := "Commit requires a writable database transaction" 1829 return makeDbErr(database.ErrTxNotWritable, str, nil) 1830 } 1831 1832 // Write pending data. The function will rollback if any errors occur. 1833 return tx.writePendingAndCommit() 1834 } 1835 1836 // Rollback undoes all changes that have been made to the root bucket and all of 1837 // its sub-buckets. 1838 // 1839 // This function is part of the database.Tx interface implementation. 1840 func (tx *transaction) Rollback() error { 1841 // Prevent rollbacks on managed transactions. 1842 if tx.managed { 1843 tx.close() 1844 panic("managed transaction rollback not allowed") 1845 } 1846 1847 // Ensure transaction state is valid. 1848 if err := tx.checkClosed(); err != nil { 1849 return err 1850 } 1851 1852 tx.close() 1853 return nil 1854 } 1855 1856 // db represents a collection of namespaces which are persisted and implements 1857 // the database.DB interface. All database access is performed through 1858 // transactions which are obtained through the specific Namespace. 1859 type db struct { 1860 writeLock sync.Mutex // Limit to one write transaction at a time. 1861 closeLock sync.RWMutex // Make database close block while txns active. 1862 closed bool // Is the database closed? 1863 store *blockStore // Handles read/writing blocks to flat files. 1864 cache *dbCache // Cache layer which wraps underlying leveldb DB. 1865 } 1866 1867 // Enforce db implements the database.DB interface. 1868 var _ database.DB = (*db)(nil) 1869 1870 // Type returns the database driver type the current database instance was 1871 // created with. 1872 // 1873 // This function is part of the database.DB interface implementation. 1874 func (db *db) Type() string { 1875 return dbType 1876 } 1877 1878 // begin is the implementation function for the Begin database method. See its 1879 // documentation for more details. 1880 // 1881 // This function is only separate because it returns the internal transaction 1882 // which is used by the managed transaction code while the database method 1883 // returns the interface. 1884 func (db *db) begin(writable bool) (*transaction, error) { 1885 // Whenever a new writable transaction is started, grab the write lock 1886 // to ensure only a single write transaction can be active at the same 1887 // time. This lock will not be released until the transaction is 1888 // closed (via Rollback or Commit). 1889 if writable { 1890 db.writeLock.Lock() 1891 } 1892 1893 // Whenever a new transaction is started, grab a read lock against the 1894 // database to ensure Close will wait for the transaction to finish. 1895 // This lock will not be released until the transaction is closed (via 1896 // Rollback or Commit). 1897 db.closeLock.RLock() 1898 if db.closed { 1899 db.closeLock.RUnlock() 1900 if writable { 1901 db.writeLock.Unlock() 1902 } 1903 return nil, makeDbErr(database.ErrDbNotOpen, errDbNotOpenStr, 1904 nil) 1905 } 1906 1907 // Grab a snapshot of the database cache (which in turn also handles the 1908 // underlying database). 1909 snapshot, err := db.cache.Snapshot() 1910 if err != nil { 1911 db.closeLock.RUnlock() 1912 if writable { 1913 db.writeLock.Unlock() 1914 } 1915 1916 return nil, err 1917 } 1918 1919 // The metadata and block index buckets are internal-only buckets, so 1920 // they have defined IDs. 1921 tx := &transaction{ 1922 writable: writable, 1923 db: db, 1924 snapshot: snapshot, 1925 pendingKeys: treap.NewMutable(), 1926 pendingRemove: treap.NewMutable(), 1927 } 1928 tx.metaBucket = &bucket{tx: tx, id: metadataBucketID} 1929 tx.blockIdxBucket = &bucket{tx: tx, id: blockIdxBucketID} 1930 return tx, nil 1931 } 1932 1933 // Begin starts a transaction which is either read-only or read-write depending 1934 // on the specified flag. Multiple read-only transactions can be started 1935 // simultaneously while only a single read-write transaction can be started at a 1936 // time. The call will block when starting a read-write transaction when one is 1937 // already open. 1938 // 1939 // NOTE: The transaction must be closed by calling Rollback or Commit on it when 1940 // it is no longer needed. Failure to do so will result in unclaimed memory. 1941 // 1942 // This function is part of the database.DB interface implementation. 1943 func (db *db) Begin(writable bool) (database.Tx, error) { 1944 return db.begin(writable) 1945 } 1946 1947 // rollbackOnPanic rolls the passed transaction back if the code in the calling 1948 // function panics. This is needed since the mutex on a transaction must be 1949 // released and a panic in called code would prevent that from happening. 1950 // 1951 // NOTE: This can only be handled manually for managed transactions since they 1952 // control the life-cycle of the transaction. As the documentation on Begin 1953 // calls out, callers opting to use manual transactions will have to ensure the 1954 // transaction is rolled back on panic if it desires that functionality as well 1955 // or the database will fail to close since the read-lock will never be 1956 // released. 1957 func rollbackOnPanic(tx *transaction) { 1958 if err := recover(); err != nil { 1959 tx.managed = false 1960 _ = tx.Rollback() 1961 panic(err) 1962 } 1963 } 1964 1965 // View invokes the passed function in the context of a managed read-only 1966 // transaction with the root bucket for the namespace. Any errors returned from 1967 // the user-supplied function are returned from this function. 1968 // 1969 // This function is part of the database.DB interface implementation. 1970 func (db *db) View(fn func(database.Tx) error) error { 1971 // Start a read-only transaction. 1972 tx, err := db.begin(false) 1973 if err != nil { 1974 return err 1975 } 1976 1977 // Since the user-provided function might panic, ensure the transaction 1978 // releases all mutexes and resources. There is no guarantee the caller 1979 // won't use recover and keep going. Thus, the database must still be 1980 // in a usable state on panics due to caller issues. 1981 defer rollbackOnPanic(tx) 1982 1983 tx.managed = true 1984 err = fn(tx) 1985 tx.managed = false 1986 if err != nil { 1987 // The error is ignored here because nothing was written yet 1988 // and regardless of a rollback failure, the tx is closed now 1989 // anyways. 1990 _ = tx.Rollback() 1991 return err 1992 } 1993 1994 return tx.Rollback() 1995 } 1996 1997 // Update invokes the passed function in the context of a managed read-write 1998 // transaction with the root bucket for the namespace. Any errors returned from 1999 // the user-supplied function will cause the transaction to be rolled back and 2000 // are returned from this function. Otherwise, the transaction is committed 2001 // when the user-supplied function returns a nil error. 2002 // 2003 // This function is part of the database.DB interface implementation. 2004 func (db *db) Update(fn func(database.Tx) error) error { 2005 // Start a read-write transaction. 2006 tx, err := db.begin(true) 2007 if err != nil { 2008 return err 2009 } 2010 2011 // Since the user-provided function might panic, ensure the transaction 2012 // releases all mutexes and resources. There is no guarantee the caller 2013 // won't use recover and keep going. Thus, the database must still be 2014 // in a usable state on panics due to caller issues. 2015 defer rollbackOnPanic(tx) 2016 2017 tx.managed = true 2018 err = fn(tx) 2019 tx.managed = false 2020 if err != nil { 2021 // The error is ignored here because nothing was written yet 2022 // and regardless of a rollback failure, the tx is closed now 2023 // anyways. 2024 _ = tx.Rollback() 2025 return err 2026 } 2027 2028 return tx.Commit() 2029 } 2030 2031 // Close cleanly shuts down the database and syncs all data. It will block 2032 // until all database transactions have been finalized (rolled back or 2033 // committed). 2034 // 2035 // This function is part of the database.DB interface implementation. 2036 func (db *db) Close() error { 2037 // Since all transactions have a read lock on this mutex, this will 2038 // cause Close to wait for all readers to complete. 2039 db.closeLock.Lock() 2040 defer db.closeLock.Unlock() 2041 2042 if db.closed { 2043 return makeDbErr(database.ErrDbNotOpen, errDbNotOpenStr, nil) 2044 } 2045 db.closed = true 2046 2047 // NOTE: Since the above lock waits for all transactions to finish and 2048 // prevents any new ones from being started, it is safe to flush the 2049 // cache and clear all state without the individual locks. 2050 2051 // Close the database cache which will flush any existing entries to 2052 // disk and close the underlying leveldb database. Any error is saved 2053 // and returned at the end after the remaining cleanup since the 2054 // database will be marked closed even if this fails given there is no 2055 // good way for the caller to recover from a failure here anyways. 2056 closeErr := db.cache.Close() 2057 2058 // Close any open flat files that house the blocks. 2059 wc := db.store.writeCursor 2060 if wc.curFile.file != nil { 2061 _ = wc.curFile.file.Close() 2062 wc.curFile.file = nil 2063 } 2064 for _, blockFile := range db.store.openBlockFiles { 2065 _ = blockFile.file.Close() 2066 } 2067 db.store.openBlockFiles = nil 2068 db.store.openBlocksLRU.Init() 2069 db.store.fileNumToLRUElem = nil 2070 2071 return closeErr 2072 } 2073 2074 // filesExists reports whether the named file or directory exists. 2075 func fileExists(name string) bool { 2076 if _, err := os.Stat(name); err != nil { 2077 if os.IsNotExist(err) { 2078 return false 2079 } 2080 } 2081 return true 2082 } 2083 2084 // initDB creates the initial buckets and values used by the package. This is 2085 // mainly in a separate function for testing purposes. 2086 func initDB(ldb *leveldb.DB) error { 2087 // The starting block file write cursor location is file num 0, offset 2088 // 0. 2089 batch := new(leveldb.Batch) 2090 batch.Put(bucketizedKey(metadataBucketID, writeLocKeyName), 2091 serializeWriteRow(0, 0)) 2092 2093 // Create block index bucket and set the current bucket id. 2094 // 2095 // NOTE: Since buckets are virtualized through the use of prefixes, 2096 // there is no need to store the bucket index data for the metadata 2097 // bucket in the database. However, the first bucket ID to use does 2098 // need to account for it to ensure there are no key collisions. 2099 batch.Put(bucketIndexKey(metadataBucketID, blockIdxBucketName), 2100 blockIdxBucketID[:]) 2101 batch.Put(curBucketIDKeyName, blockIdxBucketID[:]) 2102 2103 // Write everything as a single batch. 2104 if err := ldb.Write(batch, nil); err != nil { 2105 str := fmt.Sprintf("failed to initialize metadata database: %v", 2106 err) 2107 return convertErr(str, err) 2108 } 2109 2110 return nil 2111 } 2112 2113 // openDB opens the database at the provided path. database.ErrDbDoesNotExist 2114 // is returned if the database doesn't exist and the create flag is not set. 2115 func openDB(dbPath string, network wire.BitcoinNet, create bool) (database.DB, error) { 2116 // Error if the database doesn't exist and the create flag is not set. 2117 metadataDbPath := filepath.Join(dbPath, metadataDbName) 2118 dbExists := fileExists(metadataDbPath) 2119 if !create && !dbExists { 2120 str := fmt.Sprintf("database %q does not exist", metadataDbPath) 2121 return nil, makeDbErr(database.ErrDbDoesNotExist, str, nil) 2122 } 2123 2124 // Ensure the full path to the database exists. 2125 if !dbExists { 2126 // The error can be ignored here since the call to 2127 // leveldb.OpenFile will fail if the directory couldn't be 2128 // created. 2129 _ = os.MkdirAll(dbPath, 0700) 2130 } 2131 2132 // Open the metadata database (will create it if needed). 2133 opts := opt.Options{ 2134 ErrorIfExist: create, 2135 Strict: opt.DefaultStrict, 2136 Compression: opt.NoCompression, 2137 Filter: filter.NewBloomFilter(10), 2138 } 2139 ldb, err := leveldb.OpenFile(metadataDbPath, &opts) 2140 if err != nil { 2141 return nil, convertErr(err.Error(), err) 2142 } 2143 2144 // Create the block store which includes scanning the existing flat 2145 // block files to find what the current write cursor position is 2146 // according to the data that is actually on disk. Also create the 2147 // database cache which wraps the underlying leveldb database to provide 2148 // write caching. 2149 store, err := newBlockStore(dbPath, network) 2150 if err != nil { 2151 return nil, convertErr(err.Error(), err) 2152 } 2153 cache := newDbCache(ldb, store, defaultCacheSize, defaultFlushSecs) 2154 pdb := &db{store: store, cache: cache} 2155 2156 // Perform any reconciliation needed between the block and metadata as 2157 // well as database initialization, if needed. 2158 return reconcileDB(pdb, create) 2159 }