Skip to content

Commit ae6a99e

Browse files
author
Srinivasan Muralidharan
committed
[FAB-1163] range query access tx ctxt after timeout
Range query iterators accessed transaction contexts after they were deleted on timeout. Added a sleep parameter to the map chaincode's range query path with which to test timeout. Change-Id: If4fc92b49839d306593cc63667b878fc41f6588c Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent 4d8c8d7 commit ae6a99e

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

core/chaincode/exectransaction_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,28 @@ func TestQueries(t *testing.T) {
11461146
return
11471147
}
11481148

1149+
//FAB-1163- The following range query should timeout and produce an error
1150+
//the peer should handle this gracefully and not die
1151+
1152+
//save the original timeout and set a new timeout of 1 sec
1153+
origTimeout := theChaincodeSupport.executetimeout
1154+
theChaincodeSupport.executetimeout = time.Duration(1) * time.Second
1155+
1156+
//chaincode to sleep for 2 secs with timeout 1
1157+
args = util.ToChaincodeArgs(f, "marble001", "marble002", "2000")
1158+
1159+
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}}
1160+
_, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil)
1161+
if err == nil {
1162+
t.Fail()
1163+
t.Logf("expected timeout error but succeeded")
1164+
theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
1165+
return
1166+
}
1167+
1168+
//restore timeout
1169+
theChaincodeSupport.executetimeout = origTimeout
1170+
11491171
// querying for all marbles will return 101 marbles
11501172
// this query should return exactly 101 results (one call to Next())
11511173
//The following range query for "marble001" to "marble102" should return 101 marbles

core/chaincode/handler.go

+14
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,13 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) {
839839
}
840840

841841
txContext := handler.getTxContext(msg.Txid)
842+
if txContext == nil {
843+
payload := []byte("transaction context not found (timed out ?)")
844+
chaincodeLogger.Errorf("[%s]Failed to get transaction context. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
845+
serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
846+
return
847+
}
848+
842849
queryIter := handler.getQueryIterator(txContext, queryStateNext.Id)
843850

844851
if queryIter == nil {
@@ -918,6 +925,13 @@ func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) {
918925
}
919926

920927
txContext := handler.getTxContext(msg.Txid)
928+
if txContext == nil {
929+
payload := []byte("transaction context not found (timed out ?)")
930+
chaincodeLogger.Errorf("[%s]Failed to get transaction context. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
931+
serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
932+
return
933+
}
934+
921935
iter := handler.getQueryIterator(txContext, queryStateClose.Id)
922936
if iter != nil {
923937
iter.Close()

examples/chaincode/go/map/map.go

+13
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package main
1919
import (
2020
"encoding/json"
2121
"fmt"
22+
"strconv"
23+
"time"
2224

2325
"github.com/hyperledger/fabric/core/chaincode/shim"
2426
pb "github.com/hyperledger/fabric/protos/peer"
@@ -104,6 +106,12 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
104106
startKey := args[0]
105107
endKey := args[1]
106108

109+
//sleep needed to test peer's timeout behavior when using iterators
110+
stime := 0
111+
if len(args) > 2 {
112+
stime, _ = strconv.Atoi(args[2])
113+
}
114+
107115
keysIter, err := stub.GetStateByRange(startKey, endKey)
108116
if err != nil {
109117
return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
@@ -112,6 +120,11 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
112120

113121
var keys []string
114122
for keysIter.HasNext() {
123+
//if sleeptime is specied, take a nap
124+
if stime > 0 {
125+
time.Sleep(time.Duration(stime) * time.Millisecond)
126+
}
127+
115128
response, iterErr := keysIter.Next()
116129
if iterErr != nil {
117130
return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))

0 commit comments

Comments
 (0)