//Start starts a previously registered system codechain func (vm *InprocVM) Start(ctxt context.Context, ccid ccintf.CCID, args []string, env []string, attachstdin bool, attachstdout bool, reader io.Reader) error { path := ccid.ChaincodeSpec.ChaincodeID.Path ipctemplate := typeRegistry[path] if ipctemplate == nil { return fmt.Errorf(fmt.Sprintf("%s not registered", path)) } instName, _ := vm.GetVMName(ccid) ipc, err := vm.getInstance(ctxt, ipctemplate, instName, args, env) if err != nil { return fmt.Errorf(fmt.Sprintf("could not create instance for %s", instName)) } if ipc.running { return fmt.Errorf(fmt.Sprintf("chaincode running %s", path)) } //TODO VALIDITY CHECKS ? ccSupport, ok := ctxt.Value(ccintf.GetCCHandlerKey()).(ccintf.CCSupport) if !ok || ccSupport == nil { return fmt.Errorf("in-process communication generator not supplied") } ipc.running = true go func() { defer func() { if r := recover(); r != nil { inprocLogger.Criticalf("caught panic from chaincode %s", instName) } }() ipc.launchInProc(ctxt, instName, args, env, ccSupport) }() return nil }
// launchAndWaitForRegister will launch container if not already running. Use the targz to create the image if not found func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context.Context, cds *pb.ChaincodeDeploymentSpec, cID *pb.ChaincodeID, uuid string, cLang pb.ChaincodeSpec_Type, targz io.Reader) (bool, error) { chaincode := cID.Name if chaincode == "" { return false, fmt.Errorf("chaincode name not set") } chaincodeSupport.runningChaincodes.Lock() var ok bool //if its in the map, there must be a connected stream...nothing to do if _, ok = chaincodeSupport.chaincodeHasBeenLaunched(chaincode); ok { chaincodeLogger.Debugf("chaincode is running and ready: %s", chaincode) chaincodeSupport.runningChaincodes.Unlock() return true, nil } alreadyRunning := false notfy := chaincodeSupport.preLaunchSetup(chaincode) chaincodeSupport.runningChaincodes.Unlock() //launch the chaincode args, env, err := chaincodeSupport.getArgsAndEnv(cID, cLang) if err != nil { return alreadyRunning, err } chaincodeLogger.Debugf("start container: %s(networkid:%s,peerid:%s)", chaincode, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID) vmtype, _ := chaincodeSupport.getVMType(cds) sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID}, Reader: targz, Args: args, Env: env} ipcCtxt := context.WithValue(ctxt, ccintf.GetCCHandlerKey(), chaincodeSupport) resp, err := container.VMCProcess(ipcCtxt, vmtype, sir) if err != nil || (resp != nil && resp.(container.VMCResp).Err != nil) { if err == nil { err = resp.(container.VMCResp).Err } err = fmt.Errorf("Error starting container: %s", err) chaincodeSupport.runningChaincodes.Lock() delete(chaincodeSupport.runningChaincodes.chaincodeMap, chaincode) chaincodeSupport.runningChaincodes.Unlock() return alreadyRunning, err } //wait for REGISTER state select { case ok := <-notfy: if !ok { err = fmt.Errorf("registration failed for %s(networkid:%s,peerid:%s,tx:%s)", chaincode, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID, uuid) } case <-time.After(chaincodeSupport.ccStartupTimeout): err = fmt.Errorf("Timeout expired while starting chaincode %s(networkid:%s,peerid:%s,tx:%s)", chaincode, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID, uuid) } if err != nil { chaincodeLogger.Debugf("stopping due to error while launching %s", err) errIgnore := chaincodeSupport.Stop(ctxt, cds) if errIgnore != nil { chaincodeLogger.Debugf("error on stop %s(%s)", errIgnore, err) } } return alreadyRunning, err }