github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/confighistory/db_helper.go (about) 1 /* 2 Copyright hechain. 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/hechain20/hechain/common/ledger/util/leveldbhelper" 15 "github.com/pkg/errors" 16 ) 17 18 const ( 19 keyPrefix = "s" 20 separatorByte = byte(0) 21 nsStopper = byte(1) 22 ) 23 24 type compositeKey struct { 25 ns, key string 26 blockNum uint64 27 } 28 29 type compositeKV struct { 30 *compositeKey 31 value []byte 32 } 33 34 type dbProvider struct { 35 *leveldbhelper.Provider 36 } 37 38 type db struct { 39 *leveldbhelper.DBHandle 40 } 41 42 type batch struct { 43 *leveldbhelper.UpdateBatch 44 } 45 46 func newDBProvider(dbPath string) (*dbProvider, error) { 47 logger.Debugf("Opening db for config history: db path = %s", dbPath) 48 p, err := leveldbhelper.NewProvider(&leveldbhelper.Conf{DBPath: dbPath}) 49 if err != nil { 50 return nil, err 51 } 52 return &dbProvider{Provider: p}, nil 53 } 54 55 func (d *db) newBatch() *batch { 56 return &batch{d.DBHandle.NewUpdateBatch()} 57 } 58 59 func (p *dbProvider) getDB(id string) *db { 60 return &db{p.GetDBHandle(id)} 61 } 62 63 func (b *batch) add(ns, key string, blockNum uint64, value []byte) { 64 logger.Debugf("add() - {%s, %s, %d}", ns, key, blockNum) 65 k, v := encodeCompositeKey(ns, key, blockNum), value 66 b.Put(k, v) 67 } 68 69 func (d *db) writeBatch(batch *batch, sync bool) error { 70 return d.WriteBatch(batch.UpdateBatch, sync) 71 } 72 73 func (d *db) mostRecentEntryBelow(blockNum uint64, ns, key string) (*compositeKV, error) { 74 logger.Debugf("mostRecentEntryBelow() - {%s, %s, %d}", ns, key, blockNum) 75 if blockNum == 0 { 76 return nil, errors.New("blockNum should be greater than 0") 77 } 78 79 startKey := encodeCompositeKey(ns, key, blockNum-1) 80 stopKey := append(encodeCompositeKey(ns, key, 0), byte(0)) 81 82 itr, err := d.GetIterator(startKey, stopKey) 83 if err != nil { 84 return nil, err 85 } 86 defer itr.Release() 87 if !itr.Next() { 88 logger.Debugf("Key no entry found. Returning nil") 89 return nil, nil 90 } 91 k, v := decodeCompositeKey(itr.Key()), itr.Value() 92 return &compositeKV{k, v}, nil 93 } 94 95 func (d *db) entryAt(blockNum uint64, ns, key string) (*compositeKV, error) { 96 logger.Debugf("entryAt() - {%s, %s, %d}", ns, key, blockNum) 97 keyBytes := encodeCompositeKey(ns, key, blockNum) 98 valBytes, err := d.Get(keyBytes) 99 if err != nil { 100 return nil, err 101 } 102 if valBytes == nil { 103 return nil, nil 104 } 105 k, v := decodeCompositeKey(keyBytes), valBytes 106 return &compositeKV{k, v}, nil 107 } 108 109 func (d *db) getNamespaceIterator(ns string) (*leveldbhelper.Iterator, error) { 110 nsStartKey := []byte(keyPrefix + ns) 111 nsStartKey = append(nsStartKey, separatorByte) 112 nsEndKey := []byte(keyPrefix + ns) 113 nsEndKey = append(nsEndKey, nsStopper) 114 return d.GetIterator(nsStartKey, nsEndKey) 115 } 116 117 func encodeCompositeKey(ns, key string, blockNum uint64) []byte { 118 b := []byte(keyPrefix + ns) 119 b = append(b, separatorByte) 120 b = append(b, []byte(key)...) 121 return append(b, encodeBlockNum(blockNum)...) 122 } 123 124 func decodeCompositeKey(b []byte) *compositeKey { 125 blockNumStartIndex := len(b) - 8 126 nsKeyBytes, blockNumBytes := b[1:blockNumStartIndex], b[blockNumStartIndex:] 127 separatorIndex := bytes.Index(nsKeyBytes, []byte{separatorByte}) 128 ns, key := nsKeyBytes[0:separatorIndex], nsKeyBytes[separatorIndex+1:] 129 return &compositeKey{string(ns), string(key), decodeBlockNum(blockNumBytes)} 130 } 131 132 func encodeBlockNum(blockNum uint64) []byte { 133 b := make([]byte, 8) 134 binary.BigEndian.PutUint64(b, math.MaxUint64-blockNum) 135 return b 136 } 137 138 func decodeBlockNum(blockNumBytes []byte) uint64 { 139 return math.MaxUint64 - binary.BigEndian.Uint64(blockNumBytes) 140 }