@@ -20,6 +20,7 @@ import (
20
20
"errors"
21
21
"reflect"
22
22
23
+ "github.com/hyperledger/fabric/core/ledger"
23
24
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt"
24
25
logging "github.com/op/go-logging"
25
26
)
@@ -42,7 +43,6 @@ func newNsRWs() *nsRWs {
42
43
type LockBasedTxSimulator struct {
43
44
RWLockQueryExecutor
44
45
rwMap map [string ]* nsRWs
45
- done bool
46
46
}
47
47
48
48
func (s * LockBasedTxSimulator ) getOrCreateNsRWHolder (ns string ) * nsRWs {
@@ -57,6 +57,7 @@ func (s *LockBasedTxSimulator) getOrCreateNsRWHolder(ns string) *nsRWs {
57
57
58
58
// GetState implements method in interface `ledger.TxSimulator`
59
59
func (s * LockBasedTxSimulator ) GetState (ns string , key string ) ([]byte , error ) {
60
+ s .checkDone ()
60
61
logger .Debugf ("Get state [%s:%s]" , ns , key )
61
62
nsRWs := s .getOrCreateNsRWHolder (ns )
62
63
// check if it was written
@@ -106,11 +107,24 @@ func (s *LockBasedTxSimulator) GetState(ns string, key string) ([]byte, error) {
106
107
return value , nil
107
108
}
108
109
110
+ // GetStateRangeScanIterator implements method in interface `ledger.QueryExecutor`
111
+ // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key
112
+ // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey
113
+ // can be supplied as empty strings. However, a full scan shuold be used judiciously for performance reasons.
114
+ // TODO: The range scan queries still do not support Read-Your_Write (RYW)
115
+ // semantics as it is still not agreed upon whether we want RYW model or not.
116
+ func (s * LockBasedTxSimulator ) GetStateRangeScanIterator (namespace string , startKey string , endKey string ) (ledger.ResultsIterator , error ) {
117
+ s .checkDone ()
118
+ scanner , err := s .txmgr .getCommittedRangeScanner (namespace , startKey , endKey )
119
+ if err != nil {
120
+ return nil , err
121
+ }
122
+ return & sKVItr {scanner , s }, nil
123
+ }
124
+
109
125
// SetState implements method in interface `ledger.TxSimulator`
110
126
func (s * LockBasedTxSimulator ) SetState (ns string , key string , value []byte ) error {
111
- if s .done {
112
- panic ("This method should not be called after calling Done()" )
113
- }
127
+ s .checkDone ()
114
128
nsRWs := s .getOrCreateNsRWHolder (ns )
115
129
kvWrite , ok := nsRWs .writeMap [key ]
116
130
if ok {
@@ -126,12 +140,6 @@ func (s *LockBasedTxSimulator) DeleteState(ns string, key string) error {
126
140
return s .SetState (ns , key , nil )
127
141
}
128
142
129
- // Done implements method in interface `ledger.TxSimulator`
130
- func (s * LockBasedTxSimulator ) Done () {
131
- s .done = true
132
- s .txmgr .commitRWLock .RUnlock ()
133
- }
134
-
135
143
func (s * LockBasedTxSimulator ) getTxReadWriteSet () * txmgmt.TxReadWriteSet {
136
144
txRWSet := & txmgmt.TxReadWriteSet {}
137
145
sortedNamespaces := getSortedKeys (s .rwMap )
@@ -186,15 +194,43 @@ func (s *LockBasedTxSimulator) GetTxSimulationResults() ([]byte, error) {
186
194
187
195
// SetStateMultipleKeys implements method in interface `ledger.TxSimulator`
188
196
func (s * LockBasedTxSimulator ) SetStateMultipleKeys (namespace string , kvs map [string ][]byte ) error {
189
- return errors . New ( "Not yet implemented" )
190
- }
191
-
192
- // CopyState implements method in interface `ledger.TxSimulator`
193
- func ( s * LockBasedTxSimulator ) CopyState ( sourceNamespace string , targetNamespace string ) error {
194
- return errors . New ( "Not yet implemented" )
197
+ for k , v := range kvs {
198
+ if err := s . SetState ( namespace , k , v ); err != nil {
199
+ return err
200
+ }
201
+ }
202
+ return nil
195
203
}
196
204
197
205
// ExecuteUpdate implements method in interface `ledger.TxSimulator`
198
206
func (s * LockBasedTxSimulator ) ExecuteUpdate (query string ) error {
199
207
return errors .New ("Not supported by KV data model" )
200
208
}
209
+
210
+ type sKVItr struct {
211
+ scanner * kvScanner
212
+ simulator * LockBasedTxSimulator
213
+ }
214
+
215
+ // Next implements Next() method in ledger.ResultsIterator
216
+ func (itr * sKVItr ) Next () (ledger.QueryResult , error ) {
217
+ committedKV , err := itr .scanner .next ()
218
+ if err != nil {
219
+ return nil , err
220
+ }
221
+ if committedKV == nil {
222
+ return nil , nil
223
+ }
224
+ if committedKV .isDelete () {
225
+ return itr .Next ()
226
+ }
227
+ nsRWs := itr .simulator .getOrCreateNsRWHolder (itr .scanner .namespace )
228
+ nsRWs .readMap [committedKV .key ] = & kvReadCache {
229
+ & txmgmt.KVRead {Key : committedKV .key , Version : committedKV .version }, committedKV .value }
230
+ return & ledger.KV {Key : committedKV .key , Value : committedKV .value }, nil
231
+ }
232
+
233
+ // Close implements Close() method in ledger.ResultsIterator
234
+ func (itr * sKVItr ) Close () {
235
+ itr .scanner .close ()
236
+ }
0 commit comments