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  }