Skip to content

Commit ae03390

Browse files
committed
[FAB-7134] Deploy couchdb indexes upon cc install
This change set will automatically deploy any couchdb indexes that are defined in the chaincode package upon chaincode installation on the peer, to any joined channel's state database where the chaincode is already instantiated. If the chaincode gets instantiated after install, the indexes will automatically get deployed to couchdb at instantiation/upgrade time (see FAB-7581 for that logic). Change-Id: Idb6e374d231d7d8bc0a87597b8f40c4635fd96c8 Signed-off-by: David Enyeart <enyeart@us.ibm.com>
1 parent 66d785b commit ae03390

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

core/common/ccprovider/cc_statedb_artifacts_provider.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const (
2121
// ExtractStatedbArtifactsAsTarbytes extracts the statedb artifacts from the code package tar and create a statedb artifact tar.
2222
// The state db artifacts are expected to contain state db specific artifacts such as index specification in the case of couchdb.
2323
// This function is intented to be used during chaincode instantiate/upgrade so that statedb artifacts can be created.
24-
func ExtractStatedbArtifactsAsTarbytes(ccname, ccversion string) (installed bool, statedbArtifactsTar []byte, err error) {
24+
func ExtractStatedbArtifactsForChaincode(ccname, ccversion string) (installed bool, statedbArtifactsTar []byte, err error) {
2525
ccpackage, err := GetChaincodeFromFS(ccname, ccversion)
2626
if err != nil {
2727
// TODO for now, we assume that an error indicates that the chaincode is not installed on the peer.
@@ -31,12 +31,21 @@ func ExtractStatedbArtifactsAsTarbytes(ccname, ccversion string) (installed bool
3131
return false, nil, nil
3232
}
3333

34+
statedbArtifactsTar, err = ExtractStatedbArtifactsFromCCPackage(ccpackage)
35+
return true, statedbArtifactsTar, err
36+
}
37+
38+
// ExtractStatedbArtifactsFromCCPackage extracts the statedb artifacts from the code package tar and create a statedb artifact tar.
39+
// The state db artifacts are expected to contain state db specific artifacts such as index specification in the case of couchdb.
40+
// This function is called during chaincode instantiate/upgrade (from above), and from install, so that statedb artifacts can be created.
41+
func ExtractStatedbArtifactsFromCCPackage(ccpackage CCPackage) (statedbArtifactsTar []byte, err error) {
42+
3443
cds := ccpackage.GetDepSpec()
3544
is := bytes.NewReader(cds.CodePackage)
3645
gr, err := gzip.NewReader(is)
3746
if err != nil {
3847
ccproviderLogger.Errorf("Failure opening codepackage gzip stream: %s", err)
39-
return true, nil, err
48+
return nil, err
4049
}
4150
tr := tar.NewReader(gr)
4251
statedbTarBuffer := bytes.NewBuffer(nil)
@@ -52,25 +61,25 @@ func ExtractStatedbArtifactsAsTarbytes(ccname, ccversion string) (installed bool
5261
}
5362

5463
if err != nil {
55-
return true, nil, err
64+
return nil, err
5665
}
5766
ccproviderLogger.Debugf("header.Name = %s", header.Name)
5867
if !strings.HasPrefix(header.Name, ccPackageStatedbDir) {
5968
continue
6069
}
6170
if err = tw.WriteHeader(header); err != nil {
6271
ccproviderLogger.Error("Error adding header to statedb tar:", err, header.Name)
63-
return true, nil, err
72+
return nil, err
6473
}
6574
if _, err := io.Copy(tw, tr); err != nil {
6675
ccproviderLogger.Error("Error copying file to statedb tar:", err, header.Name)
67-
return true, nil, err
76+
return nil, err
6877
}
6978
ccproviderLogger.Debug("Wrote file to statedb tar:", header.Name)
7079
}
7180
if err = tw.Close(); err != nil {
72-
return true, nil, err
81+
return nil, err
7382
}
7483
ccproviderLogger.Debug("Created statedb artifact tar")
75-
return true, statedbTarBuffer.Bytes(), nil
84+
return statedbTarBuffer.Bytes(), nil
7685
}

core/ledger/cceventmgmt/defs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ func (p *chaincodeInfoProviderImpl) IsChaincodeDeployed(chainid string, chaincod
5050

5151
// RetrieveChaincodeArtifacts implements function in the interface ChaincodeInfoProvider
5252
func (p *chaincodeInfoProviderImpl) RetrieveChaincodeArtifacts(chaincodeDefinition *ChaincodeDefinition) (installed bool, dbArtifactsTar []byte, err error) {
53-
return ccprovider.ExtractStatedbArtifactsAsTarbytes(chaincodeDefinition.Name, chaincodeDefinition.Version)
53+
return ccprovider.ExtractStatedbArtifactsForChaincode(chaincodeDefinition.Name, chaincodeDefinition.Version)
5454
}

core/scc/lscc/lscc.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/hyperledger/fabric/core/common/ccprovider"
3030
"github.com/hyperledger/fabric/core/common/privdata"
3131
"github.com/hyperledger/fabric/core/common/sysccprovider"
32+
"github.com/hyperledger/fabric/core/ledger/cceventmgmt"
3233
"github.com/hyperledger/fabric/core/peer"
3334
"github.com/hyperledger/fabric/core/policy"
3435
"github.com/hyperledger/fabric/core/policyprovider"
@@ -395,6 +396,27 @@ func (lscc *lifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, ccb
395396
return err
396397
}
397398

399+
// Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
400+
statedbArtifactsTar, err := ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
401+
if err != nil {
402+
return err
403+
}
404+
405+
chaincodeDefinition := &cceventmgmt.ChaincodeDefinition{
406+
Name: ccpack.GetChaincodeData().Name,
407+
Version: ccpack.GetChaincodeData().Version,
408+
Hash: ccpack.GetId()} // Note - The chaincode 'id' is the hash of chaincode's (CodeHash || MetaDataHash), aka fingerprint
409+
410+
// HandleChaincodeInstall will apply any statedb artifacts (e.g. couchdb indexes) to
411+
// any channel's statedb where the chaincode is already instantiated
412+
// Note - this step is done prior to PutChaincodeToLocalStorage() since this step is idempotent and harmless until endorsements start,
413+
// that is, if there are errors deploying the indexes the chaincode install can safely be re-attempted later.
414+
err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, statedbArtifactsTar)
415+
if err != nil {
416+
return err
417+
}
418+
419+
// Finally, if everything is good above, install the chaincode to local peer file system so that endorsements can start
398420
if err = lscc.support.PutChaincodeToLocalStorage(ccpack); err != nil {
399421
return err
400422
}

core/scc/lscc/lscc_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/hyperledger/fabric/core/common/ccprovider"
2828
"github.com/hyperledger/fabric/core/common/sysccprovider"
2929
cutil "github.com/hyperledger/fabric/core/container/util"
30+
"github.com/hyperledger/fabric/core/ledger/cceventmgmt"
3031
"github.com/hyperledger/fabric/core/mocks/scc/lscc"
3132
"github.com/hyperledger/fabric/core/policy"
3233
policymocks "github.com/hyperledger/fabric/core/policy/mocks"
@@ -84,6 +85,11 @@ func constructDeploymentSpec(name string, path string, version string, initArgs
8485

8586
//TestInstall tests the install function with various inputs
8687
func TestInstall(t *testing.T) {
88+
89+
// Initialize cceventmgmt Mgr
90+
// TODO cceventmgmt singleton should be refactored out of peer in the future. See CR 16549 for details.
91+
cceventmgmt.Initialize()
92+
8793
scc := &lifeCycleSysCC{support: &lscc.MockSupport{}}
8894
stub := shim.NewMockStub("lscc", scc)
8995
res := stub.MockInit("1", nil)

0 commit comments

Comments
 (0)