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