-
Notifications
You must be signed in to change notification settings - Fork 0
/
impl.go
113 lines (98 loc) · 3.27 KB
/
impl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package fileledger
import (
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/common/ledger/blockledger"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
)
var logger = flogging.MustGetLogger("common.ledger.blockledger.file")
// FileLedger is a struct used to interact with a node's ledger
type FileLedger struct {
blockStore FileLedgerBlockStore
signal chan struct{}
}
// FileLedgerBlockStore defines the interface to interact with deliver when using a
// file ledger
type FileLedgerBlockStore interface {
AddBlock(block *cb.Block) error
GetBlockchainInfo() (*cb.BlockchainInfo, error)
RetrieveBlocks(startBlockNumber uint64) (ledger.ResultsIterator, error)
}
// NewFileLedger creates a new FileLedger for interaction with the ledger
func NewFileLedger(blockStore FileLedgerBlockStore) *FileLedger {
return &FileLedger{blockStore: blockStore, signal: make(chan struct{})}
}
type fileLedgerIterator struct {
ledger *FileLedger
blockNumber uint64
commonIterator ledger.ResultsIterator
}
// Next blocks until there is a new block available, or until Close is called.
// It returns an error if the next block is no longer retrievable.
func (i *fileLedgerIterator) Next() (*cb.Block, cb.Status) {
result, err := i.commonIterator.Next()
if err != nil {
logger.Error(err)
return nil, cb.Status_SERVICE_UNAVAILABLE
}
// Cover the case where another thread calls Close on the iterator.
if result == nil {
return nil, cb.Status_SERVICE_UNAVAILABLE
}
return result.(*cb.Block), cb.Status_SUCCESS
}
// Close releases resources acquired by the Iterator
func (i *fileLedgerIterator) Close() {
i.commonIterator.Close()
}
// Iterator returns an Iterator, as specified by an ab.SeekInfo message, and its
// starting block number
func (fl *FileLedger) Iterator(startPosition *ab.SeekPosition) (blockledger.Iterator, uint64) {
var startingBlockNumber uint64
switch start := startPosition.Type.(type) {
case *ab.SeekPosition_Oldest:
startingBlockNumber = 0
case *ab.SeekPosition_Newest:
info, err := fl.blockStore.GetBlockchainInfo()
if err != nil {
logger.Panic(err)
}
newestBlockNumber := info.Height - 1
startingBlockNumber = newestBlockNumber
case *ab.SeekPosition_Specified:
startingBlockNumber = start.Specified.Number
height := fl.Height()
if startingBlockNumber > height {
return &blockledger.NotFoundErrorIterator{}, 0
}
default:
return &blockledger.NotFoundErrorIterator{}, 0
}
iterator, err := fl.blockStore.RetrieveBlocks(startingBlockNumber)
if err != nil {
return &blockledger.NotFoundErrorIterator{}, 0
}
return &fileLedgerIterator{ledger: fl, blockNumber: startingBlockNumber, commonIterator: iterator}, startingBlockNumber
}
// Height returns the number of blocks on the ledger
func (fl *FileLedger) Height() uint64 {
info, err := fl.blockStore.GetBlockchainInfo()
if err != nil {
logger.Panic(err)
}
return info.Height
}
// Append a new block to the ledger
func (fl *FileLedger) Append(block *cb.Block) error {
err := fl.blockStore.AddBlock(block)
if err == nil {
close(fl.signal)
fl.signal = make(chan struct{})
}
return err
}