github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/ekv/union_store.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package ekv
    15  
    16  import (
    17  	"context"
    18  )
    19  
    20  // UnionStore is a causetstore that wraps a snapshot for read and a MemBuffer for buffered write.
    21  // Also, it provides some transaction related utilities.
    22  type UnionStore interface {
    23  	Retriever
    24  
    25  	// HasPresumeKeyNotExists returns whether the key presumed key not exists error for the lazy check.
    26  	HasPresumeKeyNotExists(k Key) bool
    27  	// DeleteKeyExistErrInfo deletes the key presume key not exists error flag for the lazy check.
    28  	UnmarkPresumeKeyNotExists(k Key)
    29  	// CacheIndexName caches the index name.
    30  	// PresumeKeyNotExists will use this to help decode error message.
    31  	CacheIndexName(blockID, indexID int64, name string)
    32  	// GetIndexName returns the cached index name.
    33  	// If there is no such index already inserted through CacheIndexName, it will return UNKNOWN.
    34  	GetIndexName(blockID, indexID int64) string
    35  
    36  	// SetOption sets an option with a value, when val is nil, uses the default
    37  	// value of this option.
    38  	SetOption(opt Option, val interface{})
    39  	// DelOption deletes an option.
    40  	DelOption(opt Option)
    41  	// GetOption gets an option.
    42  	GetOption(opt Option) interface{}
    43  	// GetMemBuffer return the MemBuffer binding to this unionStore.
    44  	GetMemBuffer() MemBuffer
    45  }
    46  
    47  // AssertionType is the type of a assertion.
    48  type AssertionType int
    49  
    50  // The AssertionType constants.
    51  const (
    52  	None AssertionType = iota
    53  	Exist
    54  	NotExist
    55  )
    56  
    57  // Option is used for customizing ekv causetstore's behaviors during a transaction.
    58  type Option int
    59  
    60  // Options is an interface of a set of options. Each option is associated with a value.
    61  type Options interface {
    62  	// Get gets an option value.
    63  	Get(opt Option) (v interface{}, ok bool)
    64  }
    65  
    66  type idxNameKey struct {
    67  	blockID, indexID int64
    68  }
    69  
    70  // unionStore is an in-memory CausetStore which contains a buffer for write and a
    71  // snapshot for read.
    72  type unionStore struct {
    73  	memBuffer    *memdb
    74  	snapshot     Snapshot
    75  	idxNameCache map[idxNameKey]string
    76  	opts         options
    77  }
    78  
    79  // NewUnionStore builds a new unionStore.
    80  func NewUnionStore(snapshot Snapshot) UnionStore {
    81  	return &unionStore{
    82  		snapshot:     snapshot,
    83  		memBuffer:    newMemDB(),
    84  		idxNameCache: make(map[idxNameKey]string),
    85  		opts:         make(map[Option]interface{}),
    86  	}
    87  }
    88  
    89  // GetMemBuffer return the MemBuffer binding to this unionStore.
    90  func (us *unionStore) GetMemBuffer() MemBuffer {
    91  	return us.memBuffer
    92  }
    93  
    94  // Get implements the Retriever interface.
    95  func (us *unionStore) Get(ctx context.Context, k Key) ([]byte, error) {
    96  	v, err := us.memBuffer.Get(ctx, k)
    97  	if IsErrNotFound(err) {
    98  		v, err = us.snapshot.Get(ctx, k)
    99  	}
   100  	if err != nil {
   101  		return v, err
   102  	}
   103  	if len(v) == 0 {
   104  		return nil, ErrNotExist
   105  	}
   106  	return v, nil
   107  }
   108  
   109  // Iter implements the Retriever interface.
   110  func (us *unionStore) Iter(k Key, upperBound Key) (Iterator, error) {
   111  	bufferIt, err := us.memBuffer.Iter(k, upperBound)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	retrieverIt, err := us.snapshot.Iter(k, upperBound)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	return NewUnionIter(bufferIt, retrieverIt, false)
   120  }
   121  
   122  // IterReverse implements the Retriever interface.
   123  func (us *unionStore) IterReverse(k Key) (Iterator, error) {
   124  	bufferIt, err := us.memBuffer.IterReverse(k)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	retrieverIt, err := us.snapshot.IterReverse(k)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	return NewUnionIter(bufferIt, retrieverIt, true)
   133  }
   134  
   135  // HasPresumeKeyNotExists gets the key exist error info for the lazy check.
   136  func (us *unionStore) HasPresumeKeyNotExists(k Key) bool {
   137  	flags, err := us.memBuffer.GetFlags(k)
   138  	if err != nil {
   139  		return false
   140  	}
   141  	return flags.HasPresumeKeyNotExists()
   142  }
   143  
   144  // DeleteKeyExistErrInfo deletes the key exist error info for the lazy check.
   145  func (us *unionStore) UnmarkPresumeKeyNotExists(k Key) {
   146  	us.memBuffer.UFIDelateFlags(k, DelPresumeKeyNotExists)
   147  }
   148  
   149  func (us *unionStore) GetIndexName(blockID, indexID int64) string {
   150  	key := idxNameKey{blockID: blockID, indexID: indexID}
   151  	name, ok := us.idxNameCache[key]
   152  	if !ok {
   153  		return "UNKNOWN"
   154  	}
   155  	return name
   156  }
   157  
   158  func (us *unionStore) CacheIndexName(blockID, indexID int64, name string) {
   159  	key := idxNameKey{blockID: blockID, indexID: indexID}
   160  	us.idxNameCache[key] = name
   161  }
   162  
   163  // SetOption implements the unionStore SetOption interface.
   164  func (us *unionStore) SetOption(opt Option, val interface{}) {
   165  	us.opts[opt] = val
   166  }
   167  
   168  // DelOption implements the unionStore DelOption interface.
   169  func (us *unionStore) DelOption(opt Option) {
   170  	delete(us.opts, opt)
   171  }
   172  
   173  // GetOption implements the unionStore GetOption interface.
   174  func (us *unionStore) GetOption(opt Option) interface{} {
   175  	return us.opts[opt]
   176  }
   177  
   178  type options map[Option]interface{}
   179  
   180  func (opts options) Get(opt Option) (interface{}, bool) {
   181  	v, ok := opts[opt]
   182  	return v, ok
   183  }