Skip to content

Commit 445fbdb

Browse files
committed
Added support for advance KV-queries
https://jira.hyperledger.org/browse/FAB-192 Change-Id: I04bf6a03247b38fdc49b7084182c4f70e09c7cdd Signed-off-by: manish <[email protected]>
1 parent efdab32 commit 445fbdb

File tree

8 files changed

+474
-34
lines changed

8 files changed

+474
-34
lines changed

core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb_query_executer.go

+5
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,8 @@ func (q *CouchDBQueryExecutor) GetTransactionsForKey(namespace string, key strin
5656
func (q *CouchDBQueryExecutor) ExecuteQuery(query string) (ledger.ResultsIterator, error) {
5757
return nil, errors.New("Not supported by KV data model")
5858
}
59+
60+
// Done implements method in interface `ledger.QueryExecutor`
61+
func (q *CouchDBQueryExecutor) Done() {
62+
//TODO - acquire lock when constructing and release the lock here
63+
}

core/ledger/kvledger/txmgmt/lockbasedtxmgmt/lockbased_query_executer.go

+57-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ import (
2525
// RWLockQueryExecutor is a query executor used in `LockBasedTxMgr`
2626
type RWLockQueryExecutor struct {
2727
txmgr *LockBasedTxMgr
28+
done bool
2829
}
2930

3031
// GetState implements method in interface `ledger.QueryExecutor`
3132
func (q *RWLockQueryExecutor) GetState(ns string, key string) ([]byte, error) {
33+
q.checkDone()
3234
var value []byte
3335
var err error
3436
if value, _, err = q.txmgr.getCommittedValueAndVersion(ns, key); err != nil {
@@ -39,12 +41,29 @@ func (q *RWLockQueryExecutor) GetState(ns string, key string) ([]byte, error) {
3941

4042
// GetStateMultipleKeys implements method in interface `ledger.QueryExecutor`
4143
func (q *RWLockQueryExecutor) GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) {
42-
return nil, errors.New("Not yet implemented")
44+
var results [][]byte
45+
var value []byte
46+
var err error
47+
for _, key := range keys {
48+
if value, err = q.GetState(namespace, key); err != nil {
49+
return nil, err
50+
}
51+
results = append(results, value)
52+
}
53+
return results, nil
4354
}
4455

4556
// GetStateRangeScanIterator implements method in interface `ledger.QueryExecutor`
57+
// startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key
58+
// and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey
59+
// can be supplied as empty strings. However, a full scan shuold be used judiciously for performance reasons.
4660
func (q *RWLockQueryExecutor) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (ledger.ResultsIterator, error) {
47-
return nil, errors.New("Not yet implemented")
61+
q.checkDone()
62+
scanner, err := q.txmgr.getCommittedRangeScanner(namespace, startKey, endKey)
63+
if err != nil {
64+
return nil, err
65+
}
66+
return &qKVItr{scanner}, nil
4867
}
4968

5069
// GetTransactionsForKey - implements method in interface `ledger.QueryExecutor`
@@ -56,3 +75,39 @@ func (q *RWLockQueryExecutor) GetTransactionsForKey(namespace string, key string
5675
func (q *RWLockQueryExecutor) ExecuteQuery(query string) (ledger.ResultsIterator, error) {
5776
return nil, errors.New("Not supported by KV data model")
5877
}
78+
79+
// Done implements method in interface `ledger.TxSimulator`
80+
func (q *RWLockQueryExecutor) Done() {
81+
q.done = true
82+
q.txmgr.commitRWLock.RUnlock()
83+
}
84+
85+
func (q *RWLockQueryExecutor) checkDone() {
86+
if q.done {
87+
panic("This method should not be called after calling Done()")
88+
}
89+
}
90+
91+
type qKVItr struct {
92+
s *kvScanner
93+
}
94+
95+
// Next implements Next() method in ledger.ResultsIterator
96+
func (itr *qKVItr) Next() (ledger.QueryResult, error) {
97+
committedKV, err := itr.s.next()
98+
if err != nil {
99+
return nil, err
100+
}
101+
if committedKV == nil {
102+
return nil, nil
103+
}
104+
if committedKV.isDelete() {
105+
return itr.Next()
106+
}
107+
return &ledger.KV{Key: committedKV.key, Value: committedKV.value}, nil
108+
}
109+
110+
// Close implements Close() method in ledger.ResultsIterator
111+
func (itr *qKVItr) Close() {
112+
itr.s.close()
113+
}

core/ledger/kvledger/txmgmt/lockbasedtxmgmt/lockbased_tx_simulator.go

+52-16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"errors"
2121
"reflect"
2222

23+
"github.com/hyperledger/fabric/core/ledger"
2324
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt"
2425
logging "github.com/op/go-logging"
2526
)
@@ -42,7 +43,6 @@ func newNsRWs() *nsRWs {
4243
type LockBasedTxSimulator struct {
4344
RWLockQueryExecutor
4445
rwMap map[string]*nsRWs
45-
done bool
4646
}
4747

4848
func (s *LockBasedTxSimulator) getOrCreateNsRWHolder(ns string) *nsRWs {
@@ -57,6 +57,7 @@ func (s *LockBasedTxSimulator) getOrCreateNsRWHolder(ns string) *nsRWs {
5757

5858
// GetState implements method in interface `ledger.TxSimulator`
5959
func (s *LockBasedTxSimulator) GetState(ns string, key string) ([]byte, error) {
60+
s.checkDone()
6061
logger.Debugf("Get state [%s:%s]", ns, key)
6162
nsRWs := s.getOrCreateNsRWHolder(ns)
6263
// check if it was written
@@ -106,11 +107,24 @@ func (s *LockBasedTxSimulator) GetState(ns string, key string) ([]byte, error) {
106107
return value, nil
107108
}
108109

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+
109125
// SetState implements method in interface `ledger.TxSimulator`
110126
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()
114128
nsRWs := s.getOrCreateNsRWHolder(ns)
115129
kvWrite, ok := nsRWs.writeMap[key]
116130
if ok {
@@ -126,12 +140,6 @@ func (s *LockBasedTxSimulator) DeleteState(ns string, key string) error {
126140
return s.SetState(ns, key, nil)
127141
}
128142

129-
// Done implements method in interface `ledger.TxSimulator`
130-
func (s *LockBasedTxSimulator) Done() {
131-
s.done = true
132-
s.txmgr.commitRWLock.RUnlock()
133-
}
134-
135143
func (s *LockBasedTxSimulator) getTxReadWriteSet() *txmgmt.TxReadWriteSet {
136144
txRWSet := &txmgmt.TxReadWriteSet{}
137145
sortedNamespaces := getSortedKeys(s.rwMap)
@@ -186,15 +194,43 @@ func (s *LockBasedTxSimulator) GetTxSimulationResults() ([]byte, error) {
186194

187195
// SetStateMultipleKeys implements method in interface `ledger.TxSimulator`
188196
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
195203
}
196204

197205
// ExecuteUpdate implements method in interface `ledger.TxSimulator`
198206
func (s *LockBasedTxSimulator) ExecuteUpdate(query string) error {
199207
return errors.New("Not supported by KV data model")
200208
}
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

Comments
 (0)