@@ -18,6 +18,7 @@ package chaincode
18
18
19
19
import (
20
20
"bytes"
21
+ "encoding/gob"
21
22
"fmt"
22
23
"io"
23
24
"sync"
@@ -193,7 +194,8 @@ func (handler *Handler) createTxContext(ctxt context.Context, chainID string, tx
193
194
if handler .txCtxs [txid ] != nil {
194
195
return nil , fmt .Errorf ("txid:%s exists" , txid )
195
196
}
196
- txctx := & transactionContext {chainID : chainID , signedProp : signedProp , proposal : prop , responseNotifier : make (chan * pb.ChaincodeMessage , 1 ),
197
+ txctx := & transactionContext {chainID : chainID , signedProp : signedProp ,
198
+ proposal : prop , responseNotifier : make (chan * pb.ChaincodeMessage , 1 ),
197
199
queryIteratorMap : make (map [string ]commonledger.ResultsIterator )}
198
200
handler .txCtxs [txid ] = txctx
199
201
txctx .txsimulator = getTxSimulator (ctxt )
@@ -720,38 +722,20 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) {
720
722
}
721
723
722
724
handler .putQueryIterator (txContext , iterID , rangeIter )
725
+ var payload * pb.QueryResponse
726
+ payload , err = getQueryResponse (handler , txContext , rangeIter , iterID )
723
727
724
- var keysAndValues []* pb.QueryStateKeyValue
725
- var i = 0
726
- var queryLimit = ledgerconfig .GetQueryLimit ()
727
- var qresult commonledger.QueryResult
728
- for ; i < queryLimit ; i ++ {
729
- qresult , err = rangeIter .Next ()
730
- if err != nil {
731
- chaincodeLogger .Errorf ("Failed to get query result from iterator. Sending %s" , pb .ChaincodeMessage_ERROR )
732
- return
733
- }
734
- if qresult == nil {
735
- break
736
- }
737
- kv := qresult .(* ledger.KV )
738
- keyAndValue := pb.QueryStateKeyValue {Key : kv .Key , Value : kv .Value }
739
- keysAndValues = append (keysAndValues , & keyAndValue )
740
- }
741
- if qresult != nil {
728
+ if err != nil {
742
729
rangeIter .Close ()
743
730
handler .deleteQueryIterator (txContext , iterID )
744
- //TODO log the warning that the queryLimit was exceeded. this will need to be revisited
745
- //following changes to the future paging design.
746
- chaincodeLogger .Warningf ("Query limit of %v was exceeded. Not all values meeting the criteria were returned." , queryLimit )
731
+ payload := []byte (err .Error ())
732
+ chaincodeLogger .Errorf ("Failed to get query result. Sending %s" , pb .ChaincodeMessage_ERROR )
733
+ serialSendMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR , Payload : payload , Txid : msg .Txid }
734
+ return
747
735
}
748
736
749
- //TODO - HasMore is set to false until the requery issue for the peer is resolved
750
- //FAB-2462 - Re-introduce paging for range queries and rich queries
751
- //payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, Id: iterID}
752
-
753
- payload := & pb.QueryStateResponse {KeysAndValues : keysAndValues , HasMore : false , Id : iterID }
754
- payloadBytes , err := proto .Marshal (payload )
737
+ var payloadBytes []byte
738
+ payloadBytes , err = proto .Marshal (payload )
755
739
if err != nil {
756
740
rangeIter .Close ()
757
741
handler .deleteQueryIterator (txContext , iterID )
@@ -769,6 +753,60 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) {
769
753
}()
770
754
}
771
755
756
+ func getBytes (qresult interface {}) ([]byte , error ) {
757
+ var buf bytes.Buffer
758
+ enc := gob .NewEncoder (& buf )
759
+ err := enc .Encode (qresult )
760
+ if err != nil {
761
+ return nil , err
762
+ }
763
+ return buf .Bytes (), nil
764
+ }
765
+
766
+ //getQueryResponse takes an iterator and fetch state to construct QueryResponse
767
+ func getQueryResponse (handler * Handler , txContext * transactionContext , iter commonledger.ResultsIterator ,
768
+ iterID string ) (* pb.QueryResponse , error ) {
769
+
770
+ var i = 0
771
+ var err error
772
+ var queryLimit = ledgerconfig .GetQueryLimit ()
773
+ var queryResult commonledger.QueryResult
774
+ var queryResultsBytes []* pb.QueryResultBytes
775
+
776
+ for ; i < queryLimit ; i ++ {
777
+ queryResult , err = iter .Next ()
778
+ if err != nil {
779
+ return nil , err
780
+ }
781
+ if queryResult == nil {
782
+ break
783
+ }
784
+ var resultBytes []byte
785
+ resultBytes , err = getBytes (queryResult )
786
+ if err != nil {
787
+ return nil , err
788
+ }
789
+
790
+ qresultBytes := pb.QueryResultBytes {ResultBytes : resultBytes }
791
+ queryResultsBytes = append (queryResultsBytes , & qresultBytes )
792
+ }
793
+
794
+ if queryResult == nil {
795
+ iter .Close ()
796
+ handler .deleteQueryIterator (txContext , iterID )
797
+ } else {
798
+ //TODO: remove this else part completely when paging design is implemented
799
+ //FAB-2462 - Re-introduce paging for range queries and rich queries
800
+ chaincodeLogger .Warningf ("Query limit of %v was exceeded. Not all values meeting the criteria were returned." , queryLimit )
801
+ iter .Close ()
802
+ handler .deleteQueryIterator (txContext , iterID )
803
+ }
804
+ //TODO - HasMore is set to false until the requery issue for the peer is resolved
805
+ //FAB-2462 - Re-introduce paging for range queries and rich queries
806
+ //payload := &pb.QueryResponse{Data: data, HasMore: qresult != nil, Id: iterID}
807
+ return & pb.QueryResponse {Results : queryResultsBytes , HasMore : false , Id : iterID }, nil
808
+ }
809
+
772
810
// afterQueryStateNext handles a QUERY_STATE_NEXT request from the chaincode.
773
811
func (handler * Handler ) afterQueryStateNext (e * fsm.Event , state string ) {
774
812
msg , ok := e .Args [0 ].(* pb.ChaincodeMessage )
@@ -824,39 +862,17 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) {
824
862
return
825
863
}
826
864
827
- var keysAndValues []* pb.QueryStateKeyValue
828
- var i = 0
829
- var queryLimit = ledgerconfig .GetQueryLimit ()
830
-
831
- var qresult commonledger.QueryResult
832
- var err error
833
- for ; i < queryLimit ; i ++ {
834
- qresult , err = queryIter .Next ()
835
- if err != nil {
836
- chaincodeLogger .Errorf ("Failed to get query result from iterator. Sending %s" , pb .ChaincodeMessage_ERROR )
837
- return
838
- }
839
- if qresult != nil {
840
- break
841
- }
842
- kv := qresult .(* ledger.KV )
843
- keyAndValue := pb.QueryStateKeyValue {Key : kv .Key , Value : kv .Value }
844
- keysAndValues = append (keysAndValues , & keyAndValue )
845
- }
865
+ payload , err := getQueryResponse (handler , txContext , queryIter , queryStateNext .Id )
846
866
847
- if qresult != nil {
867
+ if err != nil {
848
868
queryIter .Close ()
849
869
handler .deleteQueryIterator (txContext , queryStateNext .Id )
850
-
851
- //TODO log the warning that the queryLimit was exceeded. this will need to be revisited
852
- //following changes to the future paging design.
853
- chaincodeLogger . Warningf ( "Query limit of %v was exceeded. Not all values meeting the criteria were returned." , queryLimit )
870
+ payload := [] byte ( err . Error ())
871
+ chaincodeLogger . Errorf ( "Failed to get query result. Sending %s" , pb . ChaincodeMessage_ERROR )
872
+ serialSendMsg = & pb. ChaincodeMessage { Type : pb . ChaincodeMessage_ERROR , Payload : payload , Txid : msg . Txid }
873
+ return
854
874
}
855
875
856
- //TODO - HasMore is set to false until the requery issue for the peer is resolved
857
- //FAB-2462 - Re-introduce paging for range queries and rich queries
858
- //payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, Id: queryStateNext.Id}
859
- payload := & pb.QueryStateResponse {KeysAndValues : keysAndValues , HasMore : false , Id : queryStateNext .Id }
860
876
payloadBytes , err := proto .Marshal (payload )
861
877
if err != nil {
862
878
queryIter .Close ()
@@ -927,7 +943,7 @@ func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) {
927
943
handler .deleteQueryIterator (txContext , queryStateClose .Id )
928
944
}
929
945
930
- payload := & pb.QueryStateResponse {HasMore : false , Id : queryStateClose .Id }
946
+ payload := & pb.QueryResponse {HasMore : false , Id : queryStateClose .Id }
931
947
payloadBytes , err := proto .Marshal (payload )
932
948
if err != nil {
933
949
@@ -1010,48 +1026,27 @@ func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) {
1010
1026
}
1011
1027
1012
1028
handler .putQueryIterator (txContext , iterID , executeIter )
1029
+ var payload * pb.QueryResponse
1030
+ payload , err = getQueryResponse (handler , txContext , executeIter , iterID )
1013
1031
1014
- var keysAndValues []* pb.QueryStateKeyValue
1015
- var i = 0
1016
- var queryLimit = ledgerconfig .GetQueryLimit ()
1017
- var qresult commonledger.QueryResult
1018
- for ; i < queryLimit ; i ++ {
1019
- qresult , err = executeIter .Next ()
1020
- if err != nil {
1021
- chaincodeLogger .Errorf ("Failed to get query result from iterator. Sending %s" , pb .ChaincodeMessage_ERROR )
1022
- return
1023
- }
1024
- if qresult == nil {
1025
- break
1026
- }
1027
- queryRecord := qresult .(* ledger.QueryRecord )
1028
- keyAndValue := pb.QueryStateKeyValue {Key : queryRecord .Key , Value : queryRecord .Record }
1029
- keysAndValues = append (keysAndValues , & keyAndValue )
1030
- }
1031
-
1032
- if qresult != nil {
1032
+ if err != nil {
1033
1033
executeIter .Close ()
1034
1034
handler .deleteQueryIterator (txContext , iterID )
1035
-
1036
- //TODO log the warning that the queryLimit was exceeded. this will need to be revisited
1037
- //following changes to the future paging design.
1038
- chaincodeLogger . Warningf ( "Query limit of %v was exceeded. Not all values meeting the criteria were returned." , queryLimit )
1035
+ payload := [] byte ( err . Error ())
1036
+ chaincodeLogger . Errorf ( "Failed to get query result. Sending %s" , pb . ChaincodeMessage_ERROR )
1037
+ serialSendMsg = & pb. ChaincodeMessage { Type : pb . ChaincodeMessage_ERROR , Payload : payload , Txid : msg . Txid }
1038
+ return
1039
1039
}
1040
1040
1041
1041
var payloadBytes []byte
1042
-
1043
- //TODO - HasMore is set to false until the requery issue for the peer is resolved
1044
- //FAB-2462 - Re-introduce paging for range queries and rich queries
1045
- //payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, Id: iterID}
1046
- payload := & pb.QueryStateResponse {KeysAndValues : keysAndValues , HasMore : false , Id : iterID }
1047
1042
payloadBytes , err = proto .Marshal (payload )
1048
1043
if err != nil {
1049
1044
executeIter .Close ()
1050
1045
handler .deleteQueryIterator (txContext , iterID )
1051
1046
1052
1047
// Send error msg back to chaincode. GetState will not trigger event
1053
1048
payload := []byte (err .Error ())
1054
- chaincodeLogger .Errorf ("Failed marshall resopnse . Sending %s" , pb .ChaincodeMessage_ERROR )
1049
+ chaincodeLogger .Errorf ("Failed marshall response . Sending %s" , pb .ChaincodeMessage_ERROR )
1055
1050
serialSendMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR , Payload : payload , Txid : msg .Txid }
1056
1051
return
1057
1052
}
@@ -1128,41 +1123,19 @@ func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) {
1128
1123
1129
1124
handler .putQueryIterator (txContext , iterID , historyIter )
1130
1125
1131
- // TODO QueryStateKeyValue can be re-used for now since history records have a string (TxID)
1132
- // and value (value). But we'll need to use another structure if we add other fields like timestamp.
1133
- var keysAndValues []* pb.QueryStateKeyValue
1134
- var i = 0
1135
- var queryLimit = ledgerconfig .GetQueryLimit ()
1136
- var qresult commonledger.QueryResult
1137
- for ; i < queryLimit ; i ++ {
1138
- qresult , err = historyIter .Next ()
1139
- if err != nil {
1140
- chaincodeLogger .Errorf ("Failed to get query result from iterator. Sending %s" , pb .ChaincodeMessage_ERROR )
1141
- return
1142
- }
1143
- if qresult == nil {
1144
- break
1145
- }
1146
- queryRecord := qresult .(* ledger.KeyModification )
1147
- keyAndValue := pb.QueryStateKeyValue {Key : queryRecord .TxID , Value : queryRecord .Value }
1148
- keysAndValues = append (keysAndValues , & keyAndValue )
1149
- }
1126
+ var payload * pb.QueryResponse
1127
+ payload , err = getQueryResponse (handler , txContext , historyIter , iterID )
1150
1128
1151
- if qresult != nil {
1129
+ if err != nil {
1152
1130
historyIter .Close ()
1153
1131
handler .deleteQueryIterator (txContext , iterID )
1154
-
1155
- //TODO log the warning that the queryLimit was exceeded. this will need to be revisited
1156
- //following changes to the future paging design.
1157
- chaincodeLogger . Warningf ( "Query limit of %v was exceeded. Not all values meeting the criteria were returned." , queryLimit )
1132
+ payload := [] byte ( err . Error ())
1133
+ chaincodeLogger . Errorf ( "Failed to get query result. Sending %s" , pb . ChaincodeMessage_ERROR )
1134
+ serialSendMsg = & pb. ChaincodeMessage { Type : pb . ChaincodeMessage_ERROR , Payload : payload , Txid : msg . Txid }
1135
+ return
1158
1136
}
1159
1137
1160
1138
var payloadBytes []byte
1161
-
1162
- //TODO - HasMore is set to false until the requery issue for the peer is resolved
1163
- //FAB-2462 - Re-introduce paging for range queries and rich queries
1164
- //payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, Id: iterID}
1165
- payload := & pb.QueryStateResponse {KeysAndValues : keysAndValues , HasMore : false , Id : iterID }
1166
1139
payloadBytes , err = proto .Marshal (payload )
1167
1140
if err != nil {
1168
1141
historyIter .Close ()
0 commit comments