github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/orderer/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 "github.com/hyperledger/fabric/common/ledger/blkstorage" 21 ledger "github.com/hyperledger/fabric/orderer/ledger" 22 cb "github.com/hyperledger/fabric/protos/common" 23 ab "github.com/hyperledger/fabric/protos/orderer" 24 "github.com/op/go-logging" 25 ) 26 27 var logger = logging.MustGetLogger("orderer/fileledger") 28 var closedChan chan struct{} 29 30 func init() { 31 closedChan = make(chan struct{}) 32 close(closedChan) 33 } 34 35 type fileLedger struct { 36 blockStore blkstorage.BlockStore 37 signal chan struct{} 38 } 39 40 type fileLedgerIterator struct { 41 ledger *fileLedger 42 blockNumber uint64 43 } 44 45 // Next blocks until there is a new block available, or returns an error if the 46 // next block is no longer retrievable 47 func (i *fileLedgerIterator) Next() (*cb.Block, cb.Status) { 48 for { 49 if i.blockNumber < i.ledger.Height() { 50 block, err := i.ledger.blockStore.RetrieveBlockByNumber(i.blockNumber) 51 if err != nil { 52 return nil, cb.Status_SERVICE_UNAVAILABLE 53 } 54 i.blockNumber++ 55 return block, cb.Status_SUCCESS 56 } 57 <-i.ledger.signal 58 } 59 } 60 61 // ReadyChan supplies a channel which will block until Next will not block 62 func (i *fileLedgerIterator) ReadyChan() <-chan struct{} { 63 signal := i.ledger.signal 64 if i.blockNumber > i.ledger.Height()-1 { 65 return signal 66 } 67 return closedChan 68 } 69 70 // Iterator returns an Iterator, as specified by a cb.SeekInfo message, and its 71 // starting block number 72 func (fl *fileLedger) Iterator(startPosition *ab.SeekPosition) (ledger.Iterator, uint64) { 73 switch start := startPosition.Type.(type) { 74 case *ab.SeekPosition_Oldest: 75 return &fileLedgerIterator{ledger: fl, blockNumber: 0}, 0 76 case *ab.SeekPosition_Newest: 77 info, err := fl.blockStore.GetBlockchainInfo() 78 if err != nil { 79 logger.Panic(err) 80 } 81 newestBlockNumber := info.Height - 1 82 return &fileLedgerIterator{ledger: fl, blockNumber: newestBlockNumber}, newestBlockNumber 83 case *ab.SeekPosition_Specified: 84 height := fl.Height() 85 if start.Specified.Number > height { 86 return &ledger.NotFoundErrorIterator{}, 0 87 } 88 return &fileLedgerIterator{ledger: fl, blockNumber: start.Specified.Number}, start.Specified.Number 89 } 90 // This line should be unreachable, but the compiler requires it 91 return &ledger.NotFoundErrorIterator{}, 0 92 } 93 94 // Height returns the number of blocks on the ledger 95 func (fl *fileLedger) Height() uint64 { 96 info, err := fl.blockStore.GetBlockchainInfo() 97 if err != nil { 98 logger.Panic(err) 99 } 100 return info.Height 101 } 102 103 // Append a new block to the ledger 104 func (fl *fileLedger) Append(block *cb.Block) error { 105 err := fl.blockStore.AddBlock(block) 106 if err == nil { 107 close(fl.signal) 108 fl.signal = make(chan struct{}) 109 } 110 return err 111 }