github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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 if err := vdb.db.WriteBatch(dbBatch, false); err != nil { 152 return err 153 } 154 return nil 155 } 156 157 // GetLatestSavePoint implements method in VersionedDB interface 158 func (vdb *versionedDB) GetLatestSavePoint() (*version.Height, error) { 159 versionBytes, err := vdb.db.Get(savePointKey) 160 if err != nil { 161 return nil, err 162 } 163 if versionBytes == nil { 164 return nil, nil 165 } 166 version, _ := version.NewHeightFromBytes(versionBytes) 167 return version, nil 168 } 169 170 func constructCompositeKey(ns string, key string) []byte { 171 return append(append([]byte(ns), compositeKeySep...), []byte(key)...) 172 } 173 174 func splitCompositeKey(compositeKey []byte) (string, string) { 175 split := bytes.SplitN(compositeKey, compositeKeySep, 2) 176 return string(split[0]), string(split[1]) 177 } 178 179 type kvScanner struct { 180 namespace string 181 dbItr iterator.Iterator 182 } 183 184 func newKVScanner(namespace string, dbItr iterator.Iterator) *kvScanner { 185 return &kvScanner{namespace, dbItr} 186 } 187 188 func (scanner *kvScanner) Next() (statedb.QueryResult, error) { 189 if !scanner.dbItr.Next() { 190 return nil, nil 191 } 192 dbKey := scanner.dbItr.Key() 193 dbVal := scanner.dbItr.Value() 194 dbValCopy := make([]byte, len(dbVal)) 195 copy(dbValCopy, dbVal) 196 _, key := splitCompositeKey(dbKey) 197 value, version := statedb.DecodeValue(dbValCopy) 198 return &statedb.VersionedKV{ 199 CompositeKey: statedb.CompositeKey{Namespace: scanner.namespace, Key: key}, 200 VersionedValue: statedb.VersionedValue{Value: value, Version: version}}, nil 201 } 202 203 func (scanner *kvScanner) Close() { 204 scanner.dbItr.Release() 205 }