| // Copyright 2025 The etcd Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package cache |
| |
| import ( |
| "k8s.io/utils/third_party/forked/golang/btree" |
| |
| "go.etcd.io/etcd/api/v3/mvccpb" |
| ) |
| |
| // snapshot captures a full, point-in-time view of the KV state at rev. |
| type snapshot struct { |
| rev int64 |
| tree *btree.BTree[*kvItem] |
| } |
| |
| func newClonedSnapshot(rev int64, t *btree.BTree[*kvItem]) *snapshot { |
| return &snapshot{rev: rev, tree: t.Clone()} |
| } |
| |
| func (s *snapshot) Range(startKey, endKey []byte) []*mvccpb.KeyValue { |
| var out []*mvccpb.KeyValue |
| switch { |
| case len(endKey) == 0: |
| if item, ok := s.tree.Get(probeItemFromKey(startKey)); ok { |
| out = append(out, item.kv) |
| } |
| case isPrefixScan(endKey): |
| s.tree.AscendGreaterOrEqual(probeItemFromKey(startKey), func(item *kvItem) bool { |
| out = append(out, item.kv) |
| return true |
| }) |
| default: |
| s.tree.AscendRange( |
| probeItemFromKey(startKey), |
| probeItemFromKey(endKey), |
| func(item *kvItem) bool { |
| out = append(out, item.kv) |
| return true |
| }, |
| ) |
| } |
| return out |
| } |
| |
| func isPrefixScan(endKey []byte) bool { |
| return len(endKey) == 1 && endKey[0] == 0 |
| } |
| |
| func probeItemFromKey(key []byte) *kvItem { return &kvItem{key: string(key)} } |