github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/gossip/service/eventer.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 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 service
    18  
    19  import (
    20  	"reflect"
    21  
    22  	"github.com/hyperledger/fabric/common/config"
    23  
    24  	"github.com/hyperledger/fabric/protos/peer"
    25  )
    26  
    27  // Config enumerates the configuration methods required by gossip
    28  type Config interface {
    29  	// ChainID returns the chainID for this channel
    30  	ChainID() string
    31  
    32  	// Organizations returns a map of org ID to ApplicationOrgConfig
    33  	Organizations() map[string]config.ApplicationOrg
    34  
    35  	// Sequence should return the sequence number of the current configuration
    36  	Sequence() uint64
    37  }
    38  
    39  // ConfigProcessor receives config updates
    40  type ConfigProcessor interface {
    41  	// ProcessConfig should be invoked whenever a channel's configuration is initialized or updated
    42  	ProcessConfigUpdate(config Config)
    43  }
    44  
    45  type configStore struct {
    46  	anchorPeers []*peer.AnchorPeer
    47  	orgMap      map[string]config.ApplicationOrg
    48  }
    49  
    50  type configEventReceiver interface {
    51  	configUpdated(config Config)
    52  }
    53  
    54  type configEventer struct {
    55  	lastConfig *configStore
    56  	receiver   configEventReceiver
    57  }
    58  
    59  func newConfigEventer(receiver configEventReceiver) *configEventer {
    60  	return &configEventer{
    61  		receiver: receiver,
    62  	}
    63  }
    64  
    65  // ProcessConfigUpdate should be invoked whenever a channel's configuration is intialized or updated
    66  // it invokes the associated method in configEventReceiver when configuration is updated
    67  // but only if the configuration value actually changed
    68  // Note, that a changing sequence number is ignored as changing configuration
    69  func (ce *configEventer) ProcessConfigUpdate(config Config) {
    70  	logger.Debugf("Processing new config for channel %s", config.ChainID())
    71  
    72  	if ce.lastConfig != nil && reflect.DeepEqual(ce.lastConfig.orgMap, config.Organizations()) {
    73  		logger.Debugf("Ignoring new config for channel %s because it contained no anchor peer updates", config.ChainID())
    74  		return
    75  	}
    76  
    77  	var newAnchorPeers []*peer.AnchorPeer
    78  	for _, group := range config.Organizations() {
    79  		newAnchorPeers = append(newAnchorPeers, group.AnchorPeers()...)
    80  	}
    81  
    82  	newConfig := &configStore{
    83  		orgMap:      config.Organizations(),
    84  		anchorPeers: newAnchorPeers,
    85  	}
    86  	ce.lastConfig = newConfig
    87  
    88  	logger.Debugf("Calling out because config was updated for channel %s", config.ChainID())
    89  	ce.receiver.configUpdated(config)
    90  }