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  }