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  }