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.

137 lines
3.1 KiB

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