github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/batcheval/cmd_lease_transfer.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 batcheval
    12  
    13  import (
    14  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/keys"
    17  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/batcheval/result"
    18  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/spanset"
    19  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    20  	"github.com/cockroachdb/cockroach/pkg/storage"
    21  	"github.com/cockroachdb/cockroach/pkg/util/log"
    22  )
    23  
    24  func declareKeysTransferLease(
    25  	desc *roachpb.RangeDescriptor,
    26  	header roachpb.Header,
    27  	req roachpb.Request,
    28  	latchSpans, _ *spanset.SpanSet,
    29  ) {
    30  	latchSpans.AddNonMVCC(spanset.SpanReadWrite, roachpb.Span{Key: keys.RangeLeaseKey(header.RangeID)})
    31  	latchSpans.AddNonMVCC(spanset.SpanReadOnly, roachpb.Span{Key: keys.RangeDescriptorKey(desc.StartKey)})
    32  	// Cover the entire addressable key space with a latch to prevent any writes
    33  	// from overlapping with lease transfers. In principle we could just use the
    34  	// current range descriptor (desc) but it could potentially change due to an
    35  	// as of yet unapplied merge.
    36  	latchSpans.AddNonMVCC(spanset.SpanReadOnly, roachpb.Span{Key: keys.LocalMax, EndKey: keys.MaxKey})
    37  }
    38  
    39  func init() {
    40  	RegisterReadWriteCommand(roachpb.TransferLease, declareKeysTransferLease, TransferLease)
    41  }
    42  
    43  // TransferLease sets the lease holder for the range.
    44  // Unlike with RequestLease(), the new lease is allowed to overlap the old one,
    45  // the contract being that the transfer must have been initiated by the (soon
    46  // ex-) lease holder which must have dropped all of its lease holder powers
    47  // before proposing.
    48  func TransferLease(
    49  	ctx context.Context, readWriter storage.ReadWriter, cArgs CommandArgs, resp roachpb.Response,
    50  ) (result.Result, error) {
    51  	// When returning an error from this method, must always return
    52  	// a newFailedLeaseTrigger() to satisfy stats.
    53  	args := cArgs.Args.(*roachpb.TransferLeaseRequest)
    54  
    55  	// For now, don't allow replicas of type LEARNER to be leaseholders. There's
    56  	// no reason this wouldn't work in principle, but it seems inadvisable. In
    57  	// particular, learners can't become raft leaders, so we wouldn't be able to
    58  	// co-locate the leaseholder + raft leader, which is going to affect tail
    59  	// latencies. Additionally, as of the time of writing, learner replicas are
    60  	// only used for a short time in replica addition, so it's not worth working
    61  	// out the edge cases. If we decide to start using long-lived learners at some
    62  	// point, that math may change.
    63  	//
    64  	// If this check is removed at some point, the filtering of learners on the
    65  	// sending side would have to be removed as well.
    66  	if err := checkCanReceiveLease(&args.Lease, cArgs.EvalCtx); err != nil {
    67  		return newFailedLeaseTrigger(true /* isTransfer */), err
    68  	}
    69  
    70  	prevLease, _ := cArgs.EvalCtx.GetLease()
    71  	log.VEventf(ctx, 2, "lease transfer: prev lease: %+v, new lease: %+v", prevLease, args.Lease)
    72  	return evalNewLease(ctx, cArgs.EvalCtx, readWriter, cArgs.Stats,
    73  		args.Lease, prevLease, false /* isExtension */, true /* isTransfer */)
    74  }