github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/physicalplan/span_resolver.go (about)

     1  // Copyright 2016 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 physicalplan
    12  
    13  import (
    14  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/gossip"
    17  	"github.com/cockroachdb/cockroach/pkg/keys"
    18  	"github.com/cockroachdb/cockroach/pkg/kv"
    19  	"github.com/cockroachdb/cockroach/pkg/kv/kvclient/kvcoord"
    20  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/rpc"
    22  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/physicalplan/replicaoracle"
    24  	"github.com/cockroachdb/cockroach/pkg/util/log"
    25  )
    26  
    27  // SpanResolver resolves key spans to their respective ranges and lease holders.
    28  // Used for planning physical execution of distributed SQL queries.
    29  //
    30  // Sample usage for resolving a bunch of spans:
    31  //
    32  // func resolveSpans(
    33  //   ctx context.Context,
    34  //   it *execinfra.SpanResolverIterator,
    35  //   spans ...spanWithDir,
    36  // ) ([][]kv.ReplicaInfo, error) {
    37  //   lr := execinfra.NewSpanResolver(
    38  //     distSender, gossip, nodeDescriptor,
    39  //     execinfra.BinPackingLeaseHolderChoice)
    40  //   it := lr.NewSpanResolverIterator(nil)
    41  //   res := make([][]kv.ReplicaInfo, 0)
    42  //   for _, span := range spans {
    43  //     repls := make([]kv.ReplicaInfo, 0)
    44  //     for it.Seek(ctx, span.Span, span.dir); ; it.Next(ctx) {
    45  //       if !it.Valid() {
    46  //         return nil, it.Error()
    47  //       }
    48  //       repl, err := it.ReplicaInfo(ctx)
    49  //       if err != nil {
    50  //         return nil, err
    51  //       }
    52  //       repls = append(repls, repl)
    53  //       if !it.NeedAnother() {
    54  //         break
    55  //       }
    56  //     }
    57  //     res = append(res, repls)
    58  //   }
    59  //   return res, nil
    60  // }
    61  //
    62  //
    63  type SpanResolver interface {
    64  	// NewSpanResolverIterator creates a new SpanResolverIterator.
    65  	// Txn is used for testing and for determining if follower reads are possible.
    66  	NewSpanResolverIterator(txn *kv.Txn) SpanResolverIterator
    67  }
    68  
    69  // SpanResolverIterator is used to iterate over the ranges composing a key span.
    70  type SpanResolverIterator interface {
    71  	// Seek positions the iterator on the start of a span (span.Key or
    72  	// span.EndKey, depending on ScanDir). Note that span.EndKey is exclusive,
    73  	// regardless of scanDir.
    74  	//
    75  	// After calling this, ReplicaInfo() will return information about the range
    76  	// containing the start key of the span (or the end key, if the direction is
    77  	// Descending).
    78  	//
    79  	// NeedAnother() will return true until the iterator is positioned on or after
    80  	// the end of the span.  Possible errors encountered should be checked for
    81  	// with Valid().
    82  	//
    83  	// Seek can be called repeatedly on the same iterator. To make optimal uses of
    84  	// caches, Seek()s should be performed on spans sorted according to the
    85  	// scanDir (if Descending, then the span with the highest keys should be
    86  	// Seek()ed first).
    87  	//
    88  	// scanDir changes the direction in which Next() will advance the iterator.
    89  	Seek(ctx context.Context, span roachpb.Span, scanDir kvcoord.ScanDirection)
    90  
    91  	// NeedAnother returns true if the current range is not the last for the span
    92  	// that was last Seek()ed.
    93  	NeedAnother() bool
    94  
    95  	// Next advances the iterator to the next range. The next range contains the
    96  	// last range's end key (but it does not necessarily start there, because of
    97  	// asynchronous range splits and caching effects).
    98  	// Possible errors encountered should be checked for with Valid().
    99  	Next(ctx context.Context)
   100  
   101  	// Valid returns false if an error was encountered by the last Seek() or Next().
   102  	Valid() bool
   103  
   104  	// Error returns any error encountered by the last Seek() or Next().
   105  	Error() error
   106  
   107  	// Desc returns the current RangeDescriptor.
   108  	Desc() roachpb.RangeDescriptor
   109  
   110  	// ReplicaInfo returns information about the replica that has been picked for
   111  	// the current range.
   112  	// A RangeUnavailableError is returned if there's no information in gossip
   113  	// about any of the replicas.
   114  	ReplicaInfo(ctx context.Context) (roachpb.ReplicaDescriptor, error)
   115  }
   116  
   117  // spanResolver implements SpanResolver.
   118  type spanResolver struct {
   119  	st            *cluster.Settings
   120  	gossip        gossip.DeprecatedGossip
   121  	distSender    *kvcoord.DistSender
   122  	nodeDesc      roachpb.NodeDescriptor
   123  	oracleFactory replicaoracle.OracleFactory
   124  }
   125  
   126  var _ SpanResolver = &spanResolver{}
   127  
   128  // NewSpanResolver creates a new spanResolver.
   129  func NewSpanResolver(
   130  	st *cluster.Settings,
   131  	distSender *kvcoord.DistSender,
   132  	gw gossip.DeprecatedGossip,
   133  	nodeDesc roachpb.NodeDescriptor,
   134  	rpcCtx *rpc.Context,
   135  	policy replicaoracle.Policy,
   136  ) SpanResolver {
   137  	return &spanResolver{
   138  		st:       st,
   139  		nodeDesc: nodeDesc,
   140  		oracleFactory: replicaoracle.NewOracleFactory(policy, replicaoracle.Config{
   141  			Settings:         st,
   142  			Gossip:           gw.DeprecatedOracleGossip(48432),
   143  			NodeDesc:         nodeDesc,
   144  			RPCContext:       rpcCtx,
   145  			LeaseHolderCache: distSender.LeaseHolderCache(),
   146  		}),
   147  		distSender: distSender,
   148  		gossip:     gw,
   149  	}
   150  }
   151  
   152  // spanResolverIterator implements the SpanResolverIterator interface.
   153  type spanResolverIterator struct {
   154  	// it is a wrapper RangeIterator.
   155  	it *kvcoord.RangeIterator
   156  	// oracle is used to choose a lease holders for ranges when one isn't present
   157  	// in the cache.
   158  	oracle replicaoracle.Oracle
   159  
   160  	curSpan roachpb.RSpan
   161  	// dir is the direction set by the last Seek()
   162  	dir kvcoord.ScanDirection
   163  
   164  	queryState replicaoracle.QueryState
   165  
   166  	err error
   167  }
   168  
   169  var _ SpanResolverIterator = &spanResolverIterator{}
   170  
   171  // NewSpanResolverIterator creates a new SpanResolverIterator.
   172  func (sr *spanResolver) NewSpanResolverIterator(txn *kv.Txn) SpanResolverIterator {
   173  	return &spanResolverIterator{
   174  		it:         kvcoord.NewRangeIterator(sr.distSender),
   175  		oracle:     sr.oracleFactory.Oracle(txn),
   176  		queryState: replicaoracle.MakeQueryState(),
   177  	}
   178  }
   179  
   180  // Valid is part of the SpanResolverIterator interface.
   181  func (it *spanResolverIterator) Valid() bool {
   182  	return it.err == nil && it.it.Valid()
   183  }
   184  
   185  // Error is part of the SpanResolverIterator interface.
   186  func (it *spanResolverIterator) Error() error {
   187  	if it.err != nil {
   188  		return it.err
   189  	}
   190  	return it.it.Error()
   191  }
   192  
   193  // Seek is part of the SpanResolverIterator interface.
   194  func (it *spanResolverIterator) Seek(
   195  	ctx context.Context, span roachpb.Span, scanDir kvcoord.ScanDirection,
   196  ) {
   197  	var key, endKey roachpb.RKey
   198  	var err error
   199  	if key, err = keys.Addr(span.Key); err != nil {
   200  		it.err = err
   201  		return
   202  	}
   203  	if endKey, err = keys.Addr(span.EndKey); err != nil {
   204  		it.err = err
   205  		return
   206  	}
   207  	oldDir := it.dir
   208  	it.curSpan = roachpb.RSpan{
   209  		Key:    key,
   210  		EndKey: endKey,
   211  	}
   212  	it.dir = scanDir
   213  
   214  	var seekKey roachpb.RKey
   215  	if scanDir == kvcoord.Ascending {
   216  		seekKey = it.curSpan.Key
   217  	} else {
   218  		seekKey = it.curSpan.EndKey
   219  	}
   220  
   221  	// Check if the start of the span falls within the descriptor on which we're
   222  	// already positioned. If so, and if the direction also corresponds, there's
   223  	// no need to change the underlying iterator's state.
   224  	if it.dir == oldDir && it.it.Valid() {
   225  		reverse := (it.dir == kvcoord.Descending)
   226  		desc := it.it.Desc()
   227  		if (reverse && desc.ContainsKeyInverted(seekKey)) ||
   228  			(!reverse && desc.ContainsKey(seekKey)) {
   229  			if log.V(1) {
   230  				log.Infof(ctx, "not seeking (key=%s); existing descriptor %s", seekKey, desc)
   231  			}
   232  			return
   233  		}
   234  	}
   235  	if log.V(1) {
   236  		log.Infof(ctx, "seeking (key=%s)", seekKey)
   237  	}
   238  	it.it.Seek(ctx, seekKey, scanDir)
   239  }
   240  
   241  // Next is part of the SpanResolverIterator interface.
   242  func (it *spanResolverIterator) Next(ctx context.Context) {
   243  	if !it.Valid() {
   244  		panic(it.Error())
   245  	}
   246  	it.it.Next(ctx)
   247  }
   248  
   249  // NeedAnother is part of the SpanResolverIterator interface.
   250  func (it *spanResolverIterator) NeedAnother() bool {
   251  	return it.it.NeedAnother(it.curSpan)
   252  }
   253  
   254  // Desc is part of the SpanResolverIterator interface.
   255  func (it *spanResolverIterator) Desc() roachpb.RangeDescriptor {
   256  	return *it.it.Desc()
   257  }
   258  
   259  // ReplicaInfo is part of the SpanResolverIterator interface.
   260  func (it *spanResolverIterator) ReplicaInfo(
   261  	ctx context.Context,
   262  ) (roachpb.ReplicaDescriptor, error) {
   263  	if !it.Valid() {
   264  		panic(it.Error())
   265  	}
   266  
   267  	// If we've assigned the range before, return that assignment.
   268  	rngID := it.it.Desc().RangeID
   269  	if repl, ok := it.queryState.AssignedRanges[rngID]; ok {
   270  		return repl, nil
   271  	}
   272  
   273  	repl, err := it.oracle.ChoosePreferredReplica(
   274  		ctx, *it.it.Desc(), it.queryState)
   275  	if err != nil {
   276  		return roachpb.ReplicaDescriptor{}, err
   277  	}
   278  	it.queryState.RangesPerNode[repl.NodeID]++
   279  	it.queryState.AssignedRanges[rngID] = repl
   280  	return repl, nil
   281  }