github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/einsteindbrpc/einsteindbrpc.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package einsteindbrpc
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"sync/atomic"
    20  	"time"
    21  
    22  	"github.com/whtcorpsinc/ekvproto/pkg/debugpb"
    23  	"github.com/whtcorpsinc/ekvproto/pkg/einsteindbpb"
    24  	"github.com/whtcorpsinc/ekvproto/pkg/ekvrpcpb"
    25  	"github.com/whtcorpsinc/ekvproto/pkg/errorpb"
    26  	"github.com/whtcorpsinc/ekvproto/pkg/interlock"
    27  	"github.com/whtcorpsinc/ekvproto/pkg/spacetimepb"
    28  	"github.com/whtcorpsinc/errors"
    29  	"github.com/whtcorpsinc/milevadb/ekv"
    30  )
    31  
    32  // CmdType represents the concrete request type in Request or response type in Response.
    33  type CmdType uint16
    34  
    35  // CmdType values.
    36  const (
    37  	CmdGet CmdType = 1 + iota
    38  	CmdScan
    39  	CmdPrewrite
    40  	CmdCommit
    41  	CmdCleanup
    42  	CmdBatchGet
    43  	CmdBatchRollback
    44  	CmdScanLock
    45  	CmdResolveLock
    46  	CmdGC
    47  	CmdDeleteRange
    48  	CmdPessimisticLock
    49  	CmdPessimisticRollback
    50  	CmdTxnHeartBeat
    51  	CmdCheckTxnStatus
    52  	CmdCheckSecondaryLocks
    53  
    54  	CmdRawGet CmdType = 256 + iota
    55  	CmdRawBatchGet
    56  	CmdRawPut
    57  	CmdRawBatchPut
    58  	CmdRawDelete
    59  	CmdRawBatchDelete
    60  	CmdRawDeleteRange
    61  	CmdRawScan
    62  
    63  	CmdUnsafeDestroyRange
    64  
    65  	CmdRegisterLockObserver
    66  	CmdCheckLockObserver
    67  	CmdRemoveLockObserver
    68  	CmdPhysicalScanLock
    69  
    70  	CmdCop CmdType = 512 + iota
    71  	CmdCopStream
    72  	CmdBatchCop
    73  
    74  	CmdMvccGetByKey CmdType = 1024 + iota
    75  	CmdMvccGetByStartTs
    76  	CmdSplitRegion
    77  
    78  	CmdDebugGetRegionProperties CmdType = 2048 + iota
    79  
    80  	CmdEmpty CmdType = 3072 + iota
    81  )
    82  
    83  func (t CmdType) String() string {
    84  	switch t {
    85  	case CmdGet:
    86  		return "Get"
    87  	case CmdScan:
    88  		return "Scan"
    89  	case CmdPrewrite:
    90  		return "Prewrite"
    91  	case CmdPessimisticLock:
    92  		return "PessimisticLock"
    93  	case CmdPessimisticRollback:
    94  		return "PessimisticRollback"
    95  	case CmdCommit:
    96  		return "Commit"
    97  	case CmdCleanup:
    98  		return "Cleanup"
    99  	case CmdBatchGet:
   100  		return "BatchGet"
   101  	case CmdBatchRollback:
   102  		return "BatchRollback"
   103  	case CmdScanLock:
   104  		return "ScanLock"
   105  	case CmdResolveLock:
   106  		return "ResolveLock"
   107  	case CmdGC:
   108  		return "GC"
   109  	case CmdDeleteRange:
   110  		return "DeleteRange"
   111  	case CmdRawGet:
   112  		return "RawGet"
   113  	case CmdRawBatchGet:
   114  		return "RawBatchGet"
   115  	case CmdRawPut:
   116  		return "RawPut"
   117  	case CmdRawBatchPut:
   118  		return "RawBatchPut"
   119  	case CmdRawDelete:
   120  		return "RawDelete"
   121  	case CmdRawBatchDelete:
   122  		return "RawBatchDelete"
   123  	case CmdRawDeleteRange:
   124  		return "RawDeleteRange"
   125  	case CmdRawScan:
   126  		return "RawScan"
   127  	case CmdUnsafeDestroyRange:
   128  		return "UnsafeDestroyRange"
   129  	case CmdRegisterLockObserver:
   130  		return "RegisterLockObserver"
   131  	case CmdCheckLockObserver:
   132  		return "CheckLockObserver"
   133  	case CmdRemoveLockObserver:
   134  		return "RemoveLockObserver"
   135  	case CmdPhysicalScanLock:
   136  		return "PhysicalScanLock"
   137  	case CmdCop:
   138  		return "Causet"
   139  	case CmdCopStream:
   140  		return "CopStream"
   141  	case CmdBatchCop:
   142  		return "BatchCop"
   143  	case CmdMvccGetByKey:
   144  		return "MvccGetByKey"
   145  	case CmdMvccGetByStartTs:
   146  		return "MvccGetByStartTS"
   147  	case CmdSplitRegion:
   148  		return "SplitRegion"
   149  	case CmdCheckTxnStatus:
   150  		return "CheckTxnStatus"
   151  	case CmdCheckSecondaryLocks:
   152  		return "CheckSecondaryLocks"
   153  	case CmdDebugGetRegionProperties:
   154  		return "DebugGetRegionProperties"
   155  	case CmdTxnHeartBeat:
   156  		return "TxnHeartBeat"
   157  	}
   158  	return "Unknown"
   159  }
   160  
   161  // Request wraps all ekv/interlock requests.
   162  type Request struct {
   163  	Type CmdType
   164  	Req  interface{}
   165  	ekvrpcpb.Context
   166  	ReplicaReadSeed *uint32 // pointer to follower read seed in snapshot/interlock
   167  	StoreTp         ekv.StoreType
   168  }
   169  
   170  // NewRequest returns new ekv rpc request.
   171  func NewRequest(typ CmdType, pointer interface{}, ctxs ...ekvrpcpb.Context) *Request {
   172  	if len(ctxs) > 0 {
   173  		return &Request{
   174  			Type:    typ,
   175  			Req:     pointer,
   176  			Context: ctxs[0],
   177  		}
   178  	}
   179  	return &Request{
   180  		Type: typ,
   181  		Req:  pointer,
   182  	}
   183  }
   184  
   185  // NewReplicaReadRequest returns new ekv rpc request with replica read.
   186  func NewReplicaReadRequest(typ CmdType, pointer interface{}, replicaReadType ekv.ReplicaReadType, replicaReadSeed *uint32, ctxs ...ekvrpcpb.Context) *Request {
   187  	req := NewRequest(typ, pointer, ctxs...)
   188  	req.ReplicaRead = replicaReadType.IsFollowerRead()
   189  	req.ReplicaReadSeed = replicaReadSeed
   190  	return req
   191  }
   192  
   193  // Get returns GetRequest in request.
   194  func (req *Request) Get() *ekvrpcpb.GetRequest {
   195  	return req.Req.(*ekvrpcpb.GetRequest)
   196  }
   197  
   198  // Scan returns ScanRequest in request.
   199  func (req *Request) Scan() *ekvrpcpb.ScanRequest {
   200  	return req.Req.(*ekvrpcpb.ScanRequest)
   201  }
   202  
   203  // Prewrite returns PrewriteRequest in request.
   204  func (req *Request) Prewrite() *ekvrpcpb.PrewriteRequest {
   205  	return req.Req.(*ekvrpcpb.PrewriteRequest)
   206  }
   207  
   208  // Commit returns CommitRequest in request.
   209  func (req *Request) Commit() *ekvrpcpb.CommitRequest {
   210  	return req.Req.(*ekvrpcpb.CommitRequest)
   211  }
   212  
   213  // Cleanup returns CleanupRequest in request.
   214  func (req *Request) Cleanup() *ekvrpcpb.CleanupRequest {
   215  	return req.Req.(*ekvrpcpb.CleanupRequest)
   216  }
   217  
   218  // BatchGet returns BatchGetRequest in request.
   219  func (req *Request) BatchGet() *ekvrpcpb.BatchGetRequest {
   220  	return req.Req.(*ekvrpcpb.BatchGetRequest)
   221  }
   222  
   223  // BatchRollback returns BatchRollbackRequest in request.
   224  func (req *Request) BatchRollback() *ekvrpcpb.BatchRollbackRequest {
   225  	return req.Req.(*ekvrpcpb.BatchRollbackRequest)
   226  }
   227  
   228  // ScanLock returns ScanLockRequest in request.
   229  func (req *Request) ScanLock() *ekvrpcpb.ScanLockRequest {
   230  	return req.Req.(*ekvrpcpb.ScanLockRequest)
   231  }
   232  
   233  // ResolveLock returns ResolveLockRequest in request.
   234  func (req *Request) ResolveLock() *ekvrpcpb.ResolveLockRequest {
   235  	return req.Req.(*ekvrpcpb.ResolveLockRequest)
   236  }
   237  
   238  // GC returns GCRequest in request.
   239  func (req *Request) GC() *ekvrpcpb.GCRequest {
   240  	return req.Req.(*ekvrpcpb.GCRequest)
   241  }
   242  
   243  // DeleteRange returns DeleteRangeRequest in request.
   244  func (req *Request) DeleteRange() *ekvrpcpb.DeleteRangeRequest {
   245  	return req.Req.(*ekvrpcpb.DeleteRangeRequest)
   246  }
   247  
   248  // RawGet returns RawGetRequest in request.
   249  func (req *Request) RawGet() *ekvrpcpb.RawGetRequest {
   250  	return req.Req.(*ekvrpcpb.RawGetRequest)
   251  }
   252  
   253  // RawBatchGet returns RawBatchGetRequest in request.
   254  func (req *Request) RawBatchGet() *ekvrpcpb.RawBatchGetRequest {
   255  	return req.Req.(*ekvrpcpb.RawBatchGetRequest)
   256  }
   257  
   258  // RawPut returns RawPutRequest in request.
   259  func (req *Request) RawPut() *ekvrpcpb.RawPutRequest {
   260  	return req.Req.(*ekvrpcpb.RawPutRequest)
   261  }
   262  
   263  // RawBatchPut returns RawBatchPutRequest in request.
   264  func (req *Request) RawBatchPut() *ekvrpcpb.RawBatchPutRequest {
   265  	return req.Req.(*ekvrpcpb.RawBatchPutRequest)
   266  }
   267  
   268  // RawDelete returns PrewriteRequest in request.
   269  func (req *Request) RawDelete() *ekvrpcpb.RawDeleteRequest {
   270  	return req.Req.(*ekvrpcpb.RawDeleteRequest)
   271  }
   272  
   273  // RawBatchDelete returns RawBatchDeleteRequest in request.
   274  func (req *Request) RawBatchDelete() *ekvrpcpb.RawBatchDeleteRequest {
   275  	return req.Req.(*ekvrpcpb.RawBatchDeleteRequest)
   276  }
   277  
   278  // RawDeleteRange returns RawDeleteRangeRequest in request.
   279  func (req *Request) RawDeleteRange() *ekvrpcpb.RawDeleteRangeRequest {
   280  	return req.Req.(*ekvrpcpb.RawDeleteRangeRequest)
   281  }
   282  
   283  // RawScan returns RawScanRequest in request.
   284  func (req *Request) RawScan() *ekvrpcpb.RawScanRequest {
   285  	return req.Req.(*ekvrpcpb.RawScanRequest)
   286  }
   287  
   288  // UnsafeDestroyRange returns UnsafeDestroyRangeRequest in request.
   289  func (req *Request) UnsafeDestroyRange() *ekvrpcpb.UnsafeDestroyRangeRequest {
   290  	return req.Req.(*ekvrpcpb.UnsafeDestroyRangeRequest)
   291  }
   292  
   293  // RegisterLockObserver returns RegisterLockObserverRequest in request.
   294  func (req *Request) RegisterLockObserver() *ekvrpcpb.RegisterLockObserverRequest {
   295  	return req.Req.(*ekvrpcpb.RegisterLockObserverRequest)
   296  }
   297  
   298  // CheckLockObserver returns CheckLockObserverRequest in request.
   299  func (req *Request) CheckLockObserver() *ekvrpcpb.CheckLockObserverRequest {
   300  	return req.Req.(*ekvrpcpb.CheckLockObserverRequest)
   301  }
   302  
   303  // RemoveLockObserver returns RemoveLockObserverRequest in request.
   304  func (req *Request) RemoveLockObserver() *ekvrpcpb.RemoveLockObserverRequest {
   305  	return req.Req.(*ekvrpcpb.RemoveLockObserverRequest)
   306  }
   307  
   308  // PhysicalScanLock returns PhysicalScanLockRequest in request.
   309  func (req *Request) PhysicalScanLock() *ekvrpcpb.PhysicalScanLockRequest {
   310  	return req.Req.(*ekvrpcpb.PhysicalScanLockRequest)
   311  }
   312  
   313  // Causet returns interlock request in request.
   314  func (req *Request) Causet() *interlock.Request {
   315  	return req.Req.(*interlock.Request)
   316  }
   317  
   318  // BatchCop returns interlock request in request.
   319  func (req *Request) BatchCop() *interlock.BatchRequest {
   320  	return req.Req.(*interlock.BatchRequest)
   321  }
   322  
   323  // MvccGetByKey returns MvccGetByKeyRequest in request.
   324  func (req *Request) MvccGetByKey() *ekvrpcpb.MvccGetByKeyRequest {
   325  	return req.Req.(*ekvrpcpb.MvccGetByKeyRequest)
   326  }
   327  
   328  // MvccGetByStartTs returns MvccGetByStartTsRequest in request.
   329  func (req *Request) MvccGetByStartTs() *ekvrpcpb.MvccGetByStartTsRequest {
   330  	return req.Req.(*ekvrpcpb.MvccGetByStartTsRequest)
   331  }
   332  
   333  // SplitRegion returns SplitRegionRequest in request.
   334  func (req *Request) SplitRegion() *ekvrpcpb.SplitRegionRequest {
   335  	return req.Req.(*ekvrpcpb.SplitRegionRequest)
   336  }
   337  
   338  // PessimisticLock returns PessimisticLockRequest in request.
   339  func (req *Request) PessimisticLock() *ekvrpcpb.PessimisticLockRequest {
   340  	return req.Req.(*ekvrpcpb.PessimisticLockRequest)
   341  }
   342  
   343  // PessimisticRollback returns PessimisticRollbackRequest in request.
   344  func (req *Request) PessimisticRollback() *ekvrpcpb.PessimisticRollbackRequest {
   345  	return req.Req.(*ekvrpcpb.PessimisticRollbackRequest)
   346  }
   347  
   348  // DebugGetRegionProperties returns GetRegionPropertiesRequest in request.
   349  func (req *Request) DebugGetRegionProperties() *debugpb.GetRegionPropertiesRequest {
   350  	return req.Req.(*debugpb.GetRegionPropertiesRequest)
   351  }
   352  
   353  // Empty returns BatchCommandsEmptyRequest in request.
   354  func (req *Request) Empty() *einsteindbpb.BatchCommandsEmptyRequest {
   355  	return req.Req.(*einsteindbpb.BatchCommandsEmptyRequest)
   356  }
   357  
   358  // CheckTxnStatus returns CheckTxnStatusRequest in request.
   359  func (req *Request) CheckTxnStatus() *ekvrpcpb.CheckTxnStatusRequest {
   360  	return req.Req.(*ekvrpcpb.CheckTxnStatusRequest)
   361  }
   362  
   363  // CheckSecondaryLocks returns CheckSecondaryLocksRequest in request.
   364  func (req *Request) CheckSecondaryLocks() *ekvrpcpb.CheckSecondaryLocksRequest {
   365  	return req.Req.(*ekvrpcpb.CheckSecondaryLocksRequest)
   366  }
   367  
   368  // TxnHeartBeat returns TxnHeartBeatRequest in request.
   369  func (req *Request) TxnHeartBeat() *ekvrpcpb.TxnHeartBeatRequest {
   370  	return req.Req.(*ekvrpcpb.TxnHeartBeatRequest)
   371  }
   372  
   373  // ToBatchCommandsRequest converts the request to an entry in BatchCommands request.
   374  func (req *Request) ToBatchCommandsRequest() *einsteindbpb.BatchCommandsRequest_Request {
   375  	switch req.Type {
   376  	case CmdGet:
   377  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Get{Get: req.Get()}}
   378  	case CmdScan:
   379  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Scan{Scan: req.Scan()}}
   380  	case CmdPrewrite:
   381  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Prewrite{Prewrite: req.Prewrite()}}
   382  	case CmdCommit:
   383  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Commit{Commit: req.Commit()}}
   384  	case CmdCleanup:
   385  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Cleanup{Cleanup: req.Cleanup()}}
   386  	case CmdBatchGet:
   387  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_BatchGet{BatchGet: req.BatchGet()}}
   388  	case CmdBatchRollback:
   389  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_BatchRollback{BatchRollback: req.BatchRollback()}}
   390  	case CmdScanLock:
   391  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_ScanLock{ScanLock: req.ScanLock()}}
   392  	case CmdResolveLock:
   393  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_ResolveLock{ResolveLock: req.ResolveLock()}}
   394  	case CmdGC:
   395  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_GC{GC: req.GC()}}
   396  	case CmdDeleteRange:
   397  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_DeleteRange{DeleteRange: req.DeleteRange()}}
   398  	case CmdRawGet:
   399  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawGet{RawGet: req.RawGet()}}
   400  	case CmdRawBatchGet:
   401  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawBatchGet{RawBatchGet: req.RawBatchGet()}}
   402  	case CmdRawPut:
   403  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawPut{RawPut: req.RawPut()}}
   404  	case CmdRawBatchPut:
   405  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawBatchPut{RawBatchPut: req.RawBatchPut()}}
   406  	case CmdRawDelete:
   407  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawDelete{RawDelete: req.RawDelete()}}
   408  	case CmdRawBatchDelete:
   409  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawBatchDelete{RawBatchDelete: req.RawBatchDelete()}}
   410  	case CmdRawDeleteRange:
   411  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawDeleteRange{RawDeleteRange: req.RawDeleteRange()}}
   412  	case CmdRawScan:
   413  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_RawScan{RawScan: req.RawScan()}}
   414  	case CmdCop:
   415  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Coprocessor{Coprocessor: req.Causet()}}
   416  	case CmdPessimisticLock:
   417  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_PessimisticLock{PessimisticLock: req.PessimisticLock()}}
   418  	case CmdPessimisticRollback:
   419  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_PessimisticRollback{PessimisticRollback: req.PessimisticRollback()}}
   420  	case CmdEmpty:
   421  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_Empty{Empty: req.Empty()}}
   422  	case CmdCheckTxnStatus:
   423  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_CheckTxnStatus{CheckTxnStatus: req.CheckTxnStatus()}}
   424  	case CmdCheckSecondaryLocks:
   425  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_CheckSecondaryLocks{CheckSecondaryLocks: req.CheckSecondaryLocks()}}
   426  	case CmdTxnHeartBeat:
   427  		return &einsteindbpb.BatchCommandsRequest_Request{Cmd: &einsteindbpb.BatchCommandsRequest_Request_TxnHeartBeat{TxnHeartBeat: req.TxnHeartBeat()}}
   428  	}
   429  	return nil
   430  }
   431  
   432  // IsDebugReq check whether the req is debug req.
   433  func (req *Request) IsDebugReq() bool {
   434  	switch req.Type {
   435  	case CmdDebugGetRegionProperties:
   436  		return true
   437  	}
   438  	return false
   439  }
   440  
   441  // Response wraps all ekv/interlock responses.
   442  type Response struct {
   443  	Resp interface{}
   444  }
   445  
   446  // FromBatchCommandsResponse converts a BatchCommands response to Response.
   447  func FromBatchCommandsResponse(res *einsteindbpb.BatchCommandsResponse_Response) (*Response, error) {
   448  	if res.GetCmd() == nil {
   449  		return nil, errors.New("Unknown command response")
   450  	}
   451  	switch res := res.GetCmd().(type) {
   452  	case *einsteindbpb.BatchCommandsResponse_Response_Get:
   453  		return &Response{Resp: res.Get}, nil
   454  	case *einsteindbpb.BatchCommandsResponse_Response_Scan:
   455  		return &Response{Resp: res.Scan}, nil
   456  	case *einsteindbpb.BatchCommandsResponse_Response_Prewrite:
   457  		return &Response{Resp: res.Prewrite}, nil
   458  	case *einsteindbpb.BatchCommandsResponse_Response_Commit:
   459  		return &Response{Resp: res.Commit}, nil
   460  	case *einsteindbpb.BatchCommandsResponse_Response_Cleanup:
   461  		return &Response{Resp: res.Cleanup}, nil
   462  	case *einsteindbpb.BatchCommandsResponse_Response_BatchGet:
   463  		return &Response{Resp: res.BatchGet}, nil
   464  	case *einsteindbpb.BatchCommandsResponse_Response_BatchRollback:
   465  		return &Response{Resp: res.BatchRollback}, nil
   466  	case *einsteindbpb.BatchCommandsResponse_Response_ScanLock:
   467  		return &Response{Resp: res.ScanLock}, nil
   468  	case *einsteindbpb.BatchCommandsResponse_Response_ResolveLock:
   469  		return &Response{Resp: res.ResolveLock}, nil
   470  	case *einsteindbpb.BatchCommandsResponse_Response_GC:
   471  		return &Response{Resp: res.GC}, nil
   472  	case *einsteindbpb.BatchCommandsResponse_Response_DeleteRange:
   473  		return &Response{Resp: res.DeleteRange}, nil
   474  	case *einsteindbpb.BatchCommandsResponse_Response_RawGet:
   475  		return &Response{Resp: res.RawGet}, nil
   476  	case *einsteindbpb.BatchCommandsResponse_Response_RawBatchGet:
   477  		return &Response{Resp: res.RawBatchGet}, nil
   478  	case *einsteindbpb.BatchCommandsResponse_Response_RawPut:
   479  		return &Response{Resp: res.RawPut}, nil
   480  	case *einsteindbpb.BatchCommandsResponse_Response_RawBatchPut:
   481  		return &Response{Resp: res.RawBatchPut}, nil
   482  	case *einsteindbpb.BatchCommandsResponse_Response_RawDelete:
   483  		return &Response{Resp: res.RawDelete}, nil
   484  	case *einsteindbpb.BatchCommandsResponse_Response_RawBatchDelete:
   485  		return &Response{Resp: res.RawBatchDelete}, nil
   486  	case *einsteindbpb.BatchCommandsResponse_Response_RawDeleteRange:
   487  		return &Response{Resp: res.RawDeleteRange}, nil
   488  	case *einsteindbpb.BatchCommandsResponse_Response_RawScan:
   489  		return &Response{Resp: res.RawScan}, nil
   490  	case *einsteindbpb.BatchCommandsResponse_Response_Coprocessor:
   491  		return &Response{Resp: res.Coprocessor}, nil
   492  	case *einsteindbpb.BatchCommandsResponse_Response_PessimisticLock:
   493  		return &Response{Resp: res.PessimisticLock}, nil
   494  	case *einsteindbpb.BatchCommandsResponse_Response_PessimisticRollback:
   495  		return &Response{Resp: res.PessimisticRollback}, nil
   496  	case *einsteindbpb.BatchCommandsResponse_Response_Empty:
   497  		return &Response{Resp: res.Empty}, nil
   498  	case *einsteindbpb.BatchCommandsResponse_Response_TxnHeartBeat:
   499  		return &Response{Resp: res.TxnHeartBeat}, nil
   500  	case *einsteindbpb.BatchCommandsResponse_Response_CheckTxnStatus:
   501  		return &Response{Resp: res.CheckTxnStatus}, nil
   502  	case *einsteindbpb.BatchCommandsResponse_Response_CheckSecondaryLocks:
   503  		return &Response{Resp: res.CheckSecondaryLocks}, nil
   504  	}
   505  	panic("unreachable")
   506  }
   507  
   508  // CopStreamResponse combinates einsteindbpb.EinsteinDB_CoprocessorStreamClient and the first Recv() result together.
   509  // In streaming API, get grpc stream client may not involve any network packet, then region error have
   510  // to be handled in Recv() function. This struct facilitates the error handling.
   511  type CopStreamResponse struct {
   512  	einsteindbpb.EinsteinDB_CoprocessorStreamClient
   513  	*interlock.Response // The first result of Recv()
   514  	Timeout             time.Duration
   515  	Lease               // Shared by this object and a background goroutine.
   516  }
   517  
   518  // BatchCopStreamResponse comprises the BatchCoprocessorClient , the first result and timeout detector.
   519  type BatchCopStreamResponse struct {
   520  	einsteindbpb.EinsteinDB_BatchCoprocessorClient
   521  	*interlock.BatchResponse
   522  	Timeout time.Duration
   523  	Lease   // Shared by this object and a background goroutine.
   524  }
   525  
   526  // SetContext set the Context field for the given req to the specified ctx.
   527  func SetContext(req *Request, region *spacetimepb.Region, peer *spacetimepb.Peer) error {
   528  	ctx := &req.Context
   529  	if region != nil {
   530  		ctx.RegionId = region.Id
   531  		ctx.RegionEpoch = region.RegionEpoch
   532  	}
   533  	ctx.Peer = peer
   534  
   535  	switch req.Type {
   536  	case CmdGet:
   537  		req.Get().Context = ctx
   538  	case CmdScan:
   539  		req.Scan().Context = ctx
   540  	case CmdPrewrite:
   541  		req.Prewrite().Context = ctx
   542  	case CmdPessimisticLock:
   543  		req.PessimisticLock().Context = ctx
   544  	case CmdPessimisticRollback:
   545  		req.PessimisticRollback().Context = ctx
   546  	case CmdCommit:
   547  		req.Commit().Context = ctx
   548  	case CmdCleanup:
   549  		req.Cleanup().Context = ctx
   550  	case CmdBatchGet:
   551  		req.BatchGet().Context = ctx
   552  	case CmdBatchRollback:
   553  		req.BatchRollback().Context = ctx
   554  	case CmdScanLock:
   555  		req.ScanLock().Context = ctx
   556  	case CmdResolveLock:
   557  		req.ResolveLock().Context = ctx
   558  	case CmdGC:
   559  		req.GC().Context = ctx
   560  	case CmdDeleteRange:
   561  		req.DeleteRange().Context = ctx
   562  	case CmdRawGet:
   563  		req.RawGet().Context = ctx
   564  	case CmdRawBatchGet:
   565  		req.RawBatchGet().Context = ctx
   566  	case CmdRawPut:
   567  		req.RawPut().Context = ctx
   568  	case CmdRawBatchPut:
   569  		req.RawBatchPut().Context = ctx
   570  	case CmdRawDelete:
   571  		req.RawDelete().Context = ctx
   572  	case CmdRawBatchDelete:
   573  		req.RawBatchDelete().Context = ctx
   574  	case CmdRawDeleteRange:
   575  		req.RawDeleteRange().Context = ctx
   576  	case CmdRawScan:
   577  		req.RawScan().Context = ctx
   578  	case CmdUnsafeDestroyRange:
   579  		req.UnsafeDestroyRange().Context = ctx
   580  	case CmdRegisterLockObserver:
   581  		req.RegisterLockObserver().Context = ctx
   582  	case CmdCheckLockObserver:
   583  		req.CheckLockObserver().Context = ctx
   584  	case CmdRemoveLockObserver:
   585  		req.RemoveLockObserver().Context = ctx
   586  	case CmdPhysicalScanLock:
   587  		req.PhysicalScanLock().Context = ctx
   588  	case CmdCop:
   589  		req.Causet().Context = ctx
   590  	case CmdCopStream:
   591  		req.Causet().Context = ctx
   592  	case CmdBatchCop:
   593  		req.BatchCop().Context = ctx
   594  	case CmdMvccGetByKey:
   595  		req.MvccGetByKey().Context = ctx
   596  	case CmdMvccGetByStartTs:
   597  		req.MvccGetByStartTs().Context = ctx
   598  	case CmdSplitRegion:
   599  		req.SplitRegion().Context = ctx
   600  	case CmdEmpty:
   601  		req.SplitRegion().Context = ctx
   602  	case CmdTxnHeartBeat:
   603  		req.TxnHeartBeat().Context = ctx
   604  	case CmdCheckTxnStatus:
   605  		req.CheckTxnStatus().Context = ctx
   606  	case CmdCheckSecondaryLocks:
   607  		req.CheckSecondaryLocks().Context = ctx
   608  	default:
   609  		return fmt.Errorf("invalid request type %v", req.Type)
   610  	}
   611  	return nil
   612  }
   613  
   614  // GenRegionErrorResp returns corresponding Response with specified RegionError
   615  // according to the given req.
   616  func GenRegionErrorResp(req *Request, e *errorpb.Error) (*Response, error) {
   617  	var p interface{}
   618  	resp := &Response{}
   619  	switch req.Type {
   620  	case CmdGet:
   621  		p = &ekvrpcpb.GetResponse{
   622  			RegionError: e,
   623  		}
   624  	case CmdScan:
   625  		p = &ekvrpcpb.ScanResponse{
   626  			RegionError: e,
   627  		}
   628  	case CmdPrewrite:
   629  		p = &ekvrpcpb.PrewriteResponse{
   630  			RegionError: e,
   631  		}
   632  	case CmdPessimisticLock:
   633  		p = &ekvrpcpb.PessimisticLockResponse{
   634  			RegionError: e,
   635  		}
   636  	case CmdPessimisticRollback:
   637  		p = &ekvrpcpb.PessimisticRollbackResponse{
   638  			RegionError: e,
   639  		}
   640  	case CmdCommit:
   641  		p = &ekvrpcpb.CommitResponse{
   642  			RegionError: e,
   643  		}
   644  	case CmdCleanup:
   645  		p = &ekvrpcpb.CleanupResponse{
   646  			RegionError: e,
   647  		}
   648  	case CmdBatchGet:
   649  		p = &ekvrpcpb.BatchGetResponse{
   650  			RegionError: e,
   651  		}
   652  	case CmdBatchRollback:
   653  		p = &ekvrpcpb.BatchRollbackResponse{
   654  			RegionError: e,
   655  		}
   656  	case CmdScanLock:
   657  		p = &ekvrpcpb.ScanLockResponse{
   658  			RegionError: e,
   659  		}
   660  	case CmdResolveLock:
   661  		p = &ekvrpcpb.ResolveLockResponse{
   662  			RegionError: e,
   663  		}
   664  	case CmdGC:
   665  		p = &ekvrpcpb.GCResponse{
   666  			RegionError: e,
   667  		}
   668  	case CmdDeleteRange:
   669  		p = &ekvrpcpb.DeleteRangeResponse{
   670  			RegionError: e,
   671  		}
   672  	case CmdRawGet:
   673  		p = &ekvrpcpb.RawGetResponse{
   674  			RegionError: e,
   675  		}
   676  	case CmdRawBatchGet:
   677  		p = &ekvrpcpb.RawBatchGetResponse{
   678  			RegionError: e,
   679  		}
   680  	case CmdRawPut:
   681  		p = &ekvrpcpb.RawPutResponse{
   682  			RegionError: e,
   683  		}
   684  	case CmdRawBatchPut:
   685  		p = &ekvrpcpb.RawBatchPutResponse{
   686  			RegionError: e,
   687  		}
   688  	case CmdRawDelete:
   689  		p = &ekvrpcpb.RawDeleteResponse{
   690  			RegionError: e,
   691  		}
   692  	case CmdRawBatchDelete:
   693  		p = &ekvrpcpb.RawBatchDeleteResponse{
   694  			RegionError: e,
   695  		}
   696  	case CmdRawDeleteRange:
   697  		p = &ekvrpcpb.RawDeleteRangeResponse{
   698  			RegionError: e,
   699  		}
   700  	case CmdRawScan:
   701  		p = &ekvrpcpb.RawScanResponse{
   702  			RegionError: e,
   703  		}
   704  	case CmdUnsafeDestroyRange:
   705  		p = &ekvrpcpb.UnsafeDestroyRangeResponse{
   706  			RegionError: e,
   707  		}
   708  	case CmdCop:
   709  		p = &interlock.Response{
   710  			RegionError: e,
   711  		}
   712  	case CmdCopStream:
   713  		p = &CopStreamResponse{
   714  			Response: &interlock.Response{
   715  				RegionError: e,
   716  			},
   717  		}
   718  	case CmdMvccGetByKey:
   719  		p = &ekvrpcpb.MvccGetByKeyResponse{
   720  			RegionError: e,
   721  		}
   722  	case CmdMvccGetByStartTs:
   723  		p = &ekvrpcpb.MvccGetByStartTsResponse{
   724  			RegionError: e,
   725  		}
   726  	case CmdSplitRegion:
   727  		p = &ekvrpcpb.SplitRegionResponse{
   728  			RegionError: e,
   729  		}
   730  	case CmdEmpty:
   731  	case CmdTxnHeartBeat:
   732  		p = &ekvrpcpb.TxnHeartBeatResponse{
   733  			RegionError: e,
   734  		}
   735  	case CmdCheckTxnStatus:
   736  		p = &ekvrpcpb.CheckTxnStatusResponse{
   737  			RegionError: e,
   738  		}
   739  	case CmdCheckSecondaryLocks:
   740  		p = &ekvrpcpb.CheckSecondaryLocksResponse{
   741  			RegionError: e,
   742  		}
   743  	default:
   744  		return nil, fmt.Errorf("invalid request type %v", req.Type)
   745  	}
   746  	resp.Resp = p
   747  	return resp, nil
   748  }
   749  
   750  type getRegionError interface {
   751  	GetRegionError() *errorpb.Error
   752  }
   753  
   754  // GetRegionError returns the RegionError of the underlying concrete response.
   755  func (resp *Response) GetRegionError() (*errorpb.Error, error) {
   756  	if resp.Resp == nil {
   757  		return nil, nil
   758  	}
   759  	err, ok := resp.Resp.(getRegionError)
   760  	if !ok {
   761  		if _, isEmpty := resp.Resp.(*einsteindbpb.BatchCommandsEmptyResponse); isEmpty {
   762  			return nil, nil
   763  		}
   764  		return nil, fmt.Errorf("invalid response type %v", resp)
   765  	}
   766  	return err.GetRegionError(), nil
   767  }
   768  
   769  // CallRPC launches a rpc call.
   770  // ch is needed to implement timeout for interlock streaing, the stream object's
   771  // cancel function will be sent to the channel, together with a lease checked by a background goroutine.
   772  func CallRPC(ctx context.Context, client einsteindbpb.EinsteinDBClient, req *Request) (*Response, error) {
   773  	resp := &Response{}
   774  	var err error
   775  	switch req.Type {
   776  	case CmdGet:
   777  		resp.Resp, err = client.EkvGet(ctx, req.Get())
   778  	case CmdScan:
   779  		resp.Resp, err = client.EkvScan(ctx, req.Scan())
   780  	case CmdPrewrite:
   781  		resp.Resp, err = client.EkvPrewrite(ctx, req.Prewrite())
   782  	case CmdPessimisticLock:
   783  		resp.Resp, err = client.EkvPessimisticLock(ctx, req.PessimisticLock())
   784  	case CmdPessimisticRollback:
   785  		resp.Resp, err = client.KVPessimisticRollback(ctx, req.PessimisticRollback())
   786  	case CmdCommit:
   787  		resp.Resp, err = client.EkvCommit(ctx, req.Commit())
   788  	case CmdCleanup:
   789  		resp.Resp, err = client.EkvCleanup(ctx, req.Cleanup())
   790  	case CmdBatchGet:
   791  		resp.Resp, err = client.EkvBatchGet(ctx, req.BatchGet())
   792  	case CmdBatchRollback:
   793  		resp.Resp, err = client.EkvBatchRollback(ctx, req.BatchRollback())
   794  	case CmdScanLock:
   795  		resp.Resp, err = client.EkvScanLock(ctx, req.ScanLock())
   796  	case CmdResolveLock:
   797  		resp.Resp, err = client.EkvResolveLock(ctx, req.ResolveLock())
   798  	case CmdGC:
   799  		resp.Resp, err = client.EkvGC(ctx, req.GC())
   800  	case CmdDeleteRange:
   801  		resp.Resp, err = client.EkvDeleteRange(ctx, req.DeleteRange())
   802  	case CmdRawGet:
   803  		resp.Resp, err = client.RawGet(ctx, req.RawGet())
   804  	case CmdRawBatchGet:
   805  		resp.Resp, err = client.RawBatchGet(ctx, req.RawBatchGet())
   806  	case CmdRawPut:
   807  		resp.Resp, err = client.RawPut(ctx, req.RawPut())
   808  	case CmdRawBatchPut:
   809  		resp.Resp, err = client.RawBatchPut(ctx, req.RawBatchPut())
   810  	case CmdRawDelete:
   811  		resp.Resp, err = client.RawDelete(ctx, req.RawDelete())
   812  	case CmdRawBatchDelete:
   813  		resp.Resp, err = client.RawBatchDelete(ctx, req.RawBatchDelete())
   814  	case CmdRawDeleteRange:
   815  		resp.Resp, err = client.RawDeleteRange(ctx, req.RawDeleteRange())
   816  	case CmdRawScan:
   817  		resp.Resp, err = client.RawScan(ctx, req.RawScan())
   818  	case CmdUnsafeDestroyRange:
   819  		resp.Resp, err = client.UnsafeDestroyRange(ctx, req.UnsafeDestroyRange())
   820  	case CmdRegisterLockObserver:
   821  		resp.Resp, err = client.RegisterLockObserver(ctx, req.RegisterLockObserver())
   822  	case CmdCheckLockObserver:
   823  		resp.Resp, err = client.CheckLockObserver(ctx, req.CheckLockObserver())
   824  	case CmdRemoveLockObserver:
   825  		resp.Resp, err = client.RemoveLockObserver(ctx, req.RemoveLockObserver())
   826  	case CmdPhysicalScanLock:
   827  		resp.Resp, err = client.PhysicalScanLock(ctx, req.PhysicalScanLock())
   828  	case CmdCop:
   829  		resp.Resp, err = client.Coprocessor(ctx, req.Causet())
   830  	case CmdCopStream:
   831  		var streamClient einsteindbpb.EinsteinDB_CoprocessorStreamClient
   832  		streamClient, err = client.CoprocessorStream(ctx, req.Causet())
   833  		resp.Resp = &CopStreamResponse{
   834  			EinsteinDB_CoprocessorStreamClient: streamClient,
   835  		}
   836  	case CmdBatchCop:
   837  		var streamClient einsteindbpb.EinsteinDB_BatchCoprocessorClient
   838  		streamClient, err = client.BatchCoprocessor(ctx, req.BatchCop())
   839  		resp.Resp = &BatchCopStreamResponse{
   840  			EinsteinDB_BatchCoprocessorClient: streamClient,
   841  		}
   842  	case CmdMvccGetByKey:
   843  		resp.Resp, err = client.MvccGetByKey(ctx, req.MvccGetByKey())
   844  	case CmdMvccGetByStartTs:
   845  		resp.Resp, err = client.MvccGetByStartTs(ctx, req.MvccGetByStartTs())
   846  	case CmdSplitRegion:
   847  		resp.Resp, err = client.SplitRegion(ctx, req.SplitRegion())
   848  	case CmdEmpty:
   849  		resp.Resp, err = &einsteindbpb.BatchCommandsEmptyResponse{}, nil
   850  	case CmdCheckTxnStatus:
   851  		resp.Resp, err = client.EkvCheckTxnStatus(ctx, req.CheckTxnStatus())
   852  	case CmdCheckSecondaryLocks:
   853  		resp.Resp, err = client.EkvCheckSecondaryLocks(ctx, req.CheckSecondaryLocks())
   854  	case CmdTxnHeartBeat:
   855  		resp.Resp, err = client.EkvTxnHeartBeat(ctx, req.TxnHeartBeat())
   856  	default:
   857  		return nil, errors.Errorf("invalid request type: %v", req.Type)
   858  	}
   859  	if err != nil {
   860  		return nil, errors.Trace(err)
   861  	}
   862  	return resp, nil
   863  }
   864  
   865  // CallDebugRPC launches a debug rpc call.
   866  func CallDebugRPC(ctx context.Context, client debugpb.DebugClient, req *Request) (*Response, error) {
   867  	resp := &Response{}
   868  	var err error
   869  	switch req.Type {
   870  	case CmdDebugGetRegionProperties:
   871  		resp.Resp, err = client.GetRegionProperties(ctx, req.DebugGetRegionProperties())
   872  	default:
   873  		return nil, errors.Errorf("invalid request type: %v", req.Type)
   874  	}
   875  	return resp, err
   876  }
   877  
   878  // Lease is used to implement grpc stream timeout.
   879  type Lease struct {
   880  	Cancel   context.CancelFunc
   881  	deadline int64 // A time.UnixNano value, if time.Now().UnixNano() > deadline, cancel() would be called.
   882  }
   883  
   884  // Recv overrides the stream client Recv() function.
   885  func (resp *CopStreamResponse) Recv() (*interlock.Response, error) {
   886  	deadline := time.Now().Add(resp.Timeout).UnixNano()
   887  	atomic.StoreInt64(&resp.Lease.deadline, deadline)
   888  
   889  	ret, err := resp.EinsteinDB_CoprocessorStreamClient.Recv()
   890  
   891  	atomic.StoreInt64(&resp.Lease.deadline, 0) // Stop the lease check.
   892  	return ret, errors.Trace(err)
   893  }
   894  
   895  // Close closes the CopStreamResponse object.
   896  func (resp *CopStreamResponse) Close() {
   897  	atomic.StoreInt64(&resp.Lease.deadline, 1)
   898  	// We also call cancel here because CheckStreamTimeoutLoop
   899  	// is not guaranteed to cancel all items when it exits.
   900  	if resp.Lease.Cancel != nil {
   901  		resp.Lease.Cancel()
   902  	}
   903  }
   904  
   905  // Recv overrides the stream client Recv() function.
   906  func (resp *BatchCopStreamResponse) Recv() (*interlock.BatchResponse, error) {
   907  	deadline := time.Now().Add(resp.Timeout).UnixNano()
   908  	atomic.StoreInt64(&resp.Lease.deadline, deadline)
   909  
   910  	ret, err := resp.EinsteinDB_BatchCoprocessorClient.Recv()
   911  
   912  	atomic.StoreInt64(&resp.Lease.deadline, 0) // Stop the lease check.
   913  	return ret, errors.Trace(err)
   914  }
   915  
   916  // Close closes the CopStreamResponse object.
   917  func (resp *BatchCopStreamResponse) Close() {
   918  	atomic.StoreInt64(&resp.Lease.deadline, 1)
   919  	// We also call cancel here because CheckStreamTimeoutLoop
   920  	// is not guaranteed to cancel all items when it exits.
   921  	if resp.Lease.Cancel != nil {
   922  		resp.Lease.Cancel()
   923  	}
   924  }
   925  
   926  // CheckStreamTimeoutLoop runs periodically to check is there any stream request timeouted.
   927  // Lease is an object to track stream requests, call this function with "go CheckStreamTimeoutLoop()"
   928  // It is not guaranteed to call every Lease.Cancel() putting into channel when exits.
   929  // If grpc-go supports SetDeadline(https://github.com/grpc/grpc-go/issues/2917), we can stop using this method.
   930  func CheckStreamTimeoutLoop(ch <-chan *Lease, done <-chan struct{}) {
   931  	ticker := time.NewTicker(200 * time.Millisecond)
   932  	defer ticker.Stop()
   933  	array := make([]*Lease, 0, 1024)
   934  
   935  	for {
   936  		select {
   937  		case <-done:
   938  		drainLoop:
   939  			// Try my best cleaning the channel to make SendRequest which is blocking by it continues.
   940  			for {
   941  				select {
   942  				case <-ch:
   943  				default:
   944  					break drainLoop
   945  				}
   946  			}
   947  			return
   948  		case item := <-ch:
   949  			array = append(array, item)
   950  		case now := <-ticker.C:
   951  			array = keepOnlyActive(array, now.UnixNano())
   952  		}
   953  	}
   954  }
   955  
   956  // keepOnlyActive removes completed items, call cancel function for timeout items.
   957  func keepOnlyActive(array []*Lease, now int64) []*Lease {
   958  	idx := 0
   959  	for i := 0; i < len(array); i++ {
   960  		item := array[i]
   961  		deadline := atomic.LoadInt64(&item.deadline)
   962  		if deadline == 0 || deadline > now {
   963  			array[idx] = array[i]
   964  			idx++
   965  		} else {
   966  			item.Cancel()
   967  		}
   968  	}
   969  	return array[:idx]
   970  }