// lookupReplica looks up replica by key [range]. Lookups are done // by consulting each store in turn via Store.LookupRange(key). // Returns RangeID and replica on success; RangeKeyMismatch error // if not found. // This is only for testing usage; performance doesn't matter. func (ls *Stores) lookupReplica(start, end roachpb.RKey) (rangeID roachpb.RangeID, replica *roachpb.ReplicaDescriptor, pErr *roachpb.Error) { ls.mu.RLock() defer ls.mu.RUnlock() var rng *Replica for _, store := range ls.storeMap { rng = store.LookupReplica(start, end) if rng == nil { if tmpRng := store.LookupReplica(start, nil); tmpRng != nil { log.Warningf(fmt.Sprintf("range not contained in one range: [%s,%s), but have [%s,%s)", start, end, tmpRng.Desc().StartKey, tmpRng.Desc().EndKey)) } continue } if replica == nil { rangeID = rng.RangeID replica = rng.GetReplica() continue } // Should never happen outside of tests. return 0, nil, roachpb.NewErrorf( "range %+v exists on additional store: %+v", rng, store) } if replica == nil { pErr = roachpb.NewError(roachpb.NewRangeKeyMismatchError(start.AsRawKey(), end.AsRawKey(), nil)) } return rangeID, replica, pErr }
// lookupReplica looks up replica by key [range]. Lookups are done // by consulting each store in turn via Store.LookupRange(key). // Returns RangeID and replica on success; RangeKeyMismatch error // if not found. // This is only for testing usage; performance doesn't matter. func (ls *Stores) lookupReplica(start, end roachpb.RKey) (rangeID roachpb.RangeID, replica *roachpb.ReplicaDescriptor, err error) { ls.mu.RLock() defer ls.mu.RUnlock() var rng *Replica var partialDesc *roachpb.RangeDescriptor for _, store := range ls.storeMap { rng = store.LookupReplica(start, end) if rng == nil { if tmpRng := store.LookupReplica(start, nil); tmpRng != nil { log.Warningf("range not contained in one range: [%s,%s), but have [%s,%s)", start, end, tmpRng.Desc().StartKey, tmpRng.Desc().EndKey) partialDesc = tmpRng.Desc() break } continue } if replica == nil { rangeID = rng.RangeID replica, err = rng.GetReplica() if err != nil { if _, ok := err.(*errReplicaNotInRange); !ok { return 0, nil, err } } continue } // Should never happen outside of tests. return 0, nil, util.Errorf( "range %+v exists on additional store: %+v", rng, store) } if replica == nil { err = roachpb.NewRangeKeyMismatchError(start.AsRawKey(), end.AsRawKey(), partialDesc) } return rangeID, replica, err }
// Send forwards the call to the single store. This is a poor man's // version of kv.TxnCoordSender, but it serves the purposes of // supporting tests in this package. Transactions are not supported. // Since kv/ depends on storage/, we can't get access to a // TxnCoordSender from here. // TODO(tschottdorf): {kv->storage}.LocalSender func (db *testSender) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { if et, ok := ba.GetArg(roachpb.EndTransaction); ok { return nil, roachpb.NewError(util.Errorf("%s method not supported", et.Method())) } // Lookup range and direct request. key, endKey := keys.Range(ba) rng := db.store.LookupReplica(key, endKey) if rng == nil { return nil, roachpb.NewError(roachpb.NewRangeKeyMismatchError(key, endKey, nil)) } ba.RangeID = rng.Desc().RangeID replica := rng.GetReplica() if replica == nil { return nil, roachpb.NewError(util.Errorf("own replica missing in range")) } ba.Replica = *replica br, pErr := db.store.Send(ctx, ba) if br != nil && br.Error != nil { panic(roachpb.ErrorUnexpectedlySet(db.store, br)) } if pErr != nil { return nil, pErr } return br, nil }
// 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 }
// 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) (rangeID roachpb.RangeID, repDesc roachpb.ReplicaDescriptor, err error) { ls.mu.RLock() defer ls.mu.RUnlock() var rng *Replica var partialDesc *roachpb.RangeDescriptor var repDescFound bool for _, store := range ls.storeMap { rng = store.LookupReplica(start, end) if rng == nil { if tmpRng := store.LookupReplica(start, nil); tmpRng != nil { partialDesc = tmpRng.Desc() log.Warningf(context.TODO(), "range not contained in one range: [%s,%s), but have [%s,%s)", start, end, partialDesc.StartKey, partialDesc.EndKey) break } continue } if !repDescFound { rangeID = rng.RangeID repDesc, err = rng.GetReplicaDescriptor() if err != nil { if _, ok := err.(*roachpb.RangeNotFoundError); !ok { return 0, roachpb.ReplicaDescriptor{}, err } } else { repDescFound = true } continue } // Should never happen outside of tests. return 0, roachpb.ReplicaDescriptor{}, errors.Errorf( "range %+v exists on additional store: %+v", rng, store, ) } if !repDescFound { err = roachpb.NewRangeKeyMismatchError(start.AsRawKey(), end.AsRawKey(), partialDesc) } return rangeID, repDesc, err }