github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/batcheval/cmd_scan.go (about)

     1  // Copyright 2014 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 batcheval
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/batcheval/result"
    18  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/concurrency/lock"
    19  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    20  	"github.com/cockroachdb/cockroach/pkg/storage"
    21  )
    22  
    23  func init() {
    24  	RegisterReadOnlyCommand(roachpb.Scan, DefaultDeclareIsolatedKeys, Scan)
    25  }
    26  
    27  // Scan scans the key range specified by start key through end key
    28  // in ascending order up to some maximum number of results. maxKeys
    29  // stores the number of scan results remaining for this batch
    30  // (MaxInt64 for no limit).
    31  func Scan(
    32  	ctx context.Context, reader storage.Reader, cArgs CommandArgs, resp roachpb.Response,
    33  ) (result.Result, error) {
    34  	args := cArgs.Args.(*roachpb.ScanRequest)
    35  	h := cArgs.Header
    36  	reply := resp.(*roachpb.ScanResponse)
    37  
    38  	var res result.Result
    39  	var scanRes storage.MVCCScanResult
    40  	var err error
    41  
    42  	opts := storage.MVCCScanOptions{
    43  		Inconsistent:     h.ReadConsistency != roachpb.CONSISTENT,
    44  		Txn:              h.Txn,
    45  		MaxKeys:          h.MaxSpanRequestKeys,
    46  		TargetBytes:      h.TargetBytes,
    47  		FailOnMoreRecent: args.KeyLocking != lock.None,
    48  		Reverse:          false,
    49  	}
    50  
    51  	switch args.ScanFormat {
    52  	case roachpb.BATCH_RESPONSE:
    53  		scanRes, err = storage.MVCCScanToBytes(
    54  			ctx, reader, args.Key, args.EndKey, h.Timestamp, opts)
    55  		if err != nil {
    56  			return result.Result{}, err
    57  		}
    58  		reply.BatchResponses = scanRes.KVData
    59  	case roachpb.KEY_VALUES:
    60  		scanRes, err = storage.MVCCScan(
    61  			ctx, reader, args.Key, args.EndKey, h.Timestamp, opts)
    62  		if err != nil {
    63  			return result.Result{}, err
    64  		}
    65  		reply.Rows = scanRes.KVs
    66  	default:
    67  		panic(fmt.Sprintf("Unknown scanFormat %d", args.ScanFormat))
    68  	}
    69  
    70  	reply.NumKeys = scanRes.NumKeys
    71  	reply.NumBytes = scanRes.NumBytes
    72  
    73  	if scanRes.ResumeSpan != nil {
    74  		reply.ResumeSpan = scanRes.ResumeSpan
    75  		reply.ResumeReason = roachpb.RESUME_KEY_LIMIT
    76  	}
    77  
    78  	if h.ReadConsistency == roachpb.READ_UNCOMMITTED {
    79  		// NOTE: MVCCScan doesn't use a Prefix iterator, so we don't want to use
    80  		// one in CollectIntentRows either so that we're guaranteed to use the
    81  		// same cached iterator and observe a consistent snapshot of the engine.
    82  		const usePrefixIter = false
    83  		reply.IntentRows, err = CollectIntentRows(ctx, reader, usePrefixIter, scanRes.Intents)
    84  		if err != nil {
    85  			return result.Result{}, err
    86  		}
    87  	}
    88  
    89  	if args.KeyLocking != lock.None && h.Txn != nil {
    90  		err = acquireUnreplicatedLocksOnKeys(&res, h.Txn, args.ScanFormat, &scanRes)
    91  		if err != nil {
    92  			return result.Result{}, err
    93  		}
    94  	}
    95  	res.Local.EncounteredIntents = scanRes.Intents
    96  	return res, nil
    97  }