github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/committer/committer_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 committer
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/hyperledger/fabric/common/flogging"
    23  	"github.com/hyperledger/fabric/core/committer/txvalidator"
    24  	"github.com/hyperledger/fabric/core/ledger"
    25  	"github.com/hyperledger/fabric/events/producer"
    26  	"github.com/hyperledger/fabric/protos/common"
    27  	"github.com/hyperledger/fabric/protos/utils"
    28  	"github.com/op/go-logging"
    29  )
    30  
    31  //--------!!!IMPORTANT!!-!!IMPORTANT!!-!!IMPORTANT!!---------
    32  // This is used merely to complete the loop for the "skeleton"
    33  // path so we can reason about and  modify committer component
    34  // more effectively using code.
    35  
    36  var logger *logging.Logger // package-level logger
    37  
    38  func init() {
    39  	logger = flogging.MustGetLogger("committer")
    40  }
    41  
    42  // LedgerCommitter is the implementation of  Committer interface
    43  // it keeps the reference to the ledger to commit blocks and retrieve
    44  // chain information
    45  type LedgerCommitter struct {
    46  	ledger    ledger.PeerLedger
    47  	validator txvalidator.Validator
    48  	eventer   ConfigBlockEventer
    49  }
    50  
    51  // ConfigBlockEventer callback function proto type to define action
    52  // upon arrival on new configuaration update block
    53  type ConfigBlockEventer func(block *common.Block) error
    54  
    55  // NewLedgerCommitter is a factory function to create an instance of the committer
    56  // which passes incoming blocks via validation and commits them into the ledger.
    57  func NewLedgerCommitter(ledger ledger.PeerLedger, validator txvalidator.Validator) *LedgerCommitter {
    58  	return NewLedgerCommitterReactive(ledger, validator, func(_ *common.Block) error { return nil })
    59  }
    60  
    61  // NewLedgerCommitterReactive is a factory function to create an instance of the committer
    62  // same as way as NewLedgerCommitter, while also provides an option to specify callback to
    63  // be called upon new configuration block arrival and commit event
    64  func NewLedgerCommitterReactive(ledger ledger.PeerLedger, validator txvalidator.Validator, eventer ConfigBlockEventer) *LedgerCommitter {
    65  	return &LedgerCommitter{ledger: ledger, validator: validator, eventer: eventer}
    66  }
    67  
    68  // Commit commits block to into the ledger
    69  // Note, it is important that this always be called serially
    70  func (lc *LedgerCommitter) Commit(block *common.Block) error {
    71  
    72  	// Validate and mark invalid transactions
    73  	logger.Debug("Validating block")
    74  	if err := lc.validator.Validate(block); err != nil {
    75  		return err
    76  	}
    77  
    78  	// Updating CSCC with new configuration block
    79  	if utils.IsConfigBlock(block) {
    80  		logger.Debug("Received configuration update, calling CSCC ConfigUpdate")
    81  		if err := lc.eventer(block); err != nil {
    82  			return fmt.Errorf("Could not update CSCC with new configuration update due to %s", err)
    83  		}
    84  	}
    85  
    86  	if err := lc.ledger.Commit(block); err != nil {
    87  		return err
    88  	}
    89  
    90  	// send block event *after* the block has been committed
    91  	if err := producer.SendProducerBlockEvent(block); err != nil {
    92  		logger.Errorf("Error publishing block %d, because: %v", block.Header.Number, err)
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  // LedgerHeight returns recently committed block sequence number
    99  func (lc *LedgerCommitter) LedgerHeight() (uint64, error) {
   100  	var info *common.BlockchainInfo
   101  	var err error
   102  	if info, err = lc.ledger.GetBlockchainInfo(); err != nil {
   103  		logger.Errorf("Cannot get blockchain info, %s\n", info)
   104  		return uint64(0), err
   105  	}
   106  
   107  	return info.Height, nil
   108  }
   109  
   110  // GetBlocks used to retrieve blocks with sequence numbers provided in the slice
   111  func (lc *LedgerCommitter) GetBlocks(blockSeqs []uint64) []*common.Block {
   112  	var blocks []*common.Block
   113  
   114  	for _, seqNum := range blockSeqs {
   115  		if blck, err := lc.ledger.GetBlockByNumber(seqNum); err != nil {
   116  			logger.Errorf("Not able to acquire block num %d, from the ledger skipping...\n", seqNum)
   117  			continue
   118  		} else {
   119  			logger.Debug("Appending next block with seqNum = ", seqNum, " to the resulting set")
   120  			blocks = append(blocks, blck)
   121  		}
   122  	}
   123  
   124  	return blocks
   125  }
   126  
   127  // Close the ledger
   128  func (lc *LedgerCommitter) Close() {
   129  	lc.ledger.Close()
   130  }