Skip to content

Commit e360a6e

Browse files
committed
[FAB-9516] Split cclifecycle update to 2 phases
The lifecycle object that caches the deployed chaincodes of the peer receives a notification from the ledger before the install of the chaincode actually happens. The install might fail, and then gossip would publish false information. For this - the ledger listener separated the notification into 2 steps: 1. Notify about the deployment, which happens just before the install 2. Notify whether the deployment was successful or not, which is only relevant for install. This change set moves the state update of the lifecycle object to the DeployDone() phase (the 2nd phase from above) Change-Id: I495f73278ce4e7d017085a6df4043794bc7005a7 Signed-off-by: yacovm <yacovm@il.ibm.com>
1 parent 7dc4a86 commit e360a6e

12 files changed

+604
-636
lines changed

core/cclifecycle/lifecycle.go

+46-29
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ import (
1111

1212
"github.com/hyperledger/fabric/common/chaincode"
1313
"github.com/hyperledger/fabric/common/flogging"
14+
"github.com/hyperledger/fabric/core/ledger/cceventmgmt"
1415
"github.com/pkg/errors"
1516
)
1617

1718
var (
18-
logger = flogging.MustGetLogger("discovery/lifecycle")
19+
// Logger is the logging instance for this package.
20+
// It's exported because the tests override its backend
21+
Logger = flogging.MustGetLogger("discovery/lifecycle")
1922
)
2023

