github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/ledger/file/impl.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package fileledger 18 19 import ( 20 cl "github.com/hyperledger/fabric/common/ledger" 21 "github.com/hyperledger/fabric/common/ledger/blkstorage" 22 ledger "github.com/hyperledger/fabric/orderer/common/ledger" 23 cb "github.com/hyperledger/fabric/protos/common" 24 ab "github.com/hyperledger/fabric/protos/orderer" 25 "github.com/op/go-logging" 26 ) 27 28 var logger = logging.MustGetLogger("orderer/fileledger") 29 var closedChan chan struct{} 30 31 func init() { 32 closedChan = make(chan struct{}) 33 close(closedChan) 34 } 35 36 type fileLedger struct { 37 blockStore blkstorage.BlockStore 38 signal chan struct{} 39 } 40 41 type fileLedgerIterator struct { 42 ledger *fileLedger 43 blockNumber uint64 44 commonIterator cl.ResultsIterator 45 } 46 47 // Next blocks until there is a new block available, or returns an error if the 48 // next block is no longer retrievable 49 func (i *fileLedgerIterator) Next() (*cb.Block, cb.Status) { 50 for { 51 if i.blockNumber < i.ledger.Height() { 52 result, err := i.commonIterator.Next() 53 if err != nil { 54 return nil, cb.Status_SERVICE_UNAVAILABLE 55 } 56 i.blockNumber++ 57 return result.(*cb.Block), cb.Status_SUCCESS 58 } 59 <-i.ledger.signal 60 } 61 } 62 63 // ReadyChan supplies a channel which will block until Next will not block 64 func (i *fileLedgerIterator) ReadyChan() <-chan struct{} { 65 signal := i.ledger.signal 66 if i.blockNumber > i.ledger.Height()-1 { 67 return signal 68 } 69 return closedChan 70 } 71 72 // Close releases resources acquired by the Iterator 73 func (i *fileLedgerIterator) Close() { 74 i.commonIterator.Close() 75 } 76 77 // Iterator returns an Iterator, as specified by a cb.SeekInfo message, and its 78 // starting block number 79 func (fl *fileLedger) Iterator(startPosition *ab.SeekPosition) (ledger.Iterator, uint64) { 80 var startingBlockNumber uint64 81 switch start := startPosition.Type.(type) { 82 case *ab.SeekPosition_Oldest: 83 startingBlockNumber = 0 84 case *ab.SeekPosition_Newest: 85 info, err := fl.blockStore.GetBlockchainInfo() 86 if err != nil { 87 logger.Panic(err) 88 } 89 newestBlockNumber := info.Height - 1 90 startingBlockNumber = newestBlockNumber 91 case *ab.SeekPosition_Specified: 92 startingBlockNumber = start.Specified.Number 93 height := fl.Height() 94 if startingBlockNumber > height { 95 return &ledger.NotFoundErrorIterator{}, 0 96 } 97 default: 98 return &ledger.NotFoundErrorIterator{}, 0 99 } 100 101 iterator, err := fl.blockStore.RetrieveBlocks(startingBlockNumber) 102 if err != nil { 103 return &ledger.NotFoundErrorIterator{}, 0 104 } 105 106 return &fileLedgerIterator{ledger: fl, blockNumber: startingBlockNumber, commonIterator: iterator}, startingBlockNumber 107 } 108 109 // Height returns the number of blocks on the ledger 110 func (fl *fileLedger) Height() uint64 { 111 info, err := fl.blockStore.GetBlockchainInfo() 112 if err != nil { 113 logger.Panic(err) 114 } 115 return info.Height 116 } 117 118 // Append a new block to the ledger 119 func (fl *fileLedger) Append(block *cb.Block) error { 120 err := fl.blockStore.AddBlock(block) 121 if err == nil { 122 close(fl.signal) 123 fl.signal = make(chan struct{}) 124 } 125 return err 126 }