github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/utils/dbutil/compactdb/keys.go (about) 1 package compactdb 2 3 import ( 4 "bytes" 5 "math/big" 6 7 "github.com/unicornultrafoundation/go-u2u/common" 8 9 "github.com/unicornultrafoundation/go-helios/u2udb" 10 "github.com/unicornultrafoundation/go-helios/u2udb/table" 11 ) 12 13 func isEmptyDB(db u2udb.Iteratee) bool { 14 it := db.NewIterator(nil, nil) 15 defer it.Release() 16 return !it.Next() 17 } 18 19 func firstKey(db u2udb.Store) []byte { 20 it := db.NewIterator(nil, nil) 21 defer it.Release() 22 if !it.Next() { 23 return nil 24 } 25 return common.CopyBytes(it.Key()) 26 } 27 28 func lastKey(db u2udb.Store) []byte { 29 var start []byte 30 for { 31 for b := 0xff; b >= 0; b-- { 32 if !isEmptyDB(table.New(db, append(start, byte(b)))) { 33 start = append(start, byte(b)) 34 break 35 } 36 if b == 0 { 37 return start 38 } 39 } 40 } 41 } 42 43 func keysRange(db u2udb.Store) ([]byte, []byte, *big.Int) { 44 first := firstKey(db) 45 if first == nil { 46 return nil, nil, big.NewInt(0) 47 } 48 last := lastKey(db) 49 if last == nil { 50 return nil, nil, big.NewInt(0) 51 } 52 keySize := len(last) 53 if keySize < len(first) { 54 keySize = len(first) 55 } 56 first = common.RightPadBytes(first, keySize) 57 last = common.RightPadBytes(last, keySize) 58 firstBn := new(big.Int).SetBytes(first) 59 lastBn := new(big.Int).SetBytes(last) 60 return first, last, new(big.Int).Sub(lastBn, firstBn) 61 } 62 63 func addToKey(prefix *big.Int, diff *big.Int, size int) []byte { 64 endBn := new(big.Int).Set(prefix) 65 endBn.Add(endBn, diff) 66 if len(endBn.Bytes()) > size { 67 // overflow 68 return bytes.Repeat([]byte{0xff}, size) 69 } 70 end := endBn.Bytes() 71 res := make([]byte, size-len(end), size) 72 return append(res, end...) 73 } 74 75 // trimAfterDiff erases all bytes after first *maxDiff* differences between *a* and *b* 76 func trimAfterDiff(a, b []byte, maxDiff int) ([]byte, []byte) { 77 size := len(a) 78 if size > len(b) { 79 size = len(b) 80 } 81 for i := 0; i < size; i++ { 82 if a[i] != b[i] { 83 maxDiff-- 84 if maxDiff <= 0 { 85 size = i + 1 86 break 87 } 88 } 89 } 90 if len(a) > size { 91 a = a[:size] 92 } 93 if len(b) > size { 94 b = b[:size] 95 } 96 return a, b 97 }