2124
// Lifecycle manages information regarding chaincode lifecycle
@@ -36,12 +39,16 @@ type LifeCycleChangeListener interface {
3639
// HandleMetadataUpdate is triggered upon a change in the chaincode lifecycle change
3740
type HandleMetadataUpdate func(channel string, chaincodes chaincode.MetadataSet)
3841

42+
// go:generate mockery -dir core/cclifecycle -name LifeCycleChangeListener -case underscore -output core/cclifecycle/mocks/
43+
3944
// LifeCycleChangeListener runs whenever there is a change to the metadata
4045
// // of a chaincode in the context of a specific channel
4146
func (mdUpdate HandleMetadataUpdate) LifeCycleChangeListener(channel string, chaincodes chaincode.MetadataSet) {
4247
mdUpdate(channel, chaincodes)
4348
}
4449

50+
// go:generate mockery -dir core/cclifecycle -name Enumerator -case underscore -output core/cclifecycle/mocks/
51+
4552
// Enumerator enumerates chaincodes
4653
type Enumerator interface {
4754
// Enumerate returns the installed chaincodes
@@ -56,6 +63,8 @@ func (listCCs Enumerate) Enumerate() ([]chaincode.InstalledChaincode, error) {
5663
return listCCs()
5764
}
5865

66+
// go:generate mockery -dir core/cclifecycle -name Query -case underscore -output core/cclifecycle/mocks/
67+
5968
// Query queries the state
6069
type Query interface {
6170
// GetState gets the value for given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId
@@ -65,8 +74,21 @@ type Query interface {
6574
Done()
6675
}
6776

68-
// QueryCreator creates a new query
69-
type QueryCreator func() (Query, error)
77+
// go:generate mockery -dir core/cclifecycle -name QueryCreator -case underscore -output core/cclifecycle/mocks/
78+
79+
// QueryCreator creates queries
80+
type QueryCreator interface {
81+
// NewQuery creates a new Query, or error on failure
82+
NewQuery() (Query, error)
83+
}
84+
85+
// QueryCreatorFunc creates a new query
86+
type QueryCreatorFunc func() (Query, error)
87+
88+
// NewQuery creates a new Query, or error on failure
89+
func (qc QueryCreatorFunc) NewQuery() (Query, error) {
90+
return qc()
91+
}
7092

7193
// NewLifeCycle creates a new Lifecycle instance
7294
func NewLifeCycle(installedChaincodes Enumerator) (*Lifecycle, error) {
@@ -87,48 +109,48 @@ func NewLifeCycle(installedChaincodes Enumerator) (*Lifecycle, error) {
87109
// Metadata returns the metadata of the chaincode on the given channel,
88110
// or nil if not found or an error occurred at retrieving it
89111
func (lc *Lifecycle) Metadata(channel string, cc string) *chaincode.Metadata {
90-
newQuery := lc.queryCreatorsByChannel[channel]
91-
if newQuery == nil {
92-
logger.Warning("Requested Metadata for non-existent channel", channel)
112+
queryCreator := lc.queryCreatorsByChannel[channel]
113+
if queryCreator == nil {
114+
Logger.Warning("Requested Metadata for non-existent channel", channel)
93115
return nil
94116
}
95117
if md, found := lc.deployedCCsByChannel[channel].Lookup(cc); found {
96-
logger.Debug("Returning metadata for channel", channel, ", chaincode", cc, ":", md)
118+
Logger.Debug("Returning metadata for channel", channel, ", chaincode", cc, ":", md)
97119
return &md
98120
}
99-
query, err := newQuery()
121+
query, err := queryCreator.NewQuery()
100122
if err != nil {
101-
logger.Error("Failed obtaining new query for channel", channel, ":", err)
123+
Logger.Error("Failed obtaining new query for channel", channel, ":", err)
102124
return nil
103125
}
104126
md, err := DeployedChaincodes(query, AcceptAll, cc)
105127
if err != nil {
106-
logger.Error("Failed querying LSCC for channel", channel, ":", err)
128+
Logger.Error("Failed querying LSCC for channel", channel, ":", err)
107129
return nil
108130
}
109131
if len(md) == 0 {
110-
logger.Info("Chaincode", cc, "isn't defined in channel", channel)
132+
Logger.Info("Chaincode", cc, "isn't defined in channel", channel)
111133
return nil
112134
}
113135

114136
return &md[0]
115137
}
116138

117-
func (lc *Lifecycle) initMetadataForChannel(channel string, newQuery QueryCreator) error {
139+
func (lc *Lifecycle) initMetadataForChannel(channel string, queryCreator QueryCreator) error {
118140
if lc.isChannelMetadataInitialized(channel) {
119141
return nil
120142
}
121143
// Create a new metadata mapping for the channel
122-
query, err := newQuery()
144+
query, err := queryCreator.NewQuery()
123145
if err != nil {
124146
return errors.WithStack(err)
125147
}
126148
ccs, err := queryChaincodeDefinitions(query, lc.installedCCs, DeployedChaincodes)
127149
if err != nil {
128150
return errors.WithStack(err)
129151
}
130-
lc.createMetadataForChannel(channel, newQuery)
131-
lc.loadMetadataForChannel(channel, ccs)
152+
lc.createMetadataForChannel(channel, queryCreator)
153+
lc.updateState(channel, ccs)
132154
return nil
133155
}
134156

@@ -146,14 +168,6 @@ func (lc *Lifecycle) isChannelMetadataInitialized(channel string) bool {
146168
return exists
147169
}
148170

149-
func (lc *Lifecycle) loadMetadataForChannel(channel string, ccs chaincode.MetadataSet) {
150-
lc.RLock()
151-
defer lc.RUnlock()
152-
for _, cc := range ccs {
153-
lc.deployedCCsByChannel[channel].Update(cc)
154-
}
155-
}
156-
157171
func (lc *Lifecycle) updateState(channel string, ccUpdate chaincode.MetadataSet) {
158172
lc.RLock()
159173
defer lc.RUnlock()
@@ -167,20 +181,23 @@ func (lc *Lifecycle) fireChangeListeners(channel string) {
167181
md := lc.deployedCCsByChannel[channel]
168182
lc.RUnlock()
169183
for _, listener := range lc.listeners {
170-
listener.LifeCycleChangeListener(channel, md.Aggregate())
184+
aggregatedMD := md.Aggregate()
185+
listener.LifeCycleChangeListener(channel, aggregatedMD)
171186
}
187+
Logger.Debug("Listeners for channel", channel, "invoked")
172188
}
173189

174190
// NewChannelSubscription subscribes to a channel
175-
func (lc *Lifecycle) NewChannelSubscription(channel string, newQuery QueryCreator) (*Subscription, error) {
191+
func (lc *Lifecycle) NewChannelSubscription(channel string, queryCreator QueryCreator) (*Subscription, error) {
176192
sub := &Subscription{
177-
lc: lc,
178-
channel: channel,
179-
newQuery: newQuery,
193+
lc: lc,
194+
channel: channel,
195+
queryCreator: queryCreator,
196+
pendingUpdates: make(chan *cceventmgmt.ChaincodeDefinition, 1),
180197
}
181198
// Initialize metadata for the channel.
182199
// This loads metadata about all installed chaincodes
183-
if err := lc.initMetadataForChannel(channel, newQuery); err != nil {
200+
if err := lc.initMetadataForChannel(channel, queryCreator); err != nil {
184201
return nil, errors.WithStack(err)
185202
}
186203
lc.fireChangeListeners(channel)

0 commit comments

Comments
 (0)