github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/y/y.go (about)

     1  /*
     2   * Copyright 2017 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package y
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"fmt"
    23  	"hash/crc32"
    24  	"io"
    25  	"math"
    26  	"os"
    27  	"sync"
    28  
    29  	"github.com/pingcap/errors"
    30  )
    31  
    32  // ErrEOF indicates an end of file when trying to read from a memory mapped file
    33  // and encountering the end of slice.
    34  var ErrEOF = errors.New("End of mapped region")
    35  
    36  const (
    37  	// Sync indicates that O_DSYNC should be set on the underlying file,
    38  	// ensuring that data writes do not return until the data is flushed
    39  	// to disk.
    40  	Sync = 1 << iota
    41  	// ReadOnly opens the underlying file on a read-only basis.
    42  	ReadOnly
    43  )
    44  
    45  var (
    46  	// This is O_DSYNC (datasync) on platforms that support it -- see file_unix.go
    47  	datasyncFileFlag = 0x0
    48  
    49  	// CastagnoliCrcTable is a CRC32 polynomial table
    50  	CastagnoliCrcTable = crc32.MakeTable(crc32.Castagnoli)
    51  )
    52  
    53  // OpenExistingFile opens an existing file, errors if it doesn't exist.
    54  func OpenExistingFile(filename string, flags uint32) (*os.File, error) {
    55  	openFlags := os.O_RDWR
    56  	if flags&ReadOnly != 0 {
    57  		openFlags = os.O_RDONLY
    58  	}
    59  
    60  	if flags&Sync != 0 {
    61  		openFlags |= datasyncFileFlag
    62  	}
    63  	return os.OpenFile(filename, openFlags, 0)
    64  }
    65  
    66  // CreateSyncedFile creates a new file (using O_EXCL), errors if it already existed.
    67  func CreateSyncedFile(filename string, sync bool) (*os.File, error) {
    68  	flags := os.O_RDWR | os.O_CREATE | os.O_EXCL
    69  	if sync {
    70  		flags |= datasyncFileFlag
    71  	}
    72  	return os.OpenFile(filename, flags, 0666)
    73  }
    74  
    75  // OpenSyncedFile creates the file if one doesn't exist.
    76  func OpenSyncedFile(filename string, sync bool) (*os.File, error) {
    77  	flags := os.O_RDWR | os.O_CREATE
    78  	if sync {
    79  		flags |= datasyncFileFlag
    80  	}
    81  	return os.OpenFile(filename, flags, 0666)
    82  }
    83  
    84  // OpenTruncFile opens the file with O_RDWR | O_CREATE | O_TRUNC
    85  func OpenTruncFile(filename string, sync bool) (*os.File, error) {
    86  	flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
    87  	if sync {
    88  		flags |= datasyncFileFlag
    89  	}
    90  	return os.OpenFile(filename, flags, 0666)
    91  }
    92  
    93  // SafeCopy does append(a[:0], src...).
    94  func SafeCopy(a []byte, src []byte) []byte {
    95  	return append(a[:0], src...)
    96  }
    97  
    98  // Copy copies a byte slice and returns the copied slice.
    99  func Copy(a []byte) []byte {
   100  	b := make([]byte, len(a))
   101  	copy(b, a)
   102  	return b
   103  }
   104  
   105  // KeyWithTs generates a new key by appending ts to key.
   106  func KeyWithTs(key []byte, ts uint64) Key {
   107  	return Key{
   108  		UserKey: key,
   109  		Version: ts,
   110  	}
   111  }
   112  
   113  // ParseKey parses the actual key from the key bytes.
   114  func ParseKey(keyBytes []byte) Key {
   115  	if keyBytes == nil {
   116  		return Key{}
   117  	}
   118  	return Key{
   119  		UserKey: keyBytes[:len(keyBytes)-8],
   120  		Version: math.MaxUint64 - binary.BigEndian.Uint64(keyBytes[len(keyBytes)-8:]),
   121  	}
   122  }
   123  
   124  // Slice holds a reusable buf, will reallocate if you request a larger size than ever before.
   125  // One problem is with n distinct sizes in random order it'll reallocate log(n) times.
   126  type Slice struct {
   127  	buf []byte
   128  }
   129  
   130  // Resize reuses the Slice's buffer (or makes a new one) and returns a slice in that buffer of
   131  // length sz.
   132  func (s *Slice) Resize(sz int) []byte {
   133  	if cap(s.buf) < sz {
   134  		s.buf = make([]byte, sz)
   135  	}
   136  	return s.buf[0:sz]
   137  }
   138  
   139  // Closer holds the two things we need to close a goroutine and wait for it to finish: a chan
   140  // to tell the goroutine to shut down, and a WaitGroup with which to wait for it to finish shutting
   141  // down.
   142  type Closer struct {
   143  	closed  chan struct{}
   144  	waiting sync.WaitGroup
   145  }
   146  
   147  // NewCloser constructs a new Closer, with an initial count on the WaitGroup.
   148  func NewCloser(initial int) *Closer {
   149  	ret := &Closer{closed: make(chan struct{})}
   150  	ret.waiting.Add(initial)
   151  	return ret
   152  }
   153  
   154  // AddRunning Add()'s delta to the WaitGroup.
   155  func (lc *Closer) AddRunning(delta int) {
   156  	lc.waiting.Add(delta)
   157  }
   158  
   159  // Signal signals the HasBeenClosed signal.
   160  func (lc *Closer) Signal() {
   161  	close(lc.closed)
   162  }
   163  
   164  // HasBeenClosed gets signaled when Signal() is called.
   165  func (lc *Closer) HasBeenClosed() <-chan struct{} {
   166  	return lc.closed
   167  }
   168  
   169  // Done calls Done() on the WaitGroup.
   170  func (lc *Closer) Done() {
   171  	lc.waiting.Done()
   172  }
   173  
   174  // Wait waits on the WaitGroup.  (It waits for NewCloser's initial value, AddRunning, and Done
   175  // calls to balance out.)
   176  func (lc *Closer) Wait() {
   177  	lc.waiting.Wait()
   178  }
   179  
   180  // SignalAndWait calls Signal(), then Wait().
   181  func (lc *Closer) SignalAndWait() {
   182  	lc.Signal()
   183  	lc.Wait()
   184  }
   185  
   186  // Key is the struct for user key with version.
   187  type Key struct {
   188  	UserKey []byte
   189  	Version uint64
   190  }
   191  
   192  func (k Key) Compare(k2 Key) int {
   193  	cmp := bytes.Compare(k.UserKey, k2.UserKey)
   194  	if cmp != 0 {
   195  		return cmp
   196  	}
   197  	if k.Version > k2.Version {
   198  		// Greater version is considered smaller because we need to iterate keys from newer to older.
   199  		return -1
   200  	} else if k.Version < k2.Version {
   201  		return 1
   202  	}
   203  	return 0
   204  }
   205  
   206  func (k Key) Equal(k2 Key) bool {
   207  	if !bytes.Equal(k.UserKey, k2.UserKey) {
   208  		return false
   209  	}
   210  	return k.Version == k2.Version
   211  }
   212  
   213  func (k Key) IsEmpty() bool {
   214  	return len(k.UserKey) == 0
   215  }
   216  
   217  func (k *Key) Copy(k2 Key) {
   218  	k.UserKey = append(k.UserKey[:0], k2.UserKey...)
   219  	k.Version = k2.Version
   220  }
   221  
   222  func (k *Key) Reset() {
   223  	k.UserKey = k.UserKey[:0]
   224  }
   225  
   226  func (k Key) Len() int {
   227  	return len(k.UserKey) + 8
   228  }
   229  
   230  func (k Key) AppendTo(buf []byte) []byte {
   231  	buf = append(buf, k.UserKey...)
   232  	var uBuf [8]byte
   233  	binary.BigEndian.PutUint64(uBuf[:], math.MaxUint64-k.Version)
   234  	return append(buf, uBuf[:]...)
   235  }
   236  
   237  func (k Key) WriteTo(w io.Writer) error {
   238  	_, err := w.Write(k.UserKey)
   239  	if err != nil {
   240  		return err
   241  	}
   242  	var uBuf [8]byte
   243  	binary.BigEndian.PutUint64(uBuf[:], math.MaxUint64-k.Version)
   244  	_, err = w.Write(uBuf[:])
   245  	return err
   246  }
   247  
   248  func (k Key) SameUserKey(k2 Key) bool {
   249  	return bytes.Equal(k.UserKey, k2.UserKey)
   250  }
   251  
   252  func (k Key) String() string {
   253  	return fmt.Sprintf("%x(%d)", k.UserKey, k.Version)
   254  }