github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/key.go (about)

     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  
     7  package leveldb
     8  
     9  import (
    10  	"encoding/binary"
    11  	"fmt"
    12  
    13  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors"
    14  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/storage"
    15  )
    16  
    17  // ErrInternalKeyCorrupted records internal key corruption.
    18  type ErrInternalKeyCorrupted struct {
    19  	Ikey   []byte
    20  	Reason string
    21  }
    22  
    23  func (e *ErrInternalKeyCorrupted) Error() string {
    24  	return fmt.Sprintf("leveldb: internal key %q corrupted: %s", e.Ikey, e.Reason)
    25  }
    26  
    27  func newErrInternalKeyCorrupted(ikey []byte, reason string) error {
    28  	return errors.NewErrCorrupted(storage.FileDesc{}, &ErrInternalKeyCorrupted{append([]byte{}, ikey...), reason})
    29  }
    30  
    31  type keyType uint
    32  
    33  func (kt keyType) String() string {
    34  	switch kt {
    35  	case keyTypeDel:
    36  		return "d"
    37  	case keyTypeVal:
    38  		return "v"
    39  	}
    40  	return "x"
    41  }
    42  
    43  // Value types encoded as the last component of internal keys.
    44  // Don't modify; this value are saved to disk.
    45  const (
    46  	keyTypeDel keyType = iota
    47  	keyTypeVal
    48  )
    49  
    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
    56  
    57  const (
    58  	// Maximum value possible for sequence number; the 8-bits are
    59  	// used by value type, so its can packed together in single
    60  	// 64-bit integer.
    61  	keyMaxSeq = (uint64(1) << 56) - 1
    62  	// Maximum value possible for packed sequence number and type.
    63  	keyMaxNum = (keyMaxSeq << 8) | uint64(keyTypeSeek)
    64  )
    65  
    66  // Maximum number encoded in bytes.
    67  var keyMaxNumBytes = make([]byte, 8)
    68  
    69  func init() {
    70  	binary.LittleEndian.PutUint64(keyMaxNumBytes, keyMaxNum)
    71  }
    72  
    73  type internalKey []byte
    74  
    75  func makeInternalKey(dst, ukey []byte, seq uint64, kt keyType) internalKey {
    76  	if seq > keyMaxSeq {
    77  		panic("leveldb: invalid sequence number")
    78  	} else if kt > keyTypeVal {
    79  		panic("leveldb: invalid type")
    80  	}
    81  
    82  	if n := len(ukey) + 8; cap(dst) < n {
    83  		dst = make([]byte, n)
    84  	} else {
    85  		dst = dst[:n]
    86  	}
    87  	copy(dst, ukey)
    88  	binary.LittleEndian.PutUint64(dst[len(ukey):], (seq<<8)|uint64(kt))
    89  	return internalKey(dst)
    90  }
    91  
    92  func parseInternalKey(ik []byte) (ukey []byte, seq uint64, kt keyType, err error) {
    93  	if len(ik) < 8 {
    94  		return nil, 0, 0, newErrInternalKeyCorrupted(ik, "invalid length")
    95  	}
    96  	num := binary.LittleEndian.Uint64(ik[len(ik)-8:])
    97  	seq, kt = uint64(num>>8), keyType(num&0xff)
    98  	if kt > keyTypeVal {
    99  		return nil, 0, 0, newErrInternalKeyCorrupted(ik, "invalid type")
   100  	}
   101  	ukey = ik[:len(ik)-8]
   102  	return
   103  }
   104  
   105  func validInternalKey(ik []byte) bool {
   106  	_, _, _, err := parseInternalKey(ik)
   107  	return err == nil
   108  }
   109  
   110  func (ik internalKey) assert() {
   111  	if ik == nil {
   112  		panic("leveldb: nil internalKey")
   113  	}
   114  	if len(ik) < 8 {
   115  		panic(fmt.Sprintf("leveldb: internal key %q, len=%d: invalid length", []byte(ik), len(ik)))
   116  	}
   117  }
   118  
   119  func (ik internalKey) ukey() []byte {
   120  	ik.assert()
   121  	return ik[:len(ik)-8]
   122  }
   123  
   124  func (ik internalKey) num() uint64 {
   125  	ik.assert()
   126  	return binary.LittleEndian.Uint64(ik[len(ik)-8:])
   127  }
   128  
   129  func (ik internalKey) parseNum() (seq uint64, kt keyType) {
   130  	num := ik.num()
   131  	seq, kt = uint64(num>>8), keyType(num&0xff)
   132  	if kt > keyTypeVal {
   133  		panic(fmt.Sprintf("leveldb: internal key %q, len=%d: invalid type %#x", []byte(ik), len(ik), kt))
   134  	}
   135  	return
   136  }
   137  
   138  func (ik internalKey) String() string {
   139  	if ik == nil {
   140  		return "<nil>"
   141  	}
   142  
   143  	if ukey, seq, kt, err := parseInternalKey(ik); err == nil {
   144  		return fmt.Sprintf("%s,%s%d", shorten(string(ukey)), kt, seq)
   145  	}
   146  	return "<invalid>"
   147  }