Esempio n. 1
0
// 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
}
Esempio n. 2
0
// 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())
}