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 }