github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/core/common/ccprovider/cc_statedb_artifacts_provider.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package ccprovider 8 9 import ( 10 "archive/tar" 11 "bytes" 12 "fmt" 13 "io" 14 "io/ioutil" 15 "path/filepath" 16 "strings" 17 ) 18 19 // tarFileEntry encapsulates a file entry and it's contents inside a tar 20 type TarFileEntry struct { 21 FileHeader *tar.Header 22 FileContent []byte 23 } 24 25 // ExtractStatedbArtifactsAsTarbytes extracts the statedb artifacts from the code package tar and create a statedb artifact tar. 26 // The state db artifacts are expected to contain state db specific artifacts such as index specification in the case of couchdb. 27 // This function is intended to be used during chaincode instantiate/upgrade so that statedb artifacts can be created. 28 func ExtractStatedbArtifactsForChaincode(ccNameVersion string) (installed bool, statedbArtifactsTar []byte, err error) { 29 ccpackage, err := GetChaincodeFromFS(ccNameVersion) 30 if err != nil { 31 // TODO for now, we assume that an error indicates that the chaincode is not installed on the peer. 32 // However, we need a way to differentiate between the 'not installed' and a general error so that on general error, 33 // we can abort the chaincode instantiate/upgrade/install operation. 34 ccproviderLogger.Infof("Error while loading installation package for ccNameVersion=%s Err=%s", ccNameVersion, err) 35 return false, nil, nil 36 } 37 38 statedbArtifactsTar, err = ExtractStatedbArtifactsFromCCPackage(ccpackage) 39 return true, statedbArtifactsTar, err 40 } 41 42 // ExtractStatedbArtifactsFromCCPackage extracts the statedb artifacts from the code package tar and create a statedb artifact tar. 43 // The state db artifacts are expected to contain state db specific artifacts such as index specification in the case of couchdb. 44 // This function is called during chaincode instantiate/upgrade (from above), and from install, so that statedb artifacts can be created. 45 func ExtractStatedbArtifactsFromCCPackage(ccpackage CCPackage) (statedbArtifactsTar []byte, err error) { 46 cds := ccpackage.GetDepSpec() 47 48 metaprov, err := MetadataAsTarEntries(cds.CodePackage) 49 if err != nil { 50 ccproviderLogger.Infof("invalid deployment spec: %s", err) 51 return nil, fmt.Errorf("invalid deployment spec") 52 } 53 return metaprov, nil 54 } 55 56 // ExtractFileEntries extract file entries from the given `tarBytes`. A file entry is included in the 57 // returned results only if it is located in a directory under the indicated databaseType directory 58 // Example for chaincode indexes: 59 // "META-INF/statedb/couchdb/indexes/indexColorSortName.json" 60 // Example for collection scoped indexes: 61 // "META-INF/statedb/couchdb/collections/collectionMarbles/indexes/indexCollMarbles.json" 62 // An empty string will have the effect of returning all statedb metadata. This is useful in validating an 63 // archive in the future with multiple database types 64 func ExtractFileEntries(tarBytes []byte, databaseType string) (map[string][]*TarFileEntry, error) { 65 66 indexArtifacts := map[string][]*TarFileEntry{} 67 tarReader := tar.NewReader(bytes.NewReader(tarBytes)) 68 for { 69 hdr, err := tarReader.Next() 70 if err == io.EOF { 71 // end of tar archive 72 break 73 } 74 if err != nil { 75 return nil, err 76 } 77 if hdr.Typeflag == tar.TypeDir { 78 continue 79 } 80 81 //split the directory from the full name 82 dir, _ := filepath.Split(hdr.Name) 83 //remove the ending slash 84 if strings.HasPrefix(hdr.Name, "META-INF/statedb/"+databaseType) { 85 fileContent, err := ioutil.ReadAll(tarReader) 86 if err != nil { 87 return nil, err 88 } 89 indexArtifacts[filepath.Clean(dir)] = append(indexArtifacts[filepath.Clean(dir)], &TarFileEntry{FileHeader: hdr, FileContent: fileContent}) 90 } 91 } 92 93 return indexArtifacts, nil 94 }