github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/internal/base/internal.go (about)

     1  // Copyright 2011 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package base // import "github.com/petermattis/pebble/internal/base"
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"fmt"
    11  	"strconv"
    12  	"strings"
    13  )
    14  
    15  // InternalKeyKind enumerates the kind of key: a deletion tombstone, a set
    16  // value, a merged value, etc.
    17  type InternalKeyKind uint8
    18  
    19  // These constants are part of the file format, and should not be changed.
    20  const (
    21  	InternalKeyKindDelete  InternalKeyKind = 0
    22  	InternalKeyKindSet                     = 1
    23  	InternalKeyKindMerge                   = 2
    24  	InternalKeyKindLogData                 = 3
    25  	// InternalKeyKindColumnFamilyDeletion                     = 4
    26  	// InternalKeyKindColumnFamilyValue                        = 5
    27  	// InternalKeyKindColumnFamilyMerge                        = 6
    28  	// InternalKeyKindSingleDelete                             = 7
    29  	// InternalKeyKindColumnFamilySingleDelete                 = 8
    30  	// InternalKeyKindBeginPrepareXID                          = 9
    31  	// InternalKeyKindEndPrepareXID                            = 10
    32  	// InternalKeyKindCommitXID                                = 11
    33  	// InternalKeyKindRollbackXID                              = 12
    34  	// InternalKeyKindNoop                                     = 13
    35  	// InternalKeyKindColumnFamilyRangeDelete                  = 14
    36  	InternalKeyKindRangeDelete = 15
    37  	// InternalKeyKindColumnFamilyBlobIndex                    = 16
    38  	// InternalKeyKindBlobIndex                                = 17
    39  
    40  	// This maximum value isn't part of the file format. It's unlikely,
    41  	// but future extensions may increase this value.
    42  	//
    43  	// When constructing an internal key to pass to DB.Seek{GE,LE},
    44  	// internalKeyComparer sorts decreasing by kind (after sorting increasing by
    45  	// user key and decreasing by sequence number). Thus, use InternalKeyKindMax,
    46  	// which sorts 'less than or equal to' any other valid internalKeyKind, when
    47  	// searching for any kind of internal key formed by a certain user key and
    48  	// seqNum.
    49  	InternalKeyKindMax InternalKeyKind = 17
    50  
    51  	// A marker for an invalid key.
    52  	InternalKeyKindInvalid InternalKeyKind = 255
    53  
    54  	// InternalKeySeqNumBatch is a bit that is set on batch sequence numbers
    55  	// which prevents those entries from being excluded from iteration.
    56  	InternalKeySeqNumBatch = uint64(1 << 55)
    57  
    58  	// InternalKeySeqNumMax is the largest valid sequence number.
    59  	InternalKeySeqNumMax = uint64(1<<56 - 1)
    60  
    61  	// InternalKeyRangeDeleteSentinel is the marker for a range delete sentinel
    62  	// key. This sequence number and kind are used for the upper stable boundary
    63  	// when a range deletion tombstone is the largest key in an sstable. This is
    64  	// necessary because sstable boundaries are inclusive, while the end key of a
    65  	// range deletion tombstone is exclusive.
    66  	InternalKeyRangeDeleteSentinel = (InternalKeySeqNumMax << 8) | InternalKeyKindRangeDelete
    67  )
    68  
    69  var internalKeyKindNames = []string{
    70  	InternalKeyKindDelete:      "DEL",
    71  	InternalKeyKindSet:         "SET",
    72  	InternalKeyKindMerge:       "MERGE",
    73  	InternalKeyKindLogData:     "LOGDATA",
    74  	InternalKeyKindRangeDelete: "RANGEDEL",
    75  	InternalKeyKindMax:         "MAX",
    76  	InternalKeyKindInvalid:     "INVALID",
    77  }
    78  
    79  func (k InternalKeyKind) String() string {
    80  	if int(k) < len(internalKeyKindNames) {
    81  		return internalKeyKindNames[k]
    82  	}
    83  	return fmt.Sprintf("UNKNOWN:%d", k)
    84  }
    85  
    86  // InternalKey is a key used for the in-memory and on-disk partial DBs that
    87  // make up a pebble DB.
    88  //
    89  // It consists of the user key (as given by the code that uses package pebble)
    90  // followed by 8-bytes of metadata:
    91  //   - 1 byte for the type of internal key: delete or set,
    92  //   - 7 bytes for a uint56 sequence number, in little-endian format.
    93  type InternalKey struct {
    94  	UserKey []byte
    95  	Trailer uint64
    96  }
    97  
    98  // InvalidInternalKey is an invalid internal key for which Valid() will return
    99  // false.
   100  var InvalidInternalKey = MakeInternalKey(nil, 0, InternalKeyKindInvalid)
   101  
   102  // MakeInternalKey constructs an internal key from a specified user key,
   103  // sequence number and kind.
   104  func MakeInternalKey(userKey []byte, seqNum uint64, kind InternalKeyKind) InternalKey {
   105  	return InternalKey{
   106  		UserKey: userKey,
   107  		Trailer: (seqNum << 8) | uint64(kind),
   108  	}
   109  }
   110  
   111  // MakeSearchKey constructs an internal key that is appropriate for searching
   112  // for a the specified user key. The search key contain the maximual sequence
   113  // number and kind ensuring that it sorts before any other internal keys for
   114  // the same user key.
   115  func MakeSearchKey(userKey []byte) InternalKey {
   116  	return InternalKey{
   117  		UserKey: userKey,
   118  		Trailer: (InternalKeySeqNumMax << 8) | uint64(InternalKeyKindMax),
   119  	}
   120  }
   121  
   122  // MakeRangeDeleteSentinelKey constructs an internal key that is a range
   123  // deletion sentinel key, used as the upper boundary for an sstable when a
   124  // range deletion is the largest key in an sstable.
   125  func MakeRangeDeleteSentinelKey(userKey []byte) InternalKey {
   126  	return InternalKey{
   127  		UserKey: userKey,
   128  		Trailer: InternalKeyRangeDeleteSentinel,
   129  	}
   130  }
   131  
   132  var kindsMap = map[string]InternalKeyKind{
   133  	"DEL":      InternalKeyKindDelete,
   134  	"RANGEDEL": InternalKeyKindRangeDelete,
   135  	"SET":      InternalKeyKindSet,
   136  	"MERGE":    InternalKeyKindMerge,
   137  	"INVALID":  InternalKeyKindInvalid,
   138  	"MAX":      InternalKeyKindMax,
   139  }
   140  
   141  // ParseInternalKey parses the string representation of an internal key. The
   142  // format is <user-key>.<kind>.<seq-num>. If the seq-num starts with a "b" it
   143  // is marked as a batch-seq-num (i.e. the InternalKeySeqNumBatch bit is set).
   144  func ParseInternalKey(s string) InternalKey {
   145  	x := strings.Split(s, ".")
   146  	ukey := x[0]
   147  	kind := kindsMap[x[1]]
   148  	j := 0
   149  	if x[2][0] == 'b' {
   150  		j = 1
   151  	}
   152  	seqNum, _ := strconv.ParseUint(x[2][j:], 10, 64)
   153  	if x[2][0] == 'b' {
   154  		seqNum |= InternalKeySeqNumBatch
   155  	}
   156  	return MakeInternalKey([]byte(ukey), seqNum, kind)
   157  }
   158  
   159  // DecodeInternalKey decodes an encoded internal key. See InternalKey.Encode().
   160  func DecodeInternalKey(encodedKey []byte) InternalKey {
   161  	n := len(encodedKey) - 8
   162  	var trailer uint64
   163  	if n >= 0 {
   164  		trailer = binary.LittleEndian.Uint64(encodedKey[n:])
   165  		encodedKey = encodedKey[:n:n]
   166  	} else {
   167  		trailer = uint64(InternalKeyKindInvalid)
   168  	}
   169  	return InternalKey{
   170  		UserKey: encodedKey,
   171  		Trailer: trailer,
   172  	}
   173  }
   174  
   175  // InternalCompare compares two internal keys using the specified comparison
   176  // function. For equal user keys, internal keys compare in descending sequence
   177  // number order. For equal user keys and sequence numbers, internal keys
   178  // compare in descending kind order (though this should never happen in
   179  // practice).
   180  func InternalCompare(userCmp Compare, a, b InternalKey) int {
   181  	if !a.Valid() {
   182  		if b.Valid() {
   183  			return -1
   184  		}
   185  		return bytes.Compare(a.UserKey, b.UserKey)
   186  	}
   187  	if !b.Valid() {
   188  		return 1
   189  	}
   190  	if x := userCmp(a.UserKey, b.UserKey); x != 0 {
   191  		return x
   192  	}
   193  	if a.Trailer < b.Trailer {
   194  		return 1
   195  	}
   196  	if a.Trailer > b.Trailer {
   197  		return -1
   198  	}
   199  	return 0
   200  }
   201  
   202  // Encode encodes the receiver into the buffer. The buffer must be large enough
   203  // to hold the encoded data. See InternalKey.Size().
   204  func (k InternalKey) Encode(buf []byte) {
   205  	i := copy(buf, k.UserKey)
   206  	binary.LittleEndian.PutUint64(buf[i:], k.Trailer)
   207  }
   208  
   209  // EncodeTrailer returns the trailer encoded to an 8-byte array.
   210  func (k InternalKey) EncodeTrailer() [8]byte {
   211  	var buf [8]byte
   212  	binary.LittleEndian.PutUint64(buf[:], k.Trailer)
   213  	return buf
   214  }
   215  
   216  // Separator returns a separator key such that k <= x && x < other, where less
   217  // than is consistent with the Compare function. The buf parameter may be used
   218  // to store the returned InternalKey.UserKey, though it is valid to pass a
   219  // nil. See the Separator type for details on separator keys.
   220  func (k InternalKey) Separator(
   221  	cmp Compare, sep Separator, buf []byte, other InternalKey,
   222  ) InternalKey {
   223  	buf = sep(buf, k.UserKey, other.UserKey)
   224  	if len(buf) <= len(k.UserKey) && cmp(k.UserKey, buf) < 0 {
   225  		// The separator user key is physically shorter than k.UserKey (if it is
   226  		// longer, we'll continue to use "k"), but logically after. Tack on the max
   227  		// sequence number to the shortened user key. Note that we could tack on
   228  		// any sequence number and kind here to create a valid separator key. We
   229  		// use the max sequence number to match the behavior of LevelDB and
   230  		// RocksDB.
   231  		return MakeInternalKey(buf, InternalKeySeqNumMax, InternalKeyKindMax)
   232  	}
   233  	return k
   234  }
   235  
   236  // Successor returns a successor key such that k <= x. A simple implementation
   237  // may return k unchanged. The buf parameter may be used to store the returned
   238  // InternalKey.UserKey, though it is valid to pass a nil.
   239  func (k InternalKey) Successor(cmp Compare, succ Successor, buf []byte) InternalKey {
   240  	buf = succ(buf, k.UserKey)
   241  	if len(buf) <= len(k.UserKey) && cmp(k.UserKey, buf) < 0 {
   242  		// The successor user key is physically shorter that k.UserKey (if it is
   243  		// longer, we'll continue to use "k"), but logically after. Tack on the max
   244  		// sequence number to the shortened user key. Note that we could tack on
   245  		// any sequence number and kind here to create a valid separator key. We
   246  		// use the max sequence number to match the behavior of LevelDB and
   247  		// RocksDB.
   248  		return MakeInternalKey(buf, InternalKeySeqNumMax, InternalKeyKindMax)
   249  	}
   250  	return k
   251  }
   252  
   253  // Size returns the encoded size of the key.
   254  func (k InternalKey) Size() int {
   255  	return len(k.UserKey) + 8
   256  }
   257  
   258  // SetSeqNum sets the sequence number component of the key.
   259  func (k *InternalKey) SetSeqNum(seqNum uint64) {
   260  	k.Trailer = (seqNum << 8) | (k.Trailer & 0xff)
   261  }
   262  
   263  // SeqNum returns the sequence number component of the key.
   264  func (k InternalKey) SeqNum() uint64 {
   265  	return k.Trailer >> 8
   266  }
   267  
   268  // Visible returns true if the key is visible at the specified snapshot
   269  // sequence number.
   270  func (k InternalKey) Visible(snapshot uint64) bool {
   271  	seqNum := k.SeqNum()
   272  	return seqNum < snapshot || (seqNum&InternalKeySeqNumBatch) != 0
   273  }
   274  
   275  // SetKind sets the kind component of the key.
   276  func (k *InternalKey) SetKind(kind InternalKeyKind) {
   277  	k.Trailer = (k.Trailer &^ 0xff) | uint64(kind)
   278  }
   279  
   280  // Kind returns the kind compoment of the key.
   281  func (k InternalKey) Kind() InternalKeyKind {
   282  	return InternalKeyKind(k.Trailer & 0xff)
   283  }
   284  
   285  // Valid returns true if the key has a valid kind.
   286  func (k InternalKey) Valid() bool {
   287  	return k.Kind() <= InternalKeyKindMax
   288  }
   289  
   290  // Clone clones the storage for the UserKey component of the key.
   291  func (k InternalKey) Clone() InternalKey {
   292  	if k.UserKey == nil {
   293  		return k
   294  	}
   295  	return InternalKey{
   296  		UserKey: append([]byte(nil), k.UserKey...),
   297  		Trailer: k.Trailer,
   298  	}
   299  }
   300  
   301  // String returns a string representation of the key.
   302  func (k InternalKey) String() string {
   303  	return fmt.Sprintf("%s#%d,%d", k.UserKey, k.SeqNum(), k.Kind())
   304  }
   305  
   306  // Pretty returns a pretty-printed string representation of the key.
   307  func (k InternalKey) Pretty(f func([]byte) string) string {
   308  	return fmt.Sprintf("%s#%d,%d", f(k.UserKey), k.SeqNum(), k.Kind())
   309  }