github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/rditer/replica_data_iter.go (about) 1 // Copyright 2015 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package rditer 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/keys" 15 "github.com/cockroachdb/cockroach/pkg/roachpb" 16 "github.com/cockroachdb/cockroach/pkg/storage" 17 "github.com/cockroachdb/cockroach/pkg/util/bufalloc" 18 ) 19 20 // KeyRange is a helper struct for the ReplicaDataIterator. 21 type KeyRange struct { 22 Start, End storage.MVCCKey 23 } 24 25 // ReplicaDataIterator provides a complete iteration over all key / value 26 // rows in a range, including all system-local metadata and user data. 27 // The ranges keyRange slice specifies the key ranges which comprise 28 // all of the range's data. 29 // 30 // A ReplicaDataIterator provides a subset of the engine.Iterator interface. 31 // 32 // TODO(tschottdorf): the API is awkward. By default, ReplicaDataIterator uses 33 // a byte allocator which needs to be reset manually using `ResetAllocator`. 34 // This is problematic as it requires of every user careful tracking of when 35 // to call that method; some just never call it and pull the whole replica 36 // into memory. Use of an allocator should be opt-in. 37 type ReplicaDataIterator struct { 38 curIndex int 39 ranges []KeyRange 40 it storage.Iterator 41 a bufalloc.ByteAllocator 42 } 43 44 // MakeAllKeyRanges returns all key ranges for the given Range. 45 func MakeAllKeyRanges(d *roachpb.RangeDescriptor) []KeyRange { 46 return []KeyRange{ 47 MakeRangeIDLocalKeyRange(d.RangeID, false /* replicatedOnly */), 48 MakeRangeLocalKeyRange(d), 49 MakeUserKeyRange(d), 50 } 51 } 52 53 // MakeReplicatedKeyRanges returns all key ranges that are fully Raft 54 // replicated for the given Range. 55 // 56 // NOTE: The logic for receiving snapshot relies on this function returning the 57 // ranges in the following sorted order: 58 // 59 // 1. Replicated range-id local key range 60 // 2. Range-local key range 61 // 3. User key range 62 func MakeReplicatedKeyRanges(d *roachpb.RangeDescriptor) []KeyRange { 63 return []KeyRange{ 64 MakeRangeIDLocalKeyRange(d.RangeID, true /* replicatedOnly */), 65 MakeRangeLocalKeyRange(d), 66 MakeUserKeyRange(d), 67 } 68 } 69 70 // MakeRangeIDLocalKeyRange returns the range-id local key range. If 71 // replicatedOnly is true, then it returns only the replicated keys, otherwise, 72 // it only returns both the replicated and unreplicated keys. 73 func MakeRangeIDLocalKeyRange(rangeID roachpb.RangeID, replicatedOnly bool) KeyRange { 74 var prefixFn func(roachpb.RangeID) roachpb.Key 75 if replicatedOnly { 76 prefixFn = keys.MakeRangeIDReplicatedPrefix 77 } else { 78 prefixFn = keys.MakeRangeIDPrefix 79 } 80 sysRangeIDKey := prefixFn(rangeID) 81 return KeyRange{ 82 Start: storage.MakeMVCCMetadataKey(sysRangeIDKey), 83 End: storage.MakeMVCCMetadataKey(sysRangeIDKey.PrefixEnd()), 84 } 85 } 86 87 // MakeRangeLocalKeyRange returns the range local key range. Range-local keys 88 // are replicated keys that do not belong to the range they would naturally 89 // sort into. For example, /Local/Range/Table/1 would sort into [/Min, 90 // /System), but it actually belongs to [/Table/1, /Table/2). 91 func MakeRangeLocalKeyRange(d *roachpb.RangeDescriptor) KeyRange { 92 return KeyRange{ 93 Start: storage.MakeMVCCMetadataKey(keys.MakeRangeKeyPrefix(d.StartKey)), 94 End: storage.MakeMVCCMetadataKey(keys.MakeRangeKeyPrefix(d.EndKey)), 95 } 96 } 97 98 // MakeUserKeyRange returns the user key range. 99 func MakeUserKeyRange(d *roachpb.RangeDescriptor) KeyRange { 100 // The first range in the keyspace starts at KeyMin, which includes the 101 // node-local space. We need the original StartKey to find the range 102 // metadata, but the actual data starts at LocalMax. 103 dataStartKey := d.StartKey.AsRawKey() 104 if d.StartKey.Equal(roachpb.RKeyMin) { 105 dataStartKey = keys.LocalMax 106 } 107 return KeyRange{ 108 Start: storage.MakeMVCCMetadataKey(dataStartKey), 109 End: storage.MakeMVCCMetadataKey(d.EndKey.AsRawKey()), 110 } 111 } 112 113 // NewReplicaDataIterator creates a ReplicaDataIterator for the given replica. 114 func NewReplicaDataIterator( 115 d *roachpb.RangeDescriptor, reader storage.Reader, replicatedOnly bool, seekEnd bool, 116 ) *ReplicaDataIterator { 117 it := reader.NewIterator(storage.IterOptions{UpperBound: d.EndKey.AsRawKey()}) 118 119 rangeFunc := MakeAllKeyRanges 120 if replicatedOnly { 121 rangeFunc = MakeReplicatedKeyRanges 122 } 123 ri := &ReplicaDataIterator{ 124 ranges: rangeFunc(d), 125 it: it, 126 } 127 if seekEnd { 128 ri.seekEnd() 129 } else { 130 ri.seekStart() 131 } 132 return ri 133 } 134 135 // seekStart seeks the iterator to the start of its data range. 136 func (ri *ReplicaDataIterator) seekStart() { 137 ri.curIndex = 0 138 ri.it.SeekGE(ri.ranges[ri.curIndex].Start) 139 ri.advance() 140 } 141 142 // seekEnd seeks the iterator to the end of its data range. 143 func (ri *ReplicaDataIterator) seekEnd() { 144 ri.curIndex = len(ri.ranges) - 1 145 ri.it.SeekLT(ri.ranges[ri.curIndex].End) 146 ri.retreat() 147 } 148 149 // Close the underlying iterator. 150 func (ri *ReplicaDataIterator) Close() { 151 ri.curIndex = len(ri.ranges) 152 ri.it.Close() 153 } 154 155 // Next advances to the next key in the iteration. 156 func (ri *ReplicaDataIterator) Next() { 157 ri.it.Next() 158 ri.advance() 159 } 160 161 // advance moves the iterator forward through the ranges until a valid 162 // key is found or the iteration is done and the iterator becomes 163 // invalid. 164 func (ri *ReplicaDataIterator) advance() { 165 for { 166 if ok, _ := ri.Valid(); ok && ri.it.UnsafeKey().Less(ri.ranges[ri.curIndex].End) { 167 return 168 } 169 ri.curIndex++ 170 if ri.curIndex < len(ri.ranges) { 171 ri.it.SeekGE(ri.ranges[ri.curIndex].Start) 172 } else { 173 return 174 } 175 } 176 } 177 178 // Prev advances the iterator one key backwards. 179 func (ri *ReplicaDataIterator) Prev() { 180 ri.it.Prev() 181 ri.retreat() 182 } 183 184 // retreat is the opposite of advance. 185 func (ri *ReplicaDataIterator) retreat() { 186 for { 187 if ok, _ := ri.Valid(); ok && ri.ranges[ri.curIndex].Start.Less(ri.it.UnsafeKey()) { 188 return 189 } 190 ri.curIndex-- 191 if ri.curIndex >= 0 { 192 ri.it.SeekLT(ri.ranges[ri.curIndex].End) 193 } else { 194 return 195 } 196 } 197 } 198 199 // Valid returns true if the iterator currently points to a valid value. 200 func (ri *ReplicaDataIterator) Valid() (bool, error) { 201 ok, err := ri.it.Valid() 202 ok = ok && ri.curIndex >= 0 && ri.curIndex < len(ri.ranges) 203 return ok, err 204 } 205 206 // Key returns the current key. 207 func (ri *ReplicaDataIterator) Key() storage.MVCCKey { 208 key := ri.it.UnsafeKey() 209 ri.a, key.Key = ri.a.Copy(key.Key, 0) 210 return key 211 } 212 213 // Value returns the current value. 214 func (ri *ReplicaDataIterator) Value() []byte { 215 value := ri.it.UnsafeValue() 216 ri.a, value = ri.a.Copy(value, 0) 217 return value 218 } 219 220 // UnsafeKey returns the same value as Key, but the memory is invalidated on 221 // the next call to {Next,Prev,Close}. 222 func (ri *ReplicaDataIterator) UnsafeKey() storage.MVCCKey { 223 return ri.it.UnsafeKey() 224 } 225 226 // UnsafeValue returns the same value as Value, but the memory is invalidated on 227 // the next call to {Next,Prev,Close}. 228 func (ri *ReplicaDataIterator) UnsafeValue() []byte { 229 return ri.it.UnsafeValue() 230 } 231 232 // ResetAllocator resets the ReplicaDataIterator's internal byte allocator. 233 func (ri *ReplicaDataIterator) ResetAllocator() { 234 ri.a = nil 235 }