1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
2 // All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
13 "github.com/syndtr/goleveldb/leveldb/errors"
14 "github.com/syndtr/goleveldb/leveldb/storage"
17 // ErrInternalKeyCorrupted records internal key corruption.
18 type ErrInternalKeyCorrupted struct {
23 func (e *ErrInternalKeyCorrupted) Error() string {
24 return fmt.Sprintf("leveldb: internal key %q corrupted: %s", e.Ikey, e.Reason)
27 func newErrInternalKeyCorrupted(ikey []byte, reason string) error {
28 return errors.NewErrCorrupted(storage.FileDesc{}, &ErrInternalKeyCorrupted{append([]byte{}, ikey...), reason})
33 func (kt keyType) String() string {
40 return fmt.Sprintf("<invalid:%#x>", uint(kt))
43 // Value types encoded as the last component of internal keys.
44 // Don't modify; this value are saved to disk.
46 keyTypeDel = keyType(0)
47 keyTypeVal = keyType(1)
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
58 // Maximum value possible for sequence number; the 8-bits are
59 // used by value type, so its can packed together in single
61 keyMaxSeq = (uint64(1) << 56) - 1
62 // Maximum value possible for packed sequence number and type.
63 keyMaxNum = (keyMaxSeq << 8) | uint64(keyTypeSeek)
66 // Maximum number encoded in bytes.
67 var keyMaxNumBytes = make([]byte, 8)
70 binary.LittleEndian.PutUint64(keyMaxNumBytes, keyMaxNum)
73 type internalKey []byte
75 func makeInternalKey(dst, ukey []byte, seq uint64, kt keyType) internalKey {
77 panic("leveldb: invalid sequence number")
78 } else if kt > keyTypeVal {
79 panic("leveldb: invalid type")
82 dst = ensureBuffer(dst, len(ukey)+8)
84 binary.LittleEndian.PutUint64(dst[len(ukey):], (seq<<8)|uint64(kt))
85 return internalKey(dst)
88 func parseInternalKey(ik []byte) (ukey []byte, seq uint64, kt keyType, err error) {
90 return nil, 0, 0, newErrInternalKeyCorrupted(ik, "invalid length")
92 num := binary.LittleEndian.Uint64(ik[len(ik)-8:])
93 seq, kt = uint64(num>>8), keyType(num&0xff)
95 return nil, 0, 0, newErrInternalKeyCorrupted(ik, "invalid type")
101 func validInternalKey(ik []byte) bool {
102 _, _, _, err := parseInternalKey(ik)
106 func (ik internalKey) assert() {
108 panic("leveldb: nil internalKey")
111 panic(fmt.Sprintf("leveldb: internal key %q, len=%d: invalid length", []byte(ik), len(ik)))
115 func (ik internalKey) ukey() []byte {
117 return ik[:len(ik)-8]
120 func (ik internalKey) num() uint64 {
122 return binary.LittleEndian.Uint64(ik[len(ik)-8:])
125 func (ik internalKey) parseNum() (seq uint64, kt keyType) {
127 seq, kt = uint64(num>>8), keyType(num&0xff)
129 panic(fmt.Sprintf("leveldb: internal key %q, len=%d: invalid type %#x", []byte(ik), len(ik), kt))
134 func (ik internalKey) String() string {
139 if ukey, seq, kt, err := parseInternalKey(ik); err == nil {
140 return fmt.Sprintf("%s,%s%d", shorten(string(ukey)), kt, seq)
142 return fmt.Sprintf("<invalid:%#x>", []byte(ik))