You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.7 KiB

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