github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/common/ledger/util/leveldbhelper/leveldb_provider.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 leveldbhelper 18 19 import ( 20 "bytes" 21 "sync" 22 23 "github.com/syndtr/goleveldb/leveldb" 24 "github.com/syndtr/goleveldb/leveldb/iterator" 25 ) 26 27 var dbNameKeySep = []byte{0x00} 28 var lastKeyIndicator = byte(0x01) 29 30 // Provider enables to use a single leveldb as multiple logical leveldbs 31 type Provider struct { 32 db *DB 33 dbHandles map[string]*DBHandle 34 mux sync.Mutex 35 } 36 37 // NewProvider constructs a Provider 38 func NewProvider(conf *Conf) *Provider { 39 db := CreateDB(conf) 40 db.Open() 41 return &Provider{db, make(map[string]*DBHandle), sync.Mutex{}} 42 } 43 44 // GetDBHandle returns a handle to a named db 45 func (p *Provider) GetDBHandle(dbName string) *DBHandle { 46 p.mux.Lock() 47 defer p.mux.Unlock() 48 dbHandle := p.dbHandles[dbName] 49 if dbHandle == nil { 50 dbHandle = &DBHandle{dbName, p.db} 51 p.dbHandles[dbName] = dbHandle 52 } 53 return dbHandle 54 } 55 56 // Close closes the underlying leveldb 57 func (p *Provider) Close() { 58 p.db.Close() 59 } 60 61 // DBHandle is an handle to a named db 62 type DBHandle struct { 63 dbName string 64 db *DB 65 } 66 67 // Get returns the value for the given key 68 func (h *DBHandle) Get(key []byte) ([]byte, error) { 69 return h.db.Get(constructLevelKey(h.dbName, key)) 70 } 71 72 // Put saves the key/value 73 func (h *DBHandle) Put(key []byte, value []byte, sync bool) error { 74 return h.db.Put(constructLevelKey(h.dbName, key), value, sync) 75 } 76 77 // Delete deletes the given key 78 func (h *DBHandle) Delete(key []byte, sync bool) error { 79 return h.db.Delete(constructLevelKey(h.dbName, key), sync) 80 } 81 82 // WriteBatch writes a batch in an atomic way 83 func (h *DBHandle) WriteBatch(batch *UpdateBatch, sync bool) error { 84 levelBatch := &leveldb.Batch{} 85 for k, v := range batch.KVs { 86 key := constructLevelKey(h.dbName, []byte(k)) 87 if v == nil { 88 levelBatch.Delete(key) 89 } else { 90 levelBatch.Put(key, v) 91 } 92 } 93 if err := h.db.WriteBatch(levelBatch, sync); err != nil { 94 return err 95 } 96 return nil 97 } 98 99 // GetIterator gets an handle to iterator. The iterator should be released after the use. 100 // The resultset contains all the keys that are present in the db between the startKey (inclusive) and the endKey (exclusive). 101 // A nil startKey represents the first available key and a nil endKey represent a logical key after the last available key 102 func (h *DBHandle) GetIterator(startKey []byte, endKey []byte) *Iterator { 103 sKey := constructLevelKey(h.dbName, startKey) 104 eKey := constructLevelKey(h.dbName, endKey) 105 if endKey == nil { 106 // replace the last byte 'dbNameKeySep' by 'lastKeyIndicator' 107 eKey[len(eKey)-1] = lastKeyIndicator 108 } 109 logger.Debugf("Getting iterator for range [%#v] - [%#v]", sKey, eKey) 110 return &Iterator{h.db.GetIterator(sKey, eKey)} 111 } 112 113 // UpdateBatch encloses the details of multiple `updates` 114 type UpdateBatch struct { 115 KVs map[string][]byte 116 } 117 118 // NewUpdateBatch constructs an instance of a Batch 119 func NewUpdateBatch() *UpdateBatch { 120 return &UpdateBatch{make(map[string][]byte)} 121 } 122 123 // Put adds a KV 124 func (batch *UpdateBatch) Put(key []byte, value []byte) { 125 if value == nil { 126 panic("Nil value not allowed") 127 } 128 batch.KVs[string(key)] = value 129 } 130 131 // Delete deletes a Key and associated value 132 func (batch *UpdateBatch) Delete(key []byte) { 133 batch.KVs[string(key)] = nil 134 } 135 136 // Iterator extends actual leveldb iterator 137 type Iterator struct { 138 iterator.Iterator 139 } 140 141 // Key wraps actual leveldb iterator method 142 func (itr *Iterator) Key() []byte { 143 return retrieveAppKey(itr.Iterator.Key()) 144 } 145 146 func constructLevelKey(dbName string, key []byte) []byte { 147 return append(append([]byte(dbName), dbNameKeySep...), key...) 148 } 149 150 func retrieveAppKey(levelKey []byte) []byte { 151 return bytes.SplitN(levelKey, dbNameKeySep, 2)[1] 152 }