github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/unionstore/union_store.go (about)

     1  // Copyright 2021 TiKV Authors
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // NOTE: The code in this file is based on code from the
    16  // TiDB project, licensed under the Apache License v 2.0
    17  //
    18  // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/unionstore/union_store.go
    19  //
    20  
    21  // Copyright 2021 PingCAP, Inc.
    22  
    23  // Licensed under the Apache License, Version 2.0 (the "License");
    24  // you may not use this file except in compliance with the License.
    25  // You may obtain a copy of the License at
    26  //
    27  //     http://www.apache.org/licenses/LICENSE-2.0
    28  //
    29  // Unless required by applicable law or agreed to in writing, software
    30  // distributed under the License is distributed on an "AS IS" BASIS,
    31  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    32  // See the License for the specific language governing permissions and
    33  // limitations under the License.
    34  
    35  package unionstore
    36  
    37  import (
    38  	"context"
    39  
    40  	tikverr "github.com/KinWaiYuen/client-go/v2/error"
    41  	"github.com/KinWaiYuen/client-go/v2/kv"
    42  )
    43  
    44  // Iterator is the interface for a iterator on KV store.
    45  type Iterator interface {
    46  	Valid() bool
    47  	Key() []byte
    48  	Value() []byte
    49  	Next() error
    50  	Close()
    51  }
    52  
    53  // Getter is the interface for the Get method.
    54  type Getter interface {
    55  	// Get gets the value for key k from kv store.
    56  	// If corresponding kv pair does not exist, it returns nil and ErrNotExist.
    57  	Get(k []byte) ([]byte, error)
    58  }
    59  
    60  // uSnapshot defines the interface for the snapshot fetched from KV store.
    61  type uSnapshot interface {
    62  	// Get gets the value for key k from kv store.
    63  	// If corresponding kv pair does not exist, it returns nil and ErrNotExist.
    64  	Get(ctx context.Context, k []byte) ([]byte, error)
    65  	// Iter creates an Iterator positioned on the first entry that k <= entry's key.
    66  	// If such entry is not found, it returns an invalid Iterator with no error.
    67  	// It yields only keys that < upperBound. If upperBound is nil, it means the upperBound is unbounded.
    68  	// The Iterator must be Closed after use.
    69  	Iter(k []byte, upperBound []byte) (Iterator, error)
    70  
    71  	// IterReverse creates a reversed Iterator positioned on the first entry which key is less than k.
    72  	// The returned iterator will iterate from greater key to smaller key.
    73  	// If k is nil, the returned iterator will be positioned at the last key.
    74  	// TODO: Add lower bound limit
    75  	IterReverse(k []byte) (Iterator, error)
    76  }
    77  
    78  // KVUnionStore is an in-memory Store which contains a buffer for write and a
    79  // snapshot for read.
    80  type KVUnionStore struct {
    81  	memBuffer *MemDB
    82  	snapshot  uSnapshot
    83  }
    84  
    85  // NewUnionStore builds a new unionStore.
    86  func NewUnionStore(snapshot uSnapshot) *KVUnionStore {
    87  	return &KVUnionStore{
    88  		snapshot:  snapshot,
    89  		memBuffer: newMemDB(),
    90  	}
    91  }
    92  
    93  // GetMemBuffer return the MemBuffer binding to this unionStore.
    94  func (us *KVUnionStore) GetMemBuffer() *MemDB {
    95  	return us.memBuffer
    96  }
    97  
    98  // Get implements the Retriever interface.
    99  func (us *KVUnionStore) Get(ctx context.Context, k []byte) ([]byte, error) {
   100  	v, err := us.memBuffer.Get(k)
   101  	if tikverr.IsErrNotFound(err) {
   102  		v, err = us.snapshot.Get(ctx, k)
   103  	}
   104  	if err != nil {
   105  		return v, err
   106  	}
   107  	if len(v) == 0 {
   108  		return nil, tikverr.ErrNotExist
   109  	}
   110  	return v, nil
   111  }
   112  
   113  // Iter implements the Retriever interface.
   114  func (us *KVUnionStore) Iter(k, upperBound []byte) (Iterator, error) {
   115  	bufferIt, err := us.memBuffer.Iter(k, upperBound)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	retrieverIt, err := us.snapshot.Iter(k, upperBound)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	return NewUnionIter(bufferIt, retrieverIt, false)
   124  }
   125  
   126  // IterReverse implements the Retriever interface.
   127  func (us *KVUnionStore) IterReverse(k []byte) (Iterator, error) {
   128  	bufferIt, err := us.memBuffer.IterReverse(k)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	retrieverIt, err := us.snapshot.IterReverse(k)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  	return NewUnionIter(bufferIt, retrieverIt, true)
   137  }
   138  
   139  // HasPresumeKeyNotExists gets the key exist error info for the lazy check.
   140  func (us *KVUnionStore) HasPresumeKeyNotExists(k []byte) bool {
   141  	flags, err := us.memBuffer.GetFlags(k)
   142  	if err != nil {
   143  		return false
   144  	}
   145  	return flags.HasPresumeKeyNotExists()
   146  }
   147  
   148  // UnmarkPresumeKeyNotExists deletes the key exist error info for the lazy check.
   149  func (us *KVUnionStore) UnmarkPresumeKeyNotExists(k []byte) {
   150  	us.memBuffer.UpdateFlags(k, kv.DelPresumeKeyNotExists)
   151  }
   152  
   153  // SetEntrySizeLimit sets the size limit for each entry and total buffer.
   154  func (us *KVUnionStore) SetEntrySizeLimit(entryLimit, bufferLimit uint64) {
   155  	us.memBuffer.entrySizeLimit = entryLimit
   156  	us.memBuffer.bufferSizeLimit = bufferLimit
   157  }