github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/manualtest/dbstress/key.go (about) 1 package main 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 7 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors" 8 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/storage" 9 ) 10 11 type ErrIkeyCorrupted struct { 12 Ikey []byte 13 Reason string 14 } 15 16 func (e *ErrIkeyCorrupted) Error() string { 17 return fmt.Sprintf("leveldb: iKey %q corrupted: %s", e.Ikey, e.Reason) 18 } 19 20 func newErrIkeyCorrupted(ikey []byte, reason string) error { 21 return errors.NewErrCorrupted(storage.FileDesc{}, &ErrIkeyCorrupted{append([]byte{}, ikey...), reason}) 22 } 23 24 type kType int 25 26 func (kt kType) String() string { 27 switch kt { 28 case ktDel: 29 return "d" 30 case ktVal: 31 return "v" 32 } 33 return "x" 34 } 35 36 // Value types encoded as the last component of internal keys. 37 // Don't modify; this value are saved to disk. 38 const ( 39 ktDel kType = iota 40 ktVal 41 ) 42 43 // ktSeek defines the kType that should be passed when constructing an 44 // internal key for seeking to a particular sequence number (since we 45 // sort sequence numbers in decreasing order and the value type is 46 // embedded as the low 8 bits in the sequence number in internal keys, 47 // we need to use the highest-numbered ValueType, not the lowest). 48 const ktSeek = ktVal 49 50 const ( 51 // Maximum value possible for sequence number; the 8-bits are 52 // used by value type, so its can packed together in single 53 // 64-bit integer. 54 kMaxSeq uint64 = (uint64(1) << 56) - 1 55 // Maximum value possible for packed sequence number and type. 56 kMaxNum uint64 = (kMaxSeq << 8) | uint64(ktSeek) 57 ) 58 59 // Maximum number encoded in bytes. 60 var kMaxNumBytes = make([]byte, 8) 61 62 func init() { 63 binary.LittleEndian.PutUint64(kMaxNumBytes, kMaxNum) 64 } 65 66 type iKey []byte 67 68 func newIkey(ukey []byte, seq uint64, kt kType) iKey { 69 if seq > kMaxSeq { 70 panic("leveldb: invalid sequence number") 71 } else if kt > ktVal { 72 panic("leveldb: invalid type") 73 } 74 75 ik := make(iKey, len(ukey)+8) 76 copy(ik, ukey) 77 binary.LittleEndian.PutUint64(ik[len(ukey):], (seq<<8)|uint64(kt)) 78 return ik 79 } 80 81 func parseIkey(ik []byte) (ukey []byte, seq uint64, kt kType, err error) { 82 if len(ik) < 8 { 83 return nil, 0, 0, newErrIkeyCorrupted(ik, "invalid length") 84 } 85 num := binary.LittleEndian.Uint64(ik[len(ik)-8:]) 86 seq, kt = uint64(num>>8), kType(num&0xff) 87 if kt > ktVal { 88 return nil, 0, 0, newErrIkeyCorrupted(ik, "invalid type") 89 } 90 ukey = ik[:len(ik)-8] 91 return 92 } 93 94 func validIkey(ik []byte) bool { 95 _, _, _, err := parseIkey(ik) 96 return err == nil 97 } 98 99 func (ik iKey) assert() { 100 if ik == nil { 101 panic("leveldb: nil iKey") 102 } 103 if len(ik) < 8 { 104 panic(fmt.Sprintf("leveldb: iKey %q, len=%d: invalid length", ik, len(ik))) 105 } 106 } 107 108 func (ik iKey) ukey() []byte { 109 ik.assert() 110 return ik[:len(ik)-8] 111 } 112 113 func (ik iKey) num() uint64 { 114 ik.assert() 115 return binary.LittleEndian.Uint64(ik[len(ik)-8:]) 116 } 117 118 func (ik iKey) parseNum() (seq uint64, kt kType) { 119 num := ik.num() 120 seq, kt = uint64(num>>8), kType(num&0xff) 121 if kt > ktVal { 122 panic(fmt.Sprintf("leveldb: iKey %q, len=%d: invalid type %#x", ik, len(ik), kt)) 123 } 124 return 125 } 126 127 func (ik iKey) String() string { 128 if ik == nil { 129 return "<nil>" 130 } 131 132 if ukey, seq, kt, err := parseIkey(ik); err == nil { 133 return fmt.Sprintf("%x,%s%d", ukey, kt, seq) 134 } else { 135 return "<invalid>" 136 } 137 }