github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/store_merge.go (about) 1 // Copyright 2019 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 "context" 15 16 "github.com/cockroachdb/cockroach/pkg/roachpb" 17 "github.com/cockroachdb/cockroach/pkg/util/hlc" 18 "github.com/cockroachdb/errors" 19 ) 20 21 // MergeRange expands the left-hand replica, leftRepl, to absorb the right-hand 22 // replica, identified by rightDesc. freezeStart specifies the time at which the 23 // right-hand replica promised to stop serving traffic and is used to initialize 24 // the timestamp cache's low water mark for the right-hand keyspace. The 25 // right-hand replica must exist on this store and the raftMus for both the 26 // left-hand and right-hand replicas must be held. 27 func (s *Store) MergeRange( 28 ctx context.Context, 29 leftRepl *Replica, 30 newLeftDesc, rightDesc roachpb.RangeDescriptor, 31 freezeStart hlc.Timestamp, 32 ) error { 33 if oldLeftDesc := leftRepl.Desc(); !oldLeftDesc.EndKey.Less(newLeftDesc.EndKey) { 34 return errors.Errorf("the new end key is not greater than the current one: %+v <= %+v", 35 newLeftDesc.EndKey, oldLeftDesc.EndKey) 36 } 37 38 rightRepl, err := s.GetReplica(rightDesc.RangeID) 39 if err != nil { 40 return err 41 } 42 43 leftRepl.raftMu.AssertHeld() 44 rightRepl.raftMu.AssertHeld() 45 46 if err := rightRepl.postDestroyRaftMuLocked(ctx, rightRepl.GetMVCCStats()); err != nil { 47 return err 48 } 49 50 // Note that we were called (indirectly) from raft processing so we must 51 // call removeInitializedReplicaRaftMuLocked directly to avoid deadlocking 52 // on the right-hand replica's raftMu. 53 if err := s.removeInitializedReplicaRaftMuLocked(ctx, rightRepl, rightDesc.NextReplicaID, RemoveOptions{ 54 DestroyData: false, // the replica was destroyed when the merge commit applied 55 }); err != nil { 56 return errors.Errorf("cannot remove range: %s", err) 57 } 58 59 if leftRepl.leaseholderStats != nil { 60 leftRepl.leaseholderStats.resetRequestCounts() 61 } 62 if leftRepl.writeStats != nil { 63 // Note: this could be drastically improved by adding a replicaStats method 64 // that merges stats. Resetting stats is typically bad for the rebalancing 65 // logic that depends on them. 66 leftRepl.writeStats.resetRequestCounts() 67 } 68 69 // Clear the concurrency manager's lock and txn wait-queues to redirect the 70 // queued transactions to the left-hand replica, if necessary. 71 rightRepl.concMgr.OnRangeMerge() 72 73 leftLease, _ := leftRepl.GetLease() 74 rightLease, _ := rightRepl.GetLease() 75 if leftLease.OwnedBy(s.Ident.StoreID) && !rightLease.OwnedBy(s.Ident.StoreID) { 76 // We hold the lease for the LHS, but do not hold the lease for the RHS. 77 // That means we don't have up-to-date timestamp cache entries for the 78 // keyspace previously owned by the RHS. Bump the low water mark for the RHS 79 // keyspace to freezeStart, the time at which the RHS promised to stop 80 // serving traffic, as freezeStart is guaranteed to be greater than any 81 // entry in the RHS's timestamp cache. 82 // 83 // Note that we need to update our clock with freezeStart to preserve the 84 // invariant that our clock is always greater than or equal to any 85 // timestamps in the timestamp cache. For a full discussion, see the comment 86 // on TestStoreRangeMergeTimestampCacheCausality. 87 s.Clock().Update(freezeStart) 88 setTimestampCacheLowWaterMark(s.tsCache, &rightDesc, freezeStart) 89 } 90 91 // Update the subsuming range's descriptor. 92 leftRepl.setDescRaftMuLocked(ctx, &newLeftDesc) 93 return nil 94 }