prometheus/vendor/github.com/syndtr/goleveldb/leveldb/key.go

144 lines
3.7 KiB
Go
Raw Normal View History

2015-09-10 07:17:51 -07:00
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package leveldb
import (
"encoding/binary"
"fmt"
"github.com/syndtr/goleveldb/leveldb/errors"
2016-07-04 01:08:49 -07:00
"github.com/syndtr/goleveldb/leveldb/storage"
2015-09-10 07:17:51 -07:00
)
2016-07-04 01:08:49 -07:00
// ErrInternalKeyCorrupted records internal key corruption.
type ErrInternalKeyCorrupted struct {
2015-09-10 07:17:51 -07:00
Ikey []byte
Reason string
}
2016-07-04 01:08:49 -07:00
func (e *ErrInternalKeyCorrupted) Error() string {
return fmt.Sprintf("leveldb: internal key %q corrupted: %s", e.Ikey, e.Reason)
2015-09-10 07:17:51 -07:00
}
2016-07-04 01:08:49 -07:00
func newErrInternalKeyCorrupted(ikey []byte, reason string) error {
return errors.NewErrCorrupted(storage.FileDesc{}, &ErrInternalKeyCorrupted{append([]byte{}, ikey...), reason})
2015-09-10 07:17:51 -07:00
}
2016-07-04 01:08:49 -07:00
type keyType uint
2015-09-10 07:17:51 -07:00
2016-07-04 01:08:49 -07:00
func (kt keyType) String() string {
2015-09-10 07:17:51 -07:00
switch kt {
2016-07-04 01:08:49 -07:00
case keyTypeDel:
2015-09-10 07:17:51 -07:00
return "d"
2016-07-04 01:08:49 -07:00
case keyTypeVal:
2015-09-10 07:17:51 -07:00
return "v"
}
return fmt.Sprintf("<invalid:%#x>", uint(kt))
2015-09-10 07:17:51 -07:00
}
// Value types encoded as the last component of internal keys.
// Don't modify; this value are saved to disk.
const (
keyTypeDel = keyType(0)
keyTypeVal = keyType(1)
2015-09-10 07:17:51 -07:00
)
2016-07-04 01:08:49 -07:00
// keyTypeSeek defines the keyType that should be passed when constructing an
2015-09-10 07:17:51 -07:00
// internal key for seeking to a particular sequence number (since we
// sort sequence numbers in decreasing order and the value type is
// embedded as the low 8 bits in the sequence number in internal keys,
// we need to use the highest-numbered ValueType, not the lowest).
2016-07-04 01:08:49 -07:00
const keyTypeSeek = keyTypeVal
2015-09-10 07:17:51 -07:00
const (
// Maximum value possible for sequence number; the 8-bits are
// used by value type, so its can packed together in single
// 64-bit integer.
2016-07-04 01:08:49 -07:00
keyMaxSeq = (uint64(1) << 56) - 1
2015-09-10 07:17:51 -07:00
// Maximum value possible for packed sequence number and type.
2016-07-04 01:08:49 -07:00
keyMaxNum = (keyMaxSeq << 8) | uint64(keyTypeSeek)
2015-09-10 07:17:51 -07:00
)
// Maximum number encoded in bytes.
2016-07-04 01:08:49 -07:00
var keyMaxNumBytes = make([]byte, 8)
2015-09-10 07:17:51 -07:00
func init() {
2016-07-04 01:08:49 -07:00
binary.LittleEndian.PutUint64(keyMaxNumBytes, keyMaxNum)
2015-09-10 07:17:51 -07:00
}
2016-07-04 01:08:49 -07:00
type internalKey []byte
2015-09-10 07:17:51 -07:00
2016-07-04 01:08:49 -07:00
func makeInternalKey(dst, ukey []byte, seq uint64, kt keyType) internalKey {
if seq > keyMaxSeq {
2015-09-10 07:17:51 -07:00
panic("leveldb: invalid sequence number")
2016-07-04 01:08:49 -07:00
} else if kt > keyTypeVal {
2015-09-10 07:17:51 -07:00
panic("leveldb: invalid type")
}
dst = ensureBuffer(dst, len(ukey)+8)
2016-07-04 01:08:49 -07:00
copy(dst, ukey)
binary.LittleEndian.PutUint64(dst[len(ukey):], (seq<<8)|uint64(kt))
return internalKey(dst)
2015-09-10 07:17:51 -07:00
}
2016-07-04 01:08:49 -07:00
func parseInternalKey(ik []byte) (ukey []byte, seq uint64, kt keyType, err error) {
2015-09-10 07:17:51 -07:00
if len(ik) < 8 {
2016-07-04 01:08:49 -07:00
return nil, 0, 0, newErrInternalKeyCorrupted(ik, "invalid length")
2015-09-10 07:17:51 -07:00
}
num := binary.LittleEndian.Uint64(ik[len(ik)-8:])
2016-07-04 01:08:49 -07:00
seq, kt = uint64(num>>8), keyType(num&0xff)
if kt > keyTypeVal {
return nil, 0, 0, newErrInternalKeyCorrupted(ik, "invalid type")
2015-09-10 07:17:51 -07:00
}
ukey = ik[:len(ik)-8]
return
}
2016-07-04 01:08:49 -07:00
func validInternalKey(ik []byte) bool {
_, _, _, err := parseInternalKey(ik)
2015-09-10 07:17:51 -07:00
return err == nil
}
2016-07-04 01:08:49 -07:00
func (ik internalKey) assert() {
2015-09-10 07:17:51 -07:00
if ik == nil {
2016-07-04 01:08:49 -07:00
panic("leveldb: nil internalKey")
2015-09-10 07:17:51 -07:00
}
if len(ik) < 8 {
2016-07-04 01:08:49 -07:00
panic(fmt.Sprintf("leveldb: internal key %q, len=%d: invalid length", []byte(ik), len(ik)))
2015-09-10 07:17:51 -07:00
}
}
2016-07-04 01:08:49 -07:00
func (ik internalKey) ukey() []byte {
2015-09-10 07:17:51 -07:00
ik.assert()
return ik[:len(ik)-8]
}
2016-07-04 01:08:49 -07:00
func (ik internalKey) num() uint64 {
2015-09-10 07:17:51 -07:00
ik.assert()
return binary.LittleEndian.Uint64(ik[len(ik)-8:])
}
2016-07-04 01:08:49 -07:00
func (ik internalKey) parseNum() (seq uint64, kt keyType) {
2015-09-10 07:17:51 -07:00
num := ik.num()
2016-07-04 01:08:49 -07:00
seq, kt = uint64(num>>8), keyType(num&0xff)
if kt > keyTypeVal {
panic(fmt.Sprintf("leveldb: internal key %q, len=%d: invalid type %#x", []byte(ik), len(ik), kt))
2015-09-10 07:17:51 -07:00
}
return
}
2016-07-04 01:08:49 -07:00
func (ik internalKey) String() string {
2015-09-10 07:17:51 -07:00
if ik == nil {
return "<nil>"
}
2016-07-04 01:08:49 -07:00
if ukey, seq, kt, err := parseInternalKey(ik); err == nil {
2015-09-10 07:17:51 -07:00
return fmt.Sprintf("%s,%s%d", shorten(string(ukey)), kt, seq)
}
return fmt.Sprintf("<invalid:%#x>", []byte(ik))
2015-09-10 07:17:51 -07:00
}