github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/examples/ccchecker/ccchecker.go (about) 1 /* 2 Copyright IBM Corp. 2016 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 main 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "sync" 25 "time" 26 27 "golang.org/x/net/context" 28 29 "github.com/hyperledger/fabric/examples/ccchecker/chaincodes" 30 "github.com/hyperledger/fabric/peer/common" 31 ) 32 33 //global ccchecker params 34 var ccchecker *CCChecker 35 36 //CCChecker encapsulates ccchecker properties and runtime 37 type CCChecker struct { 38 //Chaincodes to do ccchecker over (see ccchecker.json for defaults) 39 Chaincodes []*chaincodes.CCClient 40 //TimeoutToAbortSecs abort deadline 41 TimeoutToAbortSecs int 42 //ChainName name of the chain 43 ChainName string 44 } 45 46 //LoadCCCheckerParams read the ccchecker params from a file 47 func LoadCCCheckerParams(file string) error { 48 var b []byte 49 var err error 50 if b, err = ioutil.ReadFile(file); err != nil { 51 return fmt.Errorf("Cannot read config file %s\n", err) 52 } 53 sp := &CCChecker{} 54 err = json.Unmarshal(b, &sp) 55 if err != nil { 56 return fmt.Errorf("error unmarshalling ccchecker: %s\n", err) 57 } 58 59 ccchecker = &CCChecker{} 60 id := 0 61 for _, scc := range sp.Chaincodes { 62 //concurrency <=0 will be dropped 63 if scc.Concurrency > 0 { 64 for i := 0; i < scc.Concurrency; i++ { 65 tmp := &chaincodes.CCClient{} 66 *tmp = *scc 67 tmp.ID = id 68 id = id + 1 69 ccchecker.Chaincodes = append(ccchecker.Chaincodes, tmp) 70 } 71 } 72 } 73 74 ccchecker.TimeoutToAbortSecs = sp.TimeoutToAbortSecs 75 ccchecker.ChainName = sp.ChainName 76 77 return nil 78 } 79 80 //CCCheckerInit assigns shadow chaincode to each of the CCClient from registered shadow chaincodes 81 func CCCheckerInit() { 82 if ccchecker == nil { 83 fmt.Printf("LoadCCCheckerParams needs to be called before init\n") 84 os.Exit(1) 85 } 86 87 if err := chaincodes.RegisterCCClients(ccchecker.Chaincodes); err != nil { 88 panic(fmt.Sprintf("%s", err)) 89 } 90 } 91 92 //CCCheckerRun main loops that will run the tests and cleanup 93 func CCCheckerRun(orderingEndpoint string, report bool, verbose bool) error { 94 //connect with Broadcast client 95 bc, err := common.GetBroadcastClient(orderingEndpoint, false, "") 96 if err != nil { 97 return err 98 } 99 defer bc.Close() 100 101 ec, err := common.GetEndorserClient() 102 if err != nil { 103 return err 104 } 105 106 signer, err := common.GetDefaultSigner() 107 if err != nil { 108 return err 109 } 110 111 //when the wait's timeout and get out of ccchecker, we 112 //cancel and release all goroutines 113 ctxt, cancel := context.WithCancel(context.Background()) 114 defer cancel() 115 116 var ccsWG sync.WaitGroup 117 ccsWG.Add(len(ccchecker.Chaincodes)) 118 119 //an anonymous struct to hold failures 120 var failures struct { 121 sync.Mutex 122 failedCCClients int 123 } 124 125 //run the invokes 126 ccerrs := make([]error, len(ccchecker.Chaincodes)) 127 for _, cc := range ccchecker.Chaincodes { 128 go func(cc2 *chaincodes.CCClient) { 129 if ccerrs[cc2.ID] = cc2.Run(ctxt, ccchecker.ChainName, bc, ec, signer, &ccsWG); ccerrs[cc2.ID] != nil { 130 failures.Lock() 131 failures.failedCCClients = failures.failedCCClients + 1 132 failures.Unlock() 133 } 134 }(cc) 135 } 136 137 //wait or timeout 138 err = ccchecker.wait(&ccsWG) 139 140 //verify results 141 if err == nil && failures.failedCCClients < len(ccchecker.Chaincodes) { 142 ccsWG = sync.WaitGroup{} 143 ccsWG.Add(len(ccchecker.Chaincodes) - failures.failedCCClients) 144 for _, cc := range ccchecker.Chaincodes { 145 go func(cc2 *chaincodes.CCClient) { 146 if ccerrs[cc2.ID] == nil { 147 ccerrs[cc2.ID] = cc2.Validate(ctxt, ccchecker.ChainName, bc, ec, signer, &ccsWG) 148 } else { 149 fmt.Printf("Ignoring [%v] for validation as it returned err %s\n", cc2, ccerrs[cc2.ID]) 150 } 151 }(cc) 152 } 153 154 //wait or timeout 155 err = ccchecker.wait(&ccsWG) 156 } 157 158 if report { 159 for _, cc := range ccchecker.Chaincodes { 160 cc.Report(verbose, ccchecker.ChainName) 161 } 162 } 163 164 return err 165 } 166 167 func (s *CCChecker) wait(ccsWG *sync.WaitGroup) error { 168 done := make(chan struct{}) 169 go func() { 170 ccsWG.Wait() 171 done <- struct{}{} 172 }() 173 select { 174 case <-done: 175 return nil 176 case <-time.After(time.Duration(s.TimeoutToAbortSecs) * time.Second): 177 return fmt.Errorf("Aborting due to timeoutout!!") 178 } 179 }