github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/addressing.go (about)

     1  // Copyright 2014 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 kvserver
    12  
    13  import (
    14  	"bytes"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/keys"
    17  	"github.com/cockroachdb/cockroach/pkg/kv"
    18  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    19  	"github.com/cockroachdb/errors"
    20  )
    21  
    22  type metaAction func(*kv.Batch, roachpb.Key, *roachpb.RangeDescriptor)
    23  
    24  func putMeta(b *kv.Batch, key roachpb.Key, desc *roachpb.RangeDescriptor) {
    25  	b.Put(key, desc)
    26  }
    27  
    28  func delMeta(b *kv.Batch, key roachpb.Key, desc *roachpb.RangeDescriptor) {
    29  	b.Del(key)
    30  }
    31  
    32  // splitRangeAddressing creates (or overwrites if necessary) the meta1
    33  // and meta2 range addressing records for the left and right ranges
    34  // caused by a split.
    35  func splitRangeAddressing(b *kv.Batch, left, right *roachpb.RangeDescriptor) error {
    36  	if err := rangeAddressing(b, left, putMeta); err != nil {
    37  		return err
    38  	}
    39  	return rangeAddressing(b, right, putMeta)
    40  }
    41  
    42  // mergeRangeAddressing removes subsumed meta1 and meta2 range
    43  // addressing records caused by merging and updates the records for
    44  // the new merged range. Left is the range descriptor for the "left"
    45  // range before merging and merged describes the left to right merge.
    46  func mergeRangeAddressing(b *kv.Batch, left, merged *roachpb.RangeDescriptor) error {
    47  	if err := rangeAddressing(b, left, delMeta); err != nil {
    48  		return err
    49  	}
    50  	return rangeAddressing(b, merged, putMeta)
    51  }
    52  
    53  // updateRangeAddressing overwrites the meta1 and meta2 range addressing
    54  // records for the descriptor.
    55  func updateRangeAddressing(b *kv.Batch, desc *roachpb.RangeDescriptor) error {
    56  	return rangeAddressing(b, desc, putMeta)
    57  }
    58  
    59  // rangeAddressing updates or deletes the range addressing metadata
    60  // for the range specified by desc. The action to take is specified by
    61  // the supplied metaAction function.
    62  //
    63  // The rules for meta1 and meta2 records are as follows:
    64  //
    65  //  1. If desc.StartKey or desc.EndKey is meta1:
    66  //     - ERROR
    67  //  2. If desc.EndKey is meta2:
    68  //     - meta1(desc.EndKey)
    69  //  3. If desc.EndKey is normal user key:
    70  //     - meta2(desc.EndKey)
    71  //     3a. If desc.StartKey is not normal user key:
    72  //         - meta1(KeyMax)
    73  func rangeAddressing(b *kv.Batch, desc *roachpb.RangeDescriptor, action metaAction) error {
    74  	// 1. handle illegal case of start or end key being meta1.
    75  	if bytes.HasPrefix(desc.EndKey, keys.Meta1Prefix) ||
    76  		bytes.HasPrefix(desc.StartKey, keys.Meta1Prefix) {
    77  		return errors.Errorf("meta1 addressing records cannot be split: %+v", desc)
    78  	}
    79  
    80  	// Note that both cases 2 and 3 are handled by keys.RangeMetaKey.
    81  	//
    82  	// 2. the case of the range ending with a meta2 prefix. This means
    83  	// the range is full of meta2. We must update the relevant meta1
    84  	// entry pointing to the end of this range.
    85  	//
    86  	// 3. the range ends with a normal user key, so we must update the
    87  	// relevant meta2 entry pointing to the end of this range.
    88  	action(b, keys.RangeMetaKey(desc.EndKey).AsRawKey(), desc)
    89  
    90  	if bytes.Compare(desc.StartKey, keys.MetaMax) < 0 &&
    91  		bytes.Compare(desc.EndKey, keys.MetaMax) >= 0 {
    92  		// 3a. the range spans meta2 and user keys, update the meta1
    93  		// entry for KeyMax. We do this to prevent the 3 levels of
    94  		// descriptor indirection described in #18998.
    95  		action(b, keys.Meta1KeyMax, desc)
    96  	}
    97  	return nil
    98  }