Skip to content

Commit

Permalink
Merge "FAB-2767 expose chaincode timeout as a property"
Browse files Browse the repository at this point in the history
  • Loading branch information
binhn authored and Gerrit Code Review committed Mar 15, 2017
2 parents dba3995 + 17219e2 commit 14055d7
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 5 deletions.
12 changes: 12 additions & 0 deletions core/chaincode/chaincode_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@ func NewChaincodeSupport(getPeerEndpoint func() (*pb.PeerEndpoint, error), userr
theChaincodeSupport.keepalive = time.Duration(t) * time.Second
}

//default chaincode execute timeout is 30000ms (30 secs)
execto := 30000
if eto := viper.GetInt("chaincode.executetimeout"); eto <= 1000 {
chaincodeLogger.Errorf("Invalid execute timeout value %d (should be at least 1000ms) defaulting to %d ms", eto, execto)
} else {
chaincodeLogger.Debugf("Setting execute timeout value to %d ms", eto)
execto = eto
}

theChaincodeSupport.executetimeout = time.Duration(execto) * time.Millisecond

viper.SetEnvPrefix("CORE")
viper.AutomaticEnv()
replacer := strings.NewReplacer(".", "_")
Expand Down Expand Up @@ -208,6 +219,7 @@ type ChaincodeSupport struct {
keepalive time.Duration
chaincodeLogLevel string
logFormat string
executetimeout time.Duration
}

// DuplicateChaincodeHandlerError returned if attempt to register same chaincodeID while a stream already exists.
Expand Down
6 changes: 1 addition & 5 deletions core/chaincode/exectransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package chaincode
import (
"errors"
"fmt"
"time"

"github.com/golang/protobuf/proto"
"golang.org/x/net/context"
Expand Down Expand Up @@ -57,9 +56,6 @@ func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}
return nil, nil, fmt.Errorf("Failed to stablish stream to container %s", chaincode)
}

// TODO: Need to comment next line and uncomment call to getTimeout, when transaction blocks are being created
timeout := time.Duration(30000) * time.Millisecond

if err != nil {
return nil, nil, fmt.Errorf("Failed to retrieve chaincode spec(%s)", err)
}
Expand All @@ -70,7 +66,7 @@ func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}
return nil, nil, fmt.Errorf("Failed to transaction message(%s)", err)
}

resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout)
resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, theChaincodeSupport.executetimeout)
if err != nil {
// Rollback transaction
return nil, nil, fmt.Errorf("Failed to execute transaction (%s)", err)
Expand Down
124 changes: 124 additions & 0 deletions examples/chaincode/go/sleeper/sleeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

// Sleeper chaincode sleeps and works with one state variable
// Init - 1 param, a sleep time in millisecs
// Invoke - 4 or 3 params, "put" or "get", value to set and sleep time in millisecs
//
// Sleeper can be used to test the "chaincode.executetimeout" property

import (
"fmt"
"strconv"
"time"

"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)

// SleeperChaincode example simple Chaincode implementation
type SleeperChaincode struct {
}

func (t *SleeperChaincode) sleep(sleepTime string) {
st, _ := strconv.Atoi(sleepTime)
if st >= 0 {
time.Sleep(time.Duration(st) * time.Millisecond)
}
}

// Init initializes chaincode...all it does is sleep a bi
func (t *SleeperChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
args := stub.GetStringArgs()

if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}

sleepTime := args[0]

t.sleep(sleepTime)

return shim.Success(nil)
}

// Invoke sets key/value and sleeps a bit
func (t *SleeperChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "put" {
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}

// Make payment of X units from A to B
return t.invoke(stub, args)
} else if function == "get" {
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}

// the old "Query" is now implemtned in invoke
return t.query(stub, args)
}

return shim.Error("Invalid invoke function name. Expecting \"put\" or \"get\"")
}

// Transaction makes payment of X units from A to B
func (t *SleeperChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// set state
key := args[0]
val := args[1]

err := stub.PutState(key, []byte(val))
if err != nil {
return shim.Error(err.Error())
}

sleepTime := args[2]

//sleep for a bit
t.sleep(sleepTime)

return shim.Success([]byte("OK"))
}

// query callback representing the query of a chaincode
func (t *SleeperChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
key := args[0]

// Get the state from the ledger
val, err := stub.GetState(key)
if err != nil {
return shim.Error(err.Error())
}

sleepTime := args[1]

//sleep for a bit
t.sleep(sleepTime)

return shim.Success(val)
}

func main() {
err := shim.Start(new(SleeperChaincode))
if err != nil {
fmt.Printf("Error starting Sleeper chaincode: %s", err)
}
}
5 changes: 5 additions & 0 deletions peer/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ chaincode:
# to come through. 1sec should be plenty for chaincode unit tests
startuptimeout: 300000

# timeout in millisecs for invokes and initialize commands
# this timeout is used by all chaincodes in all the channels including
# system chaincodes. Default is 30000ms (30 seconds)
executetimeout: 30000

#timeout in millisecs for deploying chaincode from a remote repository.
deploytimeout: 30000

Expand Down

0 comments on commit 14055d7

Please sign in to comment.