holdable_iterator.go 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2022 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package snapshot
  17. import (
  18. "github.com/ethereum/go-ethereum/common"
  19. "github.com/ethereum/go-ethereum/ethdb"
  20. )
  21. // holdableIterator is a wrapper of underlying database iterator. It extends
  22. // the basic iterator interface by adding Hold which can hold the element
  23. // locally where the iterator is currently located and serve it up next time.
  24. type holdableIterator struct {
  25. it ethdb.Iterator
  26. key []byte
  27. val []byte
  28. atHeld bool
  29. }
  30. // newHoldableIterator initializes the holdableIterator with the given iterator.
  31. func newHoldableIterator(it ethdb.Iterator) *holdableIterator {
  32. return &holdableIterator{it: it}
  33. }
  34. // Hold holds the element locally where the iterator is currently located which
  35. // can be served up next time.
  36. func (it *holdableIterator) Hold() {
  37. if it.it.Key() == nil {
  38. return // nothing to hold
  39. }
  40. it.key = common.CopyBytes(it.it.Key())
  41. it.val = common.CopyBytes(it.it.Value())
  42. it.atHeld = false
  43. }
  44. // Next moves the iterator to the next key/value pair. It returns whether the
  45. // iterator is exhausted.
  46. func (it *holdableIterator) Next() bool {
  47. if !it.atHeld && it.key != nil {
  48. it.atHeld = true
  49. } else if it.atHeld {
  50. it.atHeld = false
  51. it.key = nil
  52. it.val = nil
  53. }
  54. if it.key != nil {
  55. return true // shifted to locally held value
  56. }
  57. return it.it.Next()
  58. }
  59. // Error returns any accumulated error. Exhausting all the key/value pairs
  60. // is not considered to be an error.
  61. func (it *holdableIterator) Error() error { return it.it.Error() }
  62. // Release releases associated resources. Release should always succeed and can
  63. // be called multiple times without causing error.
  64. func (it *holdableIterator) Release() {
  65. it.atHeld = false
  66. it.key = nil
  67. it.val = nil
  68. it.it.Release()
  69. }
  70. // Key returns the key of the current key/value pair, or nil if done. The caller
  71. // should not modify the contents of the returned slice, and its contents may
  72. // change on the next call to Next.
  73. func (it *holdableIterator) Key() []byte {
  74. if it.key != nil {
  75. return it.key
  76. }
  77. return it.it.Key()
  78. }
  79. // Value returns the value of the current key/value pair, or nil if done. The
  80. // caller should not modify the contents of the returned slice, and its contents
  81. // may change on the next call to Next.
  82. func (it *holdableIterator) Value() []byte {
  83. if it.val != nil {
  84. return it.val
  85. }
  86. return it.it.Value()
  87. }