github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/service/eventer.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package service
     8  
     9  import (
    10  	"reflect"
    11  
    12  	"github.com/hyperledger/fabric/common/config"
    13  
    14  	"github.com/hyperledger/fabric/protos/peer"
    15  )
    16  
    17  // Config enumerates the configuration methods required by gossip
    18  type Config interface {
    19  	// ChainID returns the chainID for this channel
    20  	ChainID() string
    21  
    22  	// Organizations returns a map of org ID to ApplicationOrgConfig
    23  	Organizations() map[string]config.ApplicationOrg
    24  
    25  	// Sequence should return the sequence number of the current configuration
    26  	Sequence() uint64
    27  }
    28  
    29  // ConfigProcessor receives config updates
    30  type ConfigProcessor interface {
    31  	// ProcessConfig should be invoked whenever a channel's configuration is initialized or updated
    32  	ProcessConfigUpdate(config Config)
    33  }
    34  
    35  type configStore struct {
    36  	anchorPeers []*peer.AnchorPeer
    37  	orgMap      map[string]config.ApplicationOrg
    38  }
    39  
    40  type configEventReceiver interface {
    41  	configUpdated(config Config)
    42  }
    43  
    44  type configEventer struct {
    45  	lastConfig *configStore
    46  	receiver   configEventReceiver
    47  }
    48  
    49  func newConfigEventer(receiver configEventReceiver) *configEventer {
    50  	return &configEventer{
    51  		receiver: receiver,
    52  	}
    53  }
    54  
    55  // ProcessConfigUpdate should be invoked whenever a channel's configuration is intialized or updated
    56  // it invokes the associated method in configEventReceiver when configuration is updated
    57  // but only if the configuration value actually changed
    58  // Note, that a changing sequence number is ignored as changing configuration
    59  func (ce *configEventer) ProcessConfigUpdate(config Config) {
    60  	logger.Debugf("Processing new config for channel %s", config.ChainID())
    61  	orgMap := cloneOrgConfig(config.Organizations())
    62  	if ce.lastConfig != nil && reflect.DeepEqual(ce.lastConfig.orgMap, orgMap) {
    63  		logger.Debugf("Ignoring new config for channel %s because it contained no anchor peer updates", config.ChainID())
    64  		return
    65  	}
    66  
    67  	var newAnchorPeers []*peer.AnchorPeer
    68  	for _, group := range config.Organizations() {
    69  		newAnchorPeers = append(newAnchorPeers, group.AnchorPeers()...)
    70  	}
    71  
    72  	newConfig := &configStore{
    73  		orgMap:      orgMap,
    74  		anchorPeers: newAnchorPeers,
    75  	}
    76  	ce.lastConfig = newConfig
    77  
    78  	logger.Debugf("Calling out because config was updated for channel %s", config.ChainID())
    79  	ce.receiver.configUpdated(config)
    80  }
    81  
    82  func cloneOrgConfig(src map[string]config.ApplicationOrg) map[string]config.ApplicationOrg {
    83  	clone := make(map[string]config.ApplicationOrg)
    84  	for k, v := range src {
    85  		clone[k] = &appGrp{
    86  			name:        v.Name(),
    87  			mspID:       v.MSPID(),
    88  			anchorPeers: v.AnchorPeers(),
    89  		}
    90  	}
    91  	return clone
    92  }
    93  
    94  type appGrp struct {
    95  	name        string
    96  	mspID       string
    97  	anchorPeers []*peer.AnchorPeer
    98  }
    99  
   100  func (ag *appGrp) Name() string {
   101  	return ag.name
   102  }
   103  
   104  func (ag *appGrp) MSPID() string {
   105  	return ag.mspID
   106  }
   107  
   108  func (ag *appGrp) AnchorPeers() []*peer.AnchorPeer {
   109  	return ag.anchorPeers
   110  }