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  }