github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/unionstore/memdb_snapshot.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/memdb_snapshot.go 19 // 20 21 // Copyright 2020 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 tikverr "github.com/KinWaiYuen/client-go/v2/error" 39 ) 40 41 // SnapshotGetter returns a Getter for a snapshot of MemBuffer. 42 func (db *MemDB) SnapshotGetter() Getter { 43 return &memdbSnapGetter{ 44 db: db, 45 cp: db.getSnapshot(), 46 } 47 } 48 49 // SnapshotIter returns a Iterator for a snapshot of MemBuffer. 50 func (db *MemDB) SnapshotIter(start, end []byte) Iterator { 51 it := &memdbSnapIter{ 52 MemdbIterator: &MemdbIterator{ 53 db: db, 54 start: start, 55 end: end, 56 }, 57 cp: db.getSnapshot(), 58 } 59 it.init() 60 return it 61 } 62 63 func (db *MemDB) getSnapshot() memdbCheckpoint { 64 if len(db.stages) > 0 { 65 return db.stages[0] 66 } 67 return db.vlog.checkpoint() 68 } 69 70 type memdbSnapGetter struct { 71 db *MemDB 72 cp memdbCheckpoint 73 } 74 75 func (snap *memdbSnapGetter) Get(key []byte) ([]byte, error) { 76 x := snap.db.traverse(key, false) 77 if x.isNull() { 78 return nil, tikverr.ErrNotExist 79 } 80 if x.vptr.isNull() { 81 // A flag only key, act as value not exists 82 return nil, tikverr.ErrNotExist 83 } 84 v, ok := snap.db.vlog.getSnapshotValue(x.vptr, &snap.cp) 85 if !ok { 86 return nil, tikverr.ErrNotExist 87 } 88 return v, nil 89 } 90 91 type memdbSnapIter struct { 92 *MemdbIterator 93 value []byte 94 cp memdbCheckpoint 95 } 96 97 func (i *memdbSnapIter) Value() []byte { 98 return i.value 99 } 100 101 func (i *memdbSnapIter) Next() error { 102 i.value = nil 103 for i.Valid() { 104 if err := i.MemdbIterator.Next(); err != nil { 105 return err 106 } 107 if i.setValue() { 108 return nil 109 } 110 } 111 return nil 112 } 113 114 func (i *memdbSnapIter) setValue() bool { 115 if !i.Valid() { 116 return false 117 } 118 if v, ok := i.db.vlog.getSnapshotValue(i.curr.vptr, &i.cp); ok { 119 i.value = v 120 return true 121 } 122 return false 123 } 124 125 func (i *memdbSnapIter) init() { 126 if len(i.start) == 0 { 127 i.seekToFirst() 128 } else { 129 i.seek(i.start) 130 } 131 132 if !i.setValue() { 133 err := i.Next() 134 _ = err // memdbIterator will never fail 135 } 136 }