This repository has been archived by the owner on Apr 5, 2023. It is now read-only.
/
statedb.go
106 lines (88 loc) · 4.03 KB
/
statedb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package statedb
import (
"sync"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
)
var provider = newProvider()
// StateDB declares functions that allow for retrieving and querying from a state database
type StateDB interface {
// GetState gets the value for given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId
GetState(namespace string, key string) ([]byte, error)
// GetStateMultipleKeys gets the values for multiple keys in a single call
GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error)
// GetStateRangeScanIterator returns an iterator that contains all the key-values between given key ranges.
// startKey is inclusive
// endKey is exclusive
// The returned ResultsIterator contains results of type *VersionedKV
GetStateRangeScanIterator(namespace string, startKey string, endKey string) (statedb.ResultsIterator, error)
// GetStateRangeScanIteratorWithPagination returns an iterator that contains all the key-values between given key ranges.
// startKey is inclusive
// endKey is exclusive
// pageSize parameter limits the number of returned results
// The returned ResultsIterator contains results of type *VersionedKV
GetStateRangeScanIteratorWithPagination(namespace string, startKey string, endKey string, pageSize int32) (statedb.QueryResultsIterator, error)
// ExecuteQuery executes the given query and returns an iterator that contains results of type *VersionedKV.
ExecuteQuery(namespace, query string) (statedb.ResultsIterator, error)
// ExecuteQueryWithPagination executes the given query and
// returns an iterator that contains results of type *VersionedKV.
// The bookmark and page size parameters are associated with the pagination query.
ExecuteQueryWithPagination(namespace, query, bookmark string, pageSize int32) (statedb.QueryResultsIterator, error)
// BytesKeySupported returns true if the implementation (underlying db) supports the any bytes to be used as key.
// For instance, leveldb supports any bytes for the key while the couchdb supports only valid utf-8 string
BytesKeySupported() bool
// UpdateCache updates the state cache with the given updates. The format of the updates depends on the database implementation.
UpdateCache(blockNum uint64, updates []byte) error
}
// QueryExecutorProvider provides a query executor with and without a commit lock
type QueryExecutorProvider interface {
// NewQueryExecutor returns a query executor that first acquires a commit read lock.
// Done() must be called when finished using it.
NewQueryExecutor() (ledger.QueryExecutor, error)
// NewQueryExecutorNoLock returns a query executor that does not acquire a commit read lock.
// Done() must NOT be called.
NewQueryExecutorNoLock() (ledger.QueryExecutor, error)
}
type channelDB struct {
stateDB StateDB
qeProvider QueryExecutorProvider
}
// Provider is a state database Provider
type Provider struct {
channelDBs map[string]*channelDB
mutex sync.RWMutex
}
// GetProvider returns the state database provider
func GetProvider() *Provider {
return provider
}
func newProvider() *Provider {
return &Provider{
channelDBs: make(map[string]*channelDB),
}
}
// StateDBForChannel returns the state database for the given channel
func (p *Provider) StateDBForChannel(channelID string) StateDB {
p.mutex.RLock()
defer p.mutex.RUnlock()
return p.channelDBs[channelID].stateDB
}
// QueryExecutorProviderForChannel returns the query executor provider for the given channel
func (p *Provider) QueryExecutorProviderForChannel(channelID string) QueryExecutorProvider {
p.mutex.RLock()
defer p.mutex.RUnlock()
return p.channelDBs[channelID].qeProvider
}
// Register registers a state database for the given channel
func (p *Provider) Register(channelID string, db StateDB, qep QueryExecutorProvider) {
p.mutex.Lock()
defer p.mutex.Unlock()
p.channelDBs[channelID] = &channelDB{
stateDB: db,
qeProvider: qep,
}
}