github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package stateleveldb 18 19 import ( 20 "bytes" 21 "errors" 22 23 "github.com/hyperledger/fabric/common/flogging" 24 "github.com/hyperledger/fabric/common/ledger/util/leveldbhelper" 25 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 26 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 27 "github.com/hyperledger/fabric/core/ledger/ledgerconfig" 28 "github.com/syndtr/goleveldb/leveldb/iterator" 29 ) 30 31 var logger = flogging.MustGetLogger("stateleveldb") 32 33 var compositeKeySep = []byte{0x00} 34 var lastKeyIndicator = byte(0x01) 35 var savePointKey = []byte{0x00} 36 37 // VersionedDBProvider implements interface VersionedDBProvider 38 type VersionedDBProvider struct { 39 dbProvider *leveldbhelper.Provider 40 } 41 42 // NewVersionedDBProvider instantiates VersionedDBProvider 43 func NewVersionedDBProvider() *VersionedDBProvider { 44 dbPath := ledgerconfig.GetStateLevelDBPath() 45 logger.Debugf("constructing VersionedDBProvider dbPath=%s", dbPath) 46 dbProvider := leveldbhelper.NewProvider(&leveldbhelper.Conf{DBPath: dbPath}) 47 return &VersionedDBProvider{dbProvider} 48 } 49 50 // GetDBHandle gets the handle to a named database 51 func (provider *VersionedDBProvider) GetDBHandle(dbName string) (statedb.VersionedDB, error) { 52 return newVersionedDB(provider.dbProvider.GetDBHandle(dbName), dbName), nil 53 } 54 55 // Close closes the underlying db 56 func (provider *VersionedDBProvider) Close() { 57 provider.dbProvider.Close() 58 } 59 60 // VersionedDB implements VersionedDB interface 61 type versionedDB struct { 62 db *leveldbhelper.DBHandle 63 dbName string 64 } 65 66 // newVersionedDB constructs an instance of VersionedDB 67 func newVersionedDB(db *leveldbhelper.DBHandle, dbName string) *versionedDB { 68 return &versionedDB{db, dbName} 69 } 70 71 // Open implements method in VersionedDB interface 72 func (vdb *versionedDB) Open() error { 73 // do nothing because shared db is used 74 return nil 75 } 76 77 // Close implements method in VersionedDB interface 78 func (vdb *versionedDB) Close() { 79 // do nothing because shared db is used 80 } 81 82 // ValidateKey implements method in VersionedDB interface 83 func (vdb *versionedDB) ValidateKey(key string) error { 84 return nil 85 } 86 87 // GetState implements method in VersionedDB interface 88 func (vdb *versionedDB) GetState(namespace string, key string) (*statedb.VersionedValue, error) { 89 logger.Debugf("GetState(). ns=%s, key=%s", namespace, key) 90 compositeKey := constructCompositeKey(namespace, key) 91 dbVal, err := vdb.db.Get(compositeKey) 92 if err != nil { 93 return nil, err 94 } 95 if dbVal == nil { 96 return nil, nil 97 } 98 val, ver := statedb.DecodeValue(dbVal) 99 return &statedb.VersionedValue{Value: val, Version: ver}, nil 100 } 101 102 // GetStateMultipleKeys implements method in VersionedDB interface 103 func (vdb *versionedDB) GetStateMultipleKeys(namespace string, keys []string) ([]*statedb.VersionedValue, error) { 104 vals := make([]*statedb.VersionedValue, len(keys)) 105 for i, key := range keys { 106 val, err := vdb.GetState(namespace, key) 107 if err != nil { 108 return nil, err 109 } 110 vals[i] = val 111 } 112 return vals, nil 113 } 114 115 // GetStateRangeScanIterator implements method in VersionedDB interface 116 // startKey is inclusive 117 // endKey is exclusive 118 func (vdb *versionedDB) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (statedb.ResultsIterator, error) { 119 compositeStartKey := constructCompositeKey(namespace, startKey) 120 compositeEndKey := constructCompositeKey(namespace, endKey) 121 if endKey == "" { 122 compositeEndKey[len(compositeEndKey)-1] = lastKeyIndicator 123 } 124 dbItr := vdb.db.GetIterator(compositeStartKey, compositeEndKey) 125 return newKVScanner(namespace, dbItr), nil 126 } 127 128 // ExecuteQuery implements method in VersionedDB interface 129 func (vdb *versionedDB) ExecuteQuery(namespace, query string) (statedb.ResultsIterator, error) { 130 return nil, errors.New("ExecuteQuery not supported for leveldb") 131 } 132 133 // ApplyUpdates implements method in VersionedDB interface 134 func (vdb *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version.Height) error { 135 dbBatch := leveldbhelper.NewUpdateBatch() 136 namespaces := batch.GetUpdatedNamespaces() 137 for _, ns := range namespaces { 138 updates := batch.GetUpdates(ns) 139 for k, vv := range updates { 140 compositeKey := constructCompositeKey(ns, k) 141 logger.Debugf("Channel [%s]: Applying key=[%#v]", vdb.dbName, compositeKey) 142 143 if vv.Value == nil { 144 dbBatch.Delete(compositeKey) 145 } else { 146 dbBatch.Put(compositeKey, statedb.EncodeValue(vv.Value, vv.Version)) 147 } 148 } 149 } 150 dbBatch.Put(savePointKey, height.ToBytes()) 151 // Setting snyc to true as a precaution, false may be an ok optimization after further testing. 152 if err := vdb.db.WriteBatch(dbBatch, true); err != nil { 153 return err 154 } 155 return nil 156 } 157 158 // GetLatestSavePoint implements method in VersionedDB interface 159 func (vdb *versionedDB) GetLatestSavePoint() (*version.Height, error) { 160 versionBytes, err := vdb.db.Get(savePointKey) 161 if err != nil { 162 return nil, err 163 } 164 if versionBytes == nil { 165 return nil, nil 166 } 167 version, _ := version.NewHeightFromBytes(versionBytes) 168 return version, nil 169 } 170 171 func constructCompositeKey(ns string, key string) []byte { 172 return append(append([]byte(ns), compositeKeySep...), []byte(key)...) 173 } 174 175 func splitCompositeKey(compositeKey []byte) (string, string) { 176 split := bytes.SplitN(compositeKey, compositeKeySep, 2) 177 return string(split[0]), string(split[1]) 178 } 179 180 type kvScanner struct { 181 namespace string 182 dbItr iterator.Iterator 183 } 184 185 func newKVScanner(namespace string, dbItr iterator.Iterator) *kvScanner { 186 return &kvScanner{namespace, dbItr} 187 } 188 189 func (scanner *kvScanner) Next() (statedb.QueryResult, error) { 190 if !scanner.dbItr.Next() { 191 return nil, nil 192 } 193 dbKey := scanner.dbItr.Key() 194 dbVal := scanner.dbItr.Value() 195 dbValCopy := make([]byte, len(dbVal)) 196 copy(dbValCopy, dbVal) 197 _, key := splitCompositeKey(dbKey) 198 value, version := statedb.DecodeValue(dbValCopy) 199 return &statedb.VersionedKV{ 200 CompositeKey: statedb.CompositeKey{Namespace: scanner.namespace, Key: key}, 201 VersionedValue: statedb.VersionedValue{Value: value, Version: version}}, nil 202 } 203 204 func (scanner *kvScanner) Close() { 205 scanner.dbItr.Release() 206 }