112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package service
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/hyperledger/fabric-protos-go/peer"
|
|
"github.com/hyperledger/fabric/common/channelconfig"
|
|
"github.com/hyperledger/fabric/msp"
|
|
)
|
|
|
|
// A ConfigUpdate holds the portions of channelconfig Bundle update used by
|
|
// gossip.
|
|
type ConfigUpdate struct {
|
|
ChannelID string
|
|
Organizations map[string]channelconfig.ApplicationOrg
|
|
Sequence uint64
|
|
OrdererAddresses []string
|
|
}
|
|
|
|
// ConfigProcessor receives config updates
|
|
type ConfigProcessor interface {
|
|
// ProcessConfigUpdate should be invoked whenever a channel's configuration is initialized or updated
|
|
ProcessConfigUpdate(configUpdate ConfigUpdate)
|
|
}
|
|
|
|
type configStore struct {
|
|
anchorPeers []*peer.AnchorPeer
|
|
orgMap map[string]channelconfig.ApplicationOrg
|
|
}
|
|
|
|
type configEventReceiver interface {
|
|
updateAnchors(config ConfigUpdate)
|
|
}
|
|
|
|
type configEventer struct {
|
|
lastConfig *configStore
|
|
receiver configEventReceiver
|
|
}
|
|
|
|
func newConfigEventer(receiver configEventReceiver) *configEventer {
|
|
return &configEventer{
|
|
receiver: receiver,
|
|
}
|
|
}
|
|
|
|
// ProcessConfigUpdate should be invoked whenever a channel's configuration is initialized or updated
|
|
// it invokes the associated method in configEventReceiver when configuration is updated
|
|
// but only if the configuration value actually changed
|
|
// Note, that a changing sequence number is ignored as changing configuration
|
|
func (ce *configEventer) ProcessConfigUpdate(configUpdate ConfigUpdate) {
|
|
logger.Debugf("Processing new config for channel %s", configUpdate.ChannelID)
|
|
orgMap := cloneOrgConfig(configUpdate.Organizations)
|
|
if ce.lastConfig != nil && reflect.DeepEqual(ce.lastConfig.orgMap, orgMap) {
|
|
logger.Debugf("Ignoring new config for channel %s because it contained no anchor peer updates", configUpdate.ChannelID)
|
|
} else {
|
|
|
|
var newAnchorPeers []*peer.AnchorPeer
|
|
for _, group := range configUpdate.Organizations {
|
|
newAnchorPeers = append(newAnchorPeers, group.AnchorPeers()...)
|
|
}
|
|
|
|
newConfig := &configStore{
|
|
orgMap: orgMap,
|
|
anchorPeers: newAnchorPeers,
|
|
}
|
|
ce.lastConfig = newConfig
|
|
|
|
logger.Debugf("Calling out because config was updated for channel %s", configUpdate.ChannelID)
|
|
ce.receiver.updateAnchors(configUpdate)
|
|
}
|
|
}
|
|
|
|
func cloneOrgConfig(src map[string]channelconfig.ApplicationOrg) map[string]channelconfig.ApplicationOrg {
|
|
clone := make(map[string]channelconfig.ApplicationOrg)
|
|
for k, v := range src {
|
|
clone[k] = &appGrp{
|
|
name: v.Name(),
|
|
mspID: v.MSPID(),
|
|
anchorPeers: v.AnchorPeers(),
|
|
}
|
|
}
|
|
return clone
|
|
}
|
|
|
|
type appGrp struct {
|
|
name string
|
|
mspID string
|
|
anchorPeers []*peer.AnchorPeer
|
|
}
|
|
|
|
func (ag *appGrp) Name() string {
|
|
return ag.name
|
|
}
|
|
|
|
func (ag *appGrp) MSPID() string {
|
|
return ag.mspID
|
|
}
|
|
|
|
func (ag *appGrp) AnchorPeers() []*peer.AnchorPeer {
|
|
return ag.anchorPeers
|
|
}
|
|
|
|
func (ag *appGrp) MSP() msp.MSP {
|
|
return nil
|
|
}
|