// LookupReplica looks up replica by key [range]. Lookups are done // by consulting each store in turn via Store.LookupReplica(key). // Returns RangeID and replica on success; RangeKeyMismatch error // if not found. // If end is nil, a replica containing start is looked up. // This is only for testing usage; performance doesn't matter. func (ls *Stores) LookupReplica( start, end roachpb.RKey, ) (roachpb.RangeID, roachpb.ReplicaDescriptor, error) { ls.mu.RLock() defer ls.mu.RUnlock() var rangeID roachpb.RangeID var repDesc roachpb.ReplicaDescriptor var repDescFound bool for _, store := range ls.storeMap { replica := store.LookupReplica(start, nil) if replica == nil { continue } // Verify that the descriptor contains the entire range. if desc := replica.Desc(); !desc.ContainsKeyRange(start, end) { log.Warningf(context.TODO(), "range not contained in one range: [%s,%s), but have [%s,%s)", start, end, desc.StartKey, desc.EndKey) err := roachpb.NewRangeKeyMismatchError(start.AsRawKey(), end.AsRawKey(), desc) return 0, roachpb.ReplicaDescriptor{}, err } rangeID = replica.RangeID var err error repDesc, err = replica.GetReplicaDescriptor() if err != nil { if _, ok := err.(*roachpb.RangeNotFoundError); ok { // We are not holding a lock across this block; the replica could have // been removed from the range (via down-replication) between the // LookupReplica and the GetReplicaDescriptor calls. In this case just // ignore this replica. continue } return 0, roachpb.ReplicaDescriptor{}, err } if repDescFound { // We already found the range; this should never happen outside of tests. err := errors.Errorf("range %+v exists on additional store: %+v", replica, store) return 0, roachpb.ReplicaDescriptor{}, err } repDescFound = true } if !repDescFound { return 0, roachpb.ReplicaDescriptor{}, roachpb.NewRangeNotFoundError(0) } return rangeID, repDesc, nil }
// requestLeaseLocked executes a request to obtain or extend a lease // asynchronously and returns a promise for the result. If there's already a // request in progress, we join in waiting the results of that request. Unless // an error is returned, the obtained lease will be valid for a time interval // containing the requested timestamp. func (r *Replica) requestLeaseLocked(timestamp hlc.Timestamp) <-chan *roachpb.Error { // Propose a Raft command to get a lease for this replica. desc := r.mu.state.Desc repDesc, ok := desc.GetReplicaDescriptor(r.store.StoreID()) if !ok { llChan := make(chan *roachpb.Error, 1) llChan <- roachpb.NewError(roachpb.NewRangeNotFoundError(r.RangeID)) return llChan } if r.store.IsDrainingLeadership() { // We've retired from active duty. llChan := make(chan *roachpb.Error, 1) llChan <- roachpb.NewError(r.newNotLeaderError(nil, r.store.StoreID(), r.mu.state.Desc)) return llChan } return r.mu.pendingLeaseRequest.InitOrJoinRequest( r, repDesc, timestamp, desc.StartKey.AsRawKey()) }