github.com/yimialmonte/fabric@v2.1.1+incompatible/core/ledger/confighistory/db_helper.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package confighistory
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/binary"
    12  	"math"
    13  
    14  	"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  const (
    19  	keyPrefix     = "s"
    20  	separatorByte = byte(0)
    21  )
    22  
    23  type compositeKey struct {
    24  	ns, key  string
    25  	blockNum uint64
    26  }
    27  
    28  type compositeKV struct {
    29  	*compositeKey
    30  	value []byte
    31  }
    32  
    33  type dbProvider struct {
    34  	*leveldbhelper.Provider
    35  }
    36  
    37  type db struct {
    38  	*leveldbhelper.DBHandle
    39  }
    40  
    41  type batch struct {
    42  	*leveldbhelper.UpdateBatch
    43  }
    44  
    45  func newDBProvider(dbPath string) (*dbProvider, error) {
    46  	logger.Debugf("Opening db for config history: db path = %s", dbPath)
    47  	p, err := leveldbhelper.NewProvider(&leveldbhelper.Conf{DBPath: dbPath})
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return &dbProvider{Provider: p}, nil
    52  }
    53  
    54  func newBatch() *batch {
    55  	return &batch{leveldbhelper.NewUpdateBatch()}
    56  }
    57  
    58  func (p *dbProvider) getDB(id string) *db {
    59  	return &db{p.GetDBHandle(id)}
    60  }
    61  
    62  func (b *batch) add(ns, key string, blockNum uint64, value []byte) {
    63  	logger.Debugf("add() - {%s, %s, %d}", ns, key, blockNum)
    64  	k, v := encodeCompositeKey(ns, key, blockNum), value
    65  	b.Put(k, v)
    66  }
    67  
    68  func (d *db) writeBatch(batch *batch, sync bool) error {
    69  	return d.WriteBatch(batch.UpdateBatch, sync)
    70  }
    71  
    72  func (d *db) mostRecentEntryBelow(blockNum uint64, ns, key string) (*compositeKV, error) {
    73  	logger.Debugf("mostRecentEntryBelow() - {%s, %s, %d}", ns, key, blockNum)
    74  	if blockNum == 0 {
    75  		return nil, errors.New("blockNum should be greater than 0")
    76  	}
    77  	startKey := encodeCompositeKey(ns, key, blockNum-1)
    78  	itr := d.GetIterator(startKey, nil)
    79  	defer itr.Release()
    80  	if !itr.Next() {
    81  		logger.Debugf("Key no entry found. Returning nil")
    82  		return nil, nil
    83  	}
    84  	k, v := decodeCompositeKey(itr.Key()), itr.Value()
    85  	return &compositeKV{k, v}, nil
    86  }
    87  
    88  func (d *db) entryAt(blockNum uint64, ns, key string) (*compositeKV, error) {
    89  	logger.Debugf("entryAt() - {%s, %s, %d}", ns, key, blockNum)
    90  	keyBytes := encodeCompositeKey(ns, key, blockNum)
    91  	valBytes, err := d.Get(keyBytes)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  	if valBytes == nil {
    96  		return nil, nil
    97  	}
    98  	k, v := decodeCompositeKey(keyBytes), valBytes
    99  	return &compositeKV{k, v}, nil
   100  }
   101  
   102  func encodeCompositeKey(ns, key string, blockNum uint64) []byte {
   103  	b := []byte(keyPrefix + ns)
   104  	b = append(b, separatorByte)
   105  	b = append(b, []byte(key)...)
   106  	return append(b, encodeBlockNum(blockNum)...)
   107  }
   108  
   109  func decodeCompositeKey(b []byte) *compositeKey {
   110  	blockNumStartIndex := len(b) - 8
   111  	nsKeyBytes, blockNumBytes := b[1:blockNumStartIndex], b[blockNumStartIndex:]
   112  	separatorIndex := bytes.Index(nsKeyBytes, []byte{separatorByte})
   113  	ns, key := nsKeyBytes[0:separatorIndex], nsKeyBytes[separatorIndex+1:]
   114  	return &compositeKey{string(ns), string(key), decodeBlockNum(blockNumBytes)}
   115  }
   116  
   117  func encodeBlockNum(blockNum uint64) []byte {
   118  	b := make([]byte, 8)
   119  	binary.BigEndian.PutUint64(b, math.MaxUint64-blockNum)
   120  	return b
   121  }
   122  
   123  func decodeBlockNum(blockNumBytes []byte) uint64 {
   124  	return math.MaxUint64 - binary.BigEndian.Uint64(blockNumBytes)
   125  }