github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 // GetState implements method in VersionedDB interface 83 func (vdb *versionedDB) GetState(namespace string, key string) (*statedb.VersionedValue, error) { 84 logger.Debugf("GetState(). ns=%s, key=%s", namespace, key) 85 compositeKey := constructCompositeKey(namespace, key) 86 dbVal, err := vdb.db.Get(compositeKey) 87 if err != nil { 88 return nil, err 89 } 90 if dbVal == nil { 91 return nil, nil 92 } 93 val, ver := statedb.DecodeValue(dbVal) 94 return &statedb.VersionedValue{Value: val, Version: ver}, nil 95 } 96 97 // GetStateMultipleKeys implements method in VersionedDB interface 98 func (vdb *versionedDB) GetStateMultipleKeys(namespace string, keys []string) ([]*statedb.VersionedValue, error) { 99 vals := make([]*statedb.VersionedValue, len(keys)) 100 for i, key := range keys { 101 val, err := vdb.GetState(namespace, key) 102 if err != nil { 103 return nil, err 104 } 105 vals[i] = val 106 } 107 return vals, nil 108 } 109 110 // GetStateRangeScanIterator implements method in VersionedDB interface 111 // startKey is inclusive 112 // endKey is exclusive 113 func (vdb *versionedDB) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (statedb.ResultsIterator, error) { 114 compositeStartKey := constructCompositeKey(namespace, startKey) 115 compositeEndKey := constructCompositeKey(namespace, endKey) 116 if endKey == "" { 117 compositeEndKey[len(compositeEndKey)-1] = lastKeyIndicator 118 } 119 dbItr := vdb.db.GetIterator(compositeStartKey, compositeEndKey) 120 return newKVScanner(namespace, dbItr), nil 121 } 122 123 // ExecuteQuery implements method in VersionedDB interface 124 func (vdb *versionedDB) ExecuteQuery(namespace, query string) (statedb.ResultsIterator, error) { 125 return nil, errors.New("ExecuteQuery not supported for leveldb") 126 } 127 128 // ApplyUpdates implements method in VersionedDB interface 129 func (vdb *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version.Height) error { 130 dbBatch := leveldbhelper.NewUpdateBatch() 131 namespaces := batch.GetUpdatedNamespaces() 132 for _, ns := range namespaces { 133 updates := batch.GetUpdates(ns) 134 for k, vv := range updates { 135 compositeKey := constructCompositeKey(ns, k) 136 logger.Debugf("Channel [%s]: Applying key=[%#v]", vdb.dbName, compositeKey) 137 138 if vv.Value == nil { 139 dbBatch.Delete(compositeKey) 140 } else { 141 dbBatch.Put(compositeKey, statedb.EncodeValue(vv.Value, vv.Version)) 142 } 143 } 144 } 145 dbBatch.Put(savePointKey, height.ToBytes()) 146 if err := vdb.db.WriteBatch(dbBatch, false); err != nil { 147 return err 148 } 149 return nil 150 } 151 152 // GetLatestSavePoint implements method in VersionedDB interface 153 func (vdb *versionedDB) GetLatestSavePoint() (*version.Height, error) { 154 versionBytes, err := vdb.db.Get(savePointKey) 155 if err != nil { 156 return nil, err 157 } 158 if versionBytes == nil { 159 return nil, nil 160 } 161 version, _ := version.NewHeightFromBytes(versionBytes) 162 return version, nil 163 } 164 165 func constructCompositeKey(ns string, key string) []byte { 166 return append(append([]byte(ns), compositeKeySep...), []byte(key)...) 167 } 168 169 func splitCompositeKey(compositeKey []byte) (string, string) { 170 split := bytes.SplitN(compositeKey, compositeKeySep, 2) 171 return string(split[0]), string(split[1]) 172 } 173 174 type kvScanner struct { 175 namespace string 176 dbItr iterator.Iterator 177 } 178 179 func newKVScanner(namespace string, dbItr iterator.Iterator) *kvScanner { 180 return &kvScanner{namespace, dbItr} 181 } 182 183 func (scanner *kvScanner) Next() (statedb.QueryResult, error) { 184 if !scanner.dbItr.Next() { 185 return nil, nil 186 } 187 dbKey := scanner.dbItr.Key() 188 dbVal := scanner.dbItr.Value() 189 dbValCopy := make([]byte, len(dbVal)) 190 copy(dbValCopy, dbVal) 191 _, key := splitCompositeKey(dbKey) 192 value, version := statedb.DecodeValue(dbValCopy) 193 return &statedb.VersionedKV{ 194 CompositeKey: statedb.CompositeKey{Namespace: scanner.namespace, Key: key}, 195 VersionedValue: statedb.VersionedValue{Value: value, Version: version}}, nil 196 } 197 198 func (scanner *kvScanner) Close() { 199 scanner.dbItr.Release() 200 }