mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
internal/era: improve iterator interface
This commit is contained in:
parent
b8fc70e8f4
commit
67defc417c
1 changed files with 41 additions and 7 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
package era
|
package era
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
|
@ -29,7 +30,8 @@ type Iterator struct {
|
||||||
inner *RawIterator
|
inner *RawIterator
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIterator returns a new Iterator instance.
|
// NewRawIterator returns a new Iterator instance. Next must be immediately
|
||||||
|
// called on new iterators to load the first item.
|
||||||
func NewIterator(e *Era) (*Iterator, error) {
|
func NewIterator(e *Era) (*Iterator, error) {
|
||||||
inner, err := NewRawIterator(e)
|
inner, err := NewRawIterator(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -38,7 +40,9 @@ func NewIterator(e *Era) (*Iterator, error) {
|
||||||
return &Iterator{inner}, nil
|
return &Iterator{inner}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next moves the iterator to the next block entry.
|
// Next moves the iterator to the next block entry. It returns false when all
|
||||||
|
// items have been read or an error has halted its progress. Block, Receipts,
|
||||||
|
// and BlockAndReceipts should no longer be called after false is returned.
|
||||||
func (it *Iterator) Next() bool {
|
func (it *Iterator) Next() bool {
|
||||||
return it.inner.Next()
|
return it.inner.Next()
|
||||||
}
|
}
|
||||||
|
|
@ -48,13 +52,17 @@ func (it *Iterator) Number() uint64 {
|
||||||
return it.inner.next - 1
|
return it.inner.next - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returns the error status of the iterator.
|
// Error returns the error status of the iterator. It should be called before
|
||||||
|
// reading from any of the iterator's values.
|
||||||
func (it *Iterator) Error() error {
|
func (it *Iterator) Error() error {
|
||||||
return it.inner.Error()
|
return it.inner.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block returns the block for the iterator's current position.
|
// Block returns the block for the iterator's current position.
|
||||||
func (it *Iterator) Block() (*types.Block, error) {
|
func (it *Iterator) Block() (*types.Block, error) {
|
||||||
|
if it.inner.Header == nil || it.inner.Body == nil {
|
||||||
|
return nil, fmt.Errorf("header and body must be non-nil")
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
header types.Header
|
header types.Header
|
||||||
body types.Body
|
body types.Body
|
||||||
|
|
@ -70,6 +78,9 @@ func (it *Iterator) Block() (*types.Block, error) {
|
||||||
|
|
||||||
// Receipts returns the receipts for the iterator's current position.
|
// Receipts returns the receipts for the iterator's current position.
|
||||||
func (it *Iterator) Receipts() (types.Receipts, error) {
|
func (it *Iterator) Receipts() (types.Receipts, error) {
|
||||||
|
if it.inner.Receipts == nil {
|
||||||
|
return nil, fmt.Errorf("receipts must be non-nil")
|
||||||
|
}
|
||||||
var receipts types.Receipts
|
var receipts types.Receipts
|
||||||
err := rlp.Decode(it.inner.Receipts, &receipts)
|
err := rlp.Decode(it.inner.Receipts, &receipts)
|
||||||
return receipts, err
|
return receipts, err
|
||||||
|
|
@ -111,7 +122,8 @@ type RawIterator struct {
|
||||||
TotalDifficulty io.Reader
|
TotalDifficulty io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRawIterator returns a new Iterator instance.
|
// NewRawIterator returns a new RawIterator instance. Next must be immediately
|
||||||
|
// called on new iterators to load the first item.
|
||||||
func NewRawIterator(e *Era) (*RawIterator, error) {
|
func NewRawIterator(e *Era) (*RawIterator, error) {
|
||||||
return &RawIterator{
|
return &RawIterator{
|
||||||
e: e,
|
e: e,
|
||||||
|
|
@ -119,30 +131,43 @@ func NewRawIterator(e *Era) (*RawIterator, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next moves the iterator to the next block entry.
|
// Next moves the iterator to the next block entry. It returns false when all
|
||||||
|
// items have been read or an error has halted its progress. Header, Body,
|
||||||
|
// Receipts, TotalDifficulty will be set to nil in the case returning false or
|
||||||
|
// finding an error and should therefore no longer be read from.
|
||||||
func (it *RawIterator) Next() bool {
|
func (it *RawIterator) Next() bool {
|
||||||
|
// Clear old errors.
|
||||||
|
it.err = nil
|
||||||
if it.e.m.start+it.e.m.count <= it.next {
|
if it.e.m.start+it.e.m.count <= it.next {
|
||||||
|
it.clear()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
off, err := it.e.readOffset(it.next)
|
off, err := it.e.readOffset(it.next)
|
||||||
if err == io.EOF {
|
if err != nil {
|
||||||
|
// Error here means block index is corrupted, so don't
|
||||||
|
// continue.
|
||||||
|
it.clear()
|
||||||
it.err = err
|
it.err = err
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var n int64
|
var n int64
|
||||||
if it.Header, n, it.err = newSnappyReader(it.e.s, TypeCompressedHeader, off); it.err != nil {
|
if it.Header, n, it.err = newSnappyReader(it.e.s, TypeCompressedHeader, off); it.err != nil {
|
||||||
|
it.clear()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
off += n
|
off += n
|
||||||
if it.Body, n, it.err = newSnappyReader(it.e.s, TypeCompressedBody, off); it.err != nil {
|
if it.Body, n, it.err = newSnappyReader(it.e.s, TypeCompressedBody, off); it.err != nil {
|
||||||
|
it.clear()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
off += n
|
off += n
|
||||||
if it.Receipts, n, it.err = newSnappyReader(it.e.s, TypeCompressedReceipts, off); it.err != nil {
|
if it.Receipts, n, it.err = newSnappyReader(it.e.s, TypeCompressedReceipts, off); it.err != nil {
|
||||||
|
it.clear()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
off += n
|
off += n
|
||||||
if it.TotalDifficulty, _, it.err = it.e.s.ReaderAt(TypeTotalDifficulty, off); it.err != nil {
|
if it.TotalDifficulty, _, it.err = it.e.s.ReaderAt(TypeTotalDifficulty, off); it.err != nil {
|
||||||
|
it.clear()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
it.next += 1
|
it.next += 1
|
||||||
|
|
@ -154,10 +179,19 @@ func (it *RawIterator) Number() uint64 {
|
||||||
return it.next - 1
|
return it.next - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returns the error status of the iterator.
|
// Error returns the error status of the iterator. It should be called before
|
||||||
|
// reading from any of the iterator's values.
|
||||||
func (it *RawIterator) Error() error {
|
func (it *RawIterator) Error() error {
|
||||||
if it.err == io.EOF {
|
if it.err == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return it.err
|
return it.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear sets all the outputs to nil.
|
||||||
|
func (it *RawIterator) clear() {
|
||||||
|
it.Header = nil
|
||||||
|
it.Body = nil
|
||||||
|
it.Receipts = nil
|
||||||
|
it.TotalDifficulty = nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue