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 }