github.com/KinWaiYuen/client-go/v2@v2.5.4/tikvrpc/tikvrpc.go (about) 1 // Copyright 2021 TiKV Authors 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/tikvrpc/tikvrpc.go 19 // 20 21 // Copyright 2017 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package tikvrpc 36 37 import ( 38 "context" 39 "fmt" 40 "sync/atomic" 41 "time" 42 43 "github.com/KinWaiYuen/client-go/v2/kv" 44 "github.com/KinWaiYuen/client-go/v2/oracle" 45 "github.com/pingcap/errors" 46 "github.com/pingcap/kvproto/pkg/coprocessor" 47 "github.com/pingcap/kvproto/pkg/debugpb" 48 "github.com/pingcap/kvproto/pkg/errorpb" 49 "github.com/pingcap/kvproto/pkg/kvrpcpb" 50 "github.com/pingcap/kvproto/pkg/metapb" 51 "github.com/pingcap/kvproto/pkg/mpp" 52 "github.com/pingcap/kvproto/pkg/tikvpb" 53 ) 54 55 // CmdType represents the concrete request type in Request or response type in Response. 56 type CmdType uint16 57 58 // CmdType values. 59 const ( 60 CmdGet CmdType = 1 + iota 61 CmdScan 62 CmdPrewrite 63 CmdCommit 64 CmdCleanup 65 CmdBatchGet 66 CmdBatchRollback 67 CmdScanLock 68 CmdResolveLock 69 CmdGC 70 CmdDeleteRange 71 CmdPessimisticLock 72 CmdPessimisticRollback 73 CmdTxnHeartBeat 74 CmdCheckTxnStatus 75 CmdCheckSecondaryLocks 76 77 CmdRawGet CmdType = 256 + iota 78 CmdRawBatchGet 79 CmdRawPut 80 CmdRawBatchPut 81 CmdRawDelete 82 CmdRawBatchDelete 83 CmdRawDeleteRange 84 CmdRawScan 85 CmdGetKeyTTL 86 CmdRawCompareAndSwap 87 88 CmdUnsafeDestroyRange 89 90 CmdRegisterLockObserver 91 CmdCheckLockObserver 92 CmdRemoveLockObserver 93 CmdPhysicalScanLock 94 95 CmdStoreSafeTS 96 CmdLockWaitInfo 97 98 CmdCop CmdType = 512 + iota 99 CmdCopStream 100 CmdBatchCop 101 CmdMPPTask 102 CmdMPPConn 103 CmdMPPCancel 104 CmdMPPAlive 105 106 CmdMvccGetByKey CmdType = 1024 + iota 107 CmdMvccGetByStartTs 108 CmdSplitRegion 109 110 CmdDebugGetRegionProperties CmdType = 2048 + iota 111 112 CmdEmpty CmdType = 3072 + iota 113 ) 114 115 func (t CmdType) String() string { 116 switch t { 117 case CmdGet: 118 return "Get" 119 case CmdScan: 120 return "Scan" 121 case CmdPrewrite: 122 return "Prewrite" 123 case CmdPessimisticLock: 124 return "PessimisticLock" 125 case CmdPessimisticRollback: 126 return "PessimisticRollback" 127 case CmdCommit: 128 return "Commit" 129 case CmdCleanup: 130 return "Cleanup" 131 case CmdBatchGet: 132 return "BatchGet" 133 case CmdBatchRollback: 134 return "BatchRollback" 135 case CmdScanLock: 136 return "ScanLock" 137 case CmdResolveLock: 138 return "ResolveLock" 139 case CmdGC: 140 return "GC" 141 case CmdDeleteRange: 142 return "DeleteRange" 143 case CmdRawGet: 144 return "RawGet" 145 case CmdRawBatchGet: 146 return "RawBatchGet" 147 case CmdRawPut: 148 return "RawPut" 149 case CmdRawBatchPut: 150 return "RawBatchPut" 151 case CmdRawDelete: 152 return "RawDelete" 153 case CmdRawBatchDelete: 154 return "RawBatchDelete" 155 case CmdRawDeleteRange: 156 return "RawDeleteRange" 157 case CmdRawScan: 158 return "RawScan" 159 case CmdUnsafeDestroyRange: 160 return "UnsafeDestroyRange" 161 case CmdRegisterLockObserver: 162 return "RegisterLockObserver" 163 case CmdCheckLockObserver: 164 return "CheckLockObserver" 165 case CmdRemoveLockObserver: 166 return "RemoveLockObserver" 167 case CmdPhysicalScanLock: 168 return "PhysicalScanLock" 169 case CmdCop: 170 return "Cop" 171 case CmdCopStream: 172 return "CopStream" 173 case CmdBatchCop: 174 return "BatchCop" 175 case CmdMPPTask: 176 return "DispatchMPPTask" 177 case CmdMPPConn: 178 return "EstablishMPPConnection" 179 case CmdMPPCancel: 180 return "CancelMPPTask" 181 case CmdMPPAlive: 182 return "MPPAlive" 183 case CmdMvccGetByKey: 184 return "MvccGetByKey" 185 case CmdMvccGetByStartTs: 186 return "MvccGetByStartTS" 187 case CmdSplitRegion: 188 return "SplitRegion" 189 case CmdCheckTxnStatus: 190 return "CheckTxnStatus" 191 case CmdCheckSecondaryLocks: 192 return "CheckSecondaryLocks" 193 case CmdDebugGetRegionProperties: 194 return "DebugGetRegionProperties" 195 case CmdTxnHeartBeat: 196 return "TxnHeartBeat" 197 case CmdStoreSafeTS: 198 return "StoreSafeTS" 199 case CmdLockWaitInfo: 200 return "LockWaitInfo" 201 } 202 return "Unknown" 203 } 204 205 // Request wraps all kv/coprocessor requests. 206 type Request struct { 207 Type CmdType 208 Req interface{} 209 kvrpcpb.Context 210 ReadReplicaScope string 211 // remove txnScope after tidb removed txnScope 212 TxnScope string 213 ReplicaReadType kv.ReplicaReadType // different from `kvrpcpb.Context.ReplicaRead` 214 ReplicaReadSeed *uint32 // pointer to follower read seed in snapshot/coprocessor 215 StoreTp EndpointType 216 // ForwardedHost is the address of a store which will handle the request. It's different from 217 // the address the request sent to. 218 // If it's not empty, the store which receive the request will forward it to 219 // the forwarded host. It's useful when network partition occurs. 220 ForwardedHost string 221 } 222 223 // NewRequest returns new kv rpc request. 224 func NewRequest(typ CmdType, pointer interface{}, ctxs ...kvrpcpb.Context) *Request { 225 if len(ctxs) > 0 { 226 return &Request{ 227 Type: typ, 228 Req: pointer, 229 Context: ctxs[0], 230 } 231 } 232 return &Request{ 233 Type: typ, 234 Req: pointer, 235 } 236 } 237 238 // NewReplicaReadRequest returns new kv rpc request with replica read. 239 func NewReplicaReadRequest(typ CmdType, pointer interface{}, replicaReadType kv.ReplicaReadType, replicaReadSeed *uint32, ctxs ...kvrpcpb.Context) *Request { 240 req := NewRequest(typ, pointer, ctxs...) 241 req.ReplicaRead = replicaReadType.IsFollowerRead() 242 req.ReplicaReadType = replicaReadType 243 req.ReplicaReadSeed = replicaReadSeed 244 return req 245 } 246 247 // GetReplicaReadSeed returns ReplicaReadSeed pointer. 248 func (req *Request) GetReplicaReadSeed() *uint32 { 249 if req != nil { 250 return req.ReplicaReadSeed 251 } 252 return nil 253 } 254 255 // EnableStaleRead enables stale read 256 func (req *Request) EnableStaleRead() { 257 req.StaleRead = true 258 req.ReplicaReadType = kv.ReplicaReadMixed 259 req.ReplicaRead = false 260 } 261 262 // IsGlobalStaleRead checks if the request is a global stale read request. 263 func (req *Request) IsGlobalStaleRead() bool { 264 return req.ReadReplicaScope == oracle.GlobalTxnScope && 265 // remove txnScope after tidb remove it 266 req.TxnScope == oracle.GlobalTxnScope && 267 req.GetStaleRead() 268 } 269 270 // IsDebugReq check whether the req is debug req. 271 func (req *Request) IsDebugReq() bool { 272 switch req.Type { 273 case CmdDebugGetRegionProperties: 274 return true 275 } 276 return false 277 } 278 279 // Get returns GetRequest in request. 280 func (req *Request) Get() *kvrpcpb.GetRequest { 281 return req.Req.(*kvrpcpb.GetRequest) 282 } 283 284 // Scan returns ScanRequest in request. 285 func (req *Request) Scan() *kvrpcpb.ScanRequest { 286 return req.Req.(*kvrpcpb.ScanRequest) 287 } 288 289 // Prewrite returns PrewriteRequest in request. 290 func (req *Request) Prewrite() *kvrpcpb.PrewriteRequest { 291 return req.Req.(*kvrpcpb.PrewriteRequest) 292 } 293 294 // Commit returns CommitRequest in request. 295 func (req *Request) Commit() *kvrpcpb.CommitRequest { 296 return req.Req.(*kvrpcpb.CommitRequest) 297 } 298 299 // Cleanup returns CleanupRequest in request. 300 func (req *Request) Cleanup() *kvrpcpb.CleanupRequest { 301 return req.Req.(*kvrpcpb.CleanupRequest) 302 } 303 304 // BatchGet returns BatchGetRequest in request. 305 func (req *Request) BatchGet() *kvrpcpb.BatchGetRequest { 306 return req.Req.(*kvrpcpb.BatchGetRequest) 307 } 308 309 // BatchRollback returns BatchRollbackRequest in request. 310 func (req *Request) BatchRollback() *kvrpcpb.BatchRollbackRequest { 311 return req.Req.(*kvrpcpb.BatchRollbackRequest) 312 } 313 314 // ScanLock returns ScanLockRequest in request. 315 func (req *Request) ScanLock() *kvrpcpb.ScanLockRequest { 316 return req.Req.(*kvrpcpb.ScanLockRequest) 317 } 318 319 // ResolveLock returns ResolveLockRequest in request. 320 func (req *Request) ResolveLock() *kvrpcpb.ResolveLockRequest { 321 return req.Req.(*kvrpcpb.ResolveLockRequest) 322 } 323 324 // GC returns GCRequest in request. 325 func (req *Request) GC() *kvrpcpb.GCRequest { 326 return req.Req.(*kvrpcpb.GCRequest) 327 } 328 329 // DeleteRange returns DeleteRangeRequest in request. 330 func (req *Request) DeleteRange() *kvrpcpb.DeleteRangeRequest { 331 return req.Req.(*kvrpcpb.DeleteRangeRequest) 332 } 333 334 // RawGet returns RawGetRequest in request. 335 func (req *Request) RawGet() *kvrpcpb.RawGetRequest { 336 return req.Req.(*kvrpcpb.RawGetRequest) 337 } 338 339 // RawBatchGet returns RawBatchGetRequest in request. 340 func (req *Request) RawBatchGet() *kvrpcpb.RawBatchGetRequest { 341 return req.Req.(*kvrpcpb.RawBatchGetRequest) 342 } 343 344 // RawPut returns RawPutRequest in request. 345 func (req *Request) RawPut() *kvrpcpb.RawPutRequest { 346 return req.Req.(*kvrpcpb.RawPutRequest) 347 } 348 349 // RawBatchPut returns RawBatchPutRequest in request. 350 func (req *Request) RawBatchPut() *kvrpcpb.RawBatchPutRequest { 351 return req.Req.(*kvrpcpb.RawBatchPutRequest) 352 } 353 354 // RawDelete returns PrewriteRequest in request. 355 func (req *Request) RawDelete() *kvrpcpb.RawDeleteRequest { 356 return req.Req.(*kvrpcpb.RawDeleteRequest) 357 } 358 359 // RawBatchDelete returns RawBatchDeleteRequest in request. 360 func (req *Request) RawBatchDelete() *kvrpcpb.RawBatchDeleteRequest { 361 return req.Req.(*kvrpcpb.RawBatchDeleteRequest) 362 } 363 364 // RawDeleteRange returns RawDeleteRangeRequest in request. 365 func (req *Request) RawDeleteRange() *kvrpcpb.RawDeleteRangeRequest { 366 return req.Req.(*kvrpcpb.RawDeleteRangeRequest) 367 } 368 369 // RawScan returns RawScanRequest in request. 370 func (req *Request) RawScan() *kvrpcpb.RawScanRequest { 371 return req.Req.(*kvrpcpb.RawScanRequest) 372 } 373 374 // UnsafeDestroyRange returns UnsafeDestroyRangeRequest in request. 375 func (req *Request) UnsafeDestroyRange() *kvrpcpb.UnsafeDestroyRangeRequest { 376 return req.Req.(*kvrpcpb.UnsafeDestroyRangeRequest) 377 } 378 379 // RawGetKeyTTL returns RawGetKeyTTLRequest in request. 380 func (req *Request) RawGetKeyTTL() *kvrpcpb.RawGetKeyTTLRequest { 381 return req.Req.(*kvrpcpb.RawGetKeyTTLRequest) 382 } 383 384 // RawCompareAndSwap returns RawCASRequest in request. 385 func (req *Request) RawCompareAndSwap() *kvrpcpb.RawCASRequest { 386 return req.Req.(*kvrpcpb.RawCASRequest) 387 } 388 389 // RegisterLockObserver returns RegisterLockObserverRequest in request. 390 func (req *Request) RegisterLockObserver() *kvrpcpb.RegisterLockObserverRequest { 391 return req.Req.(*kvrpcpb.RegisterLockObserverRequest) 392 } 393 394 // CheckLockObserver returns CheckLockObserverRequest in request. 395 func (req *Request) CheckLockObserver() *kvrpcpb.CheckLockObserverRequest { 396 return req.Req.(*kvrpcpb.CheckLockObserverRequest) 397 } 398 399 // RemoveLockObserver returns RemoveLockObserverRequest in request. 400 func (req *Request) RemoveLockObserver() *kvrpcpb.RemoveLockObserverRequest { 401 return req.Req.(*kvrpcpb.RemoveLockObserverRequest) 402 } 403 404 // PhysicalScanLock returns PhysicalScanLockRequest in request. 405 func (req *Request) PhysicalScanLock() *kvrpcpb.PhysicalScanLockRequest { 406 return req.Req.(*kvrpcpb.PhysicalScanLockRequest) 407 } 408 409 // Cop returns coprocessor request in request. 410 func (req *Request) Cop() *coprocessor.Request { 411 return req.Req.(*coprocessor.Request) 412 } 413 414 // BatchCop returns BatchCop request in request. 415 func (req *Request) BatchCop() *coprocessor.BatchRequest { 416 return req.Req.(*coprocessor.BatchRequest) 417 } 418 419 // DispatchMPPTask returns dispatch task request in request. 420 func (req *Request) DispatchMPPTask() *mpp.DispatchTaskRequest { 421 return req.Req.(*mpp.DispatchTaskRequest) 422 } 423 424 // IsMPPAlive returns IsAlive request in request. 425 func (req *Request) IsMPPAlive() *mpp.IsAliveRequest { 426 return req.Req.(*mpp.IsAliveRequest) 427 } 428 429 // EstablishMPPConn returns EstablishMPPConnectionRequest in request. 430 func (req *Request) EstablishMPPConn() *mpp.EstablishMPPConnectionRequest { 431 return req.Req.(*mpp.EstablishMPPConnectionRequest) 432 } 433 434 // CancelMPPTask returns canceling task in request 435 func (req *Request) CancelMPPTask() *mpp.CancelTaskRequest { 436 return req.Req.(*mpp.CancelTaskRequest) 437 } 438 439 // MvccGetByKey returns MvccGetByKeyRequest in request. 440 func (req *Request) MvccGetByKey() *kvrpcpb.MvccGetByKeyRequest { 441 return req.Req.(*kvrpcpb.MvccGetByKeyRequest) 442 } 443 444 // MvccGetByStartTs returns MvccGetByStartTsRequest in request. 445 func (req *Request) MvccGetByStartTs() *kvrpcpb.MvccGetByStartTsRequest { 446 return req.Req.(*kvrpcpb.MvccGetByStartTsRequest) 447 } 448 449 // SplitRegion returns SplitRegionRequest in request. 450 func (req *Request) SplitRegion() *kvrpcpb.SplitRegionRequest { 451 return req.Req.(*kvrpcpb.SplitRegionRequest) 452 } 453 454 // PessimisticLock returns PessimisticLockRequest in request. 455 func (req *Request) PessimisticLock() *kvrpcpb.PessimisticLockRequest { 456 return req.Req.(*kvrpcpb.PessimisticLockRequest) 457 } 458 459 // PessimisticRollback returns PessimisticRollbackRequest in request. 460 func (req *Request) PessimisticRollback() *kvrpcpb.PessimisticRollbackRequest { 461 return req.Req.(*kvrpcpb.PessimisticRollbackRequest) 462 } 463 464 // DebugGetRegionProperties returns GetRegionPropertiesRequest in request. 465 func (req *Request) DebugGetRegionProperties() *debugpb.GetRegionPropertiesRequest { 466 return req.Req.(*debugpb.GetRegionPropertiesRequest) 467 } 468 469 // Empty returns BatchCommandsEmptyRequest in request. 470 func (req *Request) Empty() *tikvpb.BatchCommandsEmptyRequest { 471 return req.Req.(*tikvpb.BatchCommandsEmptyRequest) 472 } 473 474 // CheckTxnStatus returns CheckTxnStatusRequest in request. 475 func (req *Request) CheckTxnStatus() *kvrpcpb.CheckTxnStatusRequest { 476 return req.Req.(*kvrpcpb.CheckTxnStatusRequest) 477 } 478 479 // CheckSecondaryLocks returns CheckSecondaryLocksRequest in request. 480 func (req *Request) CheckSecondaryLocks() *kvrpcpb.CheckSecondaryLocksRequest { 481 return req.Req.(*kvrpcpb.CheckSecondaryLocksRequest) 482 } 483 484 // TxnHeartBeat returns TxnHeartBeatRequest in request. 485 func (req *Request) TxnHeartBeat() *kvrpcpb.TxnHeartBeatRequest { 486 return req.Req.(*kvrpcpb.TxnHeartBeatRequest) 487 } 488 489 // StoreSafeTS returns StoreSafeTSRequest in request. 490 func (req *Request) StoreSafeTS() *kvrpcpb.StoreSafeTSRequest { 491 return req.Req.(*kvrpcpb.StoreSafeTSRequest) 492 } 493 494 // LockWaitInfo returns GetLockWaitInfoRequest in request. 495 func (req *Request) LockWaitInfo() *kvrpcpb.GetLockWaitInfoRequest { 496 return req.Req.(*kvrpcpb.GetLockWaitInfoRequest) 497 } 498 499 // ToBatchCommandsRequest converts the request to an entry in BatchCommands request. 500 func (req *Request) ToBatchCommandsRequest() *tikvpb.BatchCommandsRequest_Request { 501 switch req.Type { 502 case CmdGet: 503 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Get{Get: req.Get()}} 504 case CmdScan: 505 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Scan{Scan: req.Scan()}} 506 case CmdPrewrite: 507 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Prewrite{Prewrite: req.Prewrite()}} 508 case CmdCommit: 509 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Commit{Commit: req.Commit()}} 510 case CmdCleanup: 511 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Cleanup{Cleanup: req.Cleanup()}} 512 case CmdBatchGet: 513 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_BatchGet{BatchGet: req.BatchGet()}} 514 case CmdBatchRollback: 515 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_BatchRollback{BatchRollback: req.BatchRollback()}} 516 case CmdScanLock: 517 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_ScanLock{ScanLock: req.ScanLock()}} 518 case CmdResolveLock: 519 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_ResolveLock{ResolveLock: req.ResolveLock()}} 520 case CmdGC: 521 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_GC{GC: req.GC()}} 522 case CmdDeleteRange: 523 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_DeleteRange{DeleteRange: req.DeleteRange()}} 524 case CmdRawGet: 525 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawGet{RawGet: req.RawGet()}} 526 case CmdRawBatchGet: 527 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawBatchGet{RawBatchGet: req.RawBatchGet()}} 528 case CmdRawPut: 529 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawPut{RawPut: req.RawPut()}} 530 case CmdRawBatchPut: 531 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawBatchPut{RawBatchPut: req.RawBatchPut()}} 532 case CmdRawDelete: 533 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawDelete{RawDelete: req.RawDelete()}} 534 case CmdRawBatchDelete: 535 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawBatchDelete{RawBatchDelete: req.RawBatchDelete()}} 536 case CmdRawDeleteRange: 537 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawDeleteRange{RawDeleteRange: req.RawDeleteRange()}} 538 case CmdRawScan: 539 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_RawScan{RawScan: req.RawScan()}} 540 case CmdCop: 541 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Coprocessor{Coprocessor: req.Cop()}} 542 case CmdPessimisticLock: 543 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_PessimisticLock{PessimisticLock: req.PessimisticLock()}} 544 case CmdPessimisticRollback: 545 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_PessimisticRollback{PessimisticRollback: req.PessimisticRollback()}} 546 case CmdEmpty: 547 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_Empty{Empty: req.Empty()}} 548 case CmdCheckTxnStatus: 549 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_CheckTxnStatus{CheckTxnStatus: req.CheckTxnStatus()}} 550 case CmdCheckSecondaryLocks: 551 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_CheckSecondaryLocks{CheckSecondaryLocks: req.CheckSecondaryLocks()}} 552 case CmdTxnHeartBeat: 553 return &tikvpb.BatchCommandsRequest_Request{Cmd: &tikvpb.BatchCommandsRequest_Request_TxnHeartBeat{TxnHeartBeat: req.TxnHeartBeat()}} 554 } 555 return nil 556 } 557 558 // Response wraps all kv/coprocessor responses. 559 type Response struct { 560 Resp interface{} 561 } 562 563 // FromBatchCommandsResponse converts a BatchCommands response to Response. 564 func FromBatchCommandsResponse(res *tikvpb.BatchCommandsResponse_Response) (*Response, error) { 565 if res.GetCmd() == nil { 566 return nil, errors.New("Unknown command response") 567 } 568 switch res := res.GetCmd().(type) { 569 case *tikvpb.BatchCommandsResponse_Response_Get: 570 return &Response{Resp: res.Get}, nil 571 case *tikvpb.BatchCommandsResponse_Response_Scan: 572 return &Response{Resp: res.Scan}, nil 573 case *tikvpb.BatchCommandsResponse_Response_Prewrite: 574 return &Response{Resp: res.Prewrite}, nil 575 case *tikvpb.BatchCommandsResponse_Response_Commit: 576 return &Response{Resp: res.Commit}, nil 577 case *tikvpb.BatchCommandsResponse_Response_Cleanup: 578 return &Response{Resp: res.Cleanup}, nil 579 case *tikvpb.BatchCommandsResponse_Response_BatchGet: 580 return &Response{Resp: res.BatchGet}, nil 581 case *tikvpb.BatchCommandsResponse_Response_BatchRollback: 582 return &Response{Resp: res.BatchRollback}, nil 583 case *tikvpb.BatchCommandsResponse_Response_ScanLock: 584 return &Response{Resp: res.ScanLock}, nil 585 case *tikvpb.BatchCommandsResponse_Response_ResolveLock: 586 return &Response{Resp: res.ResolveLock}, nil 587 case *tikvpb.BatchCommandsResponse_Response_GC: 588 return &Response{Resp: res.GC}, nil 589 case *tikvpb.BatchCommandsResponse_Response_DeleteRange: 590 return &Response{Resp: res.DeleteRange}, nil 591 case *tikvpb.BatchCommandsResponse_Response_RawGet: 592 return &Response{Resp: res.RawGet}, nil 593 case *tikvpb.BatchCommandsResponse_Response_RawBatchGet: 594 return &Response{Resp: res.RawBatchGet}, nil 595 case *tikvpb.BatchCommandsResponse_Response_RawPut: 596 return &Response{Resp: res.RawPut}, nil 597 case *tikvpb.BatchCommandsResponse_Response_RawBatchPut: 598 return &Response{Resp: res.RawBatchPut}, nil 599 case *tikvpb.BatchCommandsResponse_Response_RawDelete: 600 return &Response{Resp: res.RawDelete}, nil 601 case *tikvpb.BatchCommandsResponse_Response_RawBatchDelete: 602 return &Response{Resp: res.RawBatchDelete}, nil 603 case *tikvpb.BatchCommandsResponse_Response_RawDeleteRange: 604 return &Response{Resp: res.RawDeleteRange}, nil 605 case *tikvpb.BatchCommandsResponse_Response_RawScan: 606 return &Response{Resp: res.RawScan}, nil 607 case *tikvpb.BatchCommandsResponse_Response_Coprocessor: 608 return &Response{Resp: res.Coprocessor}, nil 609 case *tikvpb.BatchCommandsResponse_Response_PessimisticLock: 610 return &Response{Resp: res.PessimisticLock}, nil 611 case *tikvpb.BatchCommandsResponse_Response_PessimisticRollback: 612 return &Response{Resp: res.PessimisticRollback}, nil 613 case *tikvpb.BatchCommandsResponse_Response_Empty: 614 return &Response{Resp: res.Empty}, nil 615 case *tikvpb.BatchCommandsResponse_Response_TxnHeartBeat: 616 return &Response{Resp: res.TxnHeartBeat}, nil 617 case *tikvpb.BatchCommandsResponse_Response_CheckTxnStatus: 618 return &Response{Resp: res.CheckTxnStatus}, nil 619 case *tikvpb.BatchCommandsResponse_Response_CheckSecondaryLocks: 620 return &Response{Resp: res.CheckSecondaryLocks}, nil 621 } 622 panic("unreachable") 623 } 624 625 // CopStreamResponse combines tikvpb.Tikv_CoprocessorStreamClient and the first Recv() result together. 626 // In streaming API, get grpc stream client may not involve any network packet, then region error have 627 // to be handled in Recv() function. This struct facilitates the error handling. 628 type CopStreamResponse struct { 629 tikvpb.Tikv_CoprocessorStreamClient 630 *coprocessor.Response // The first result of Recv() 631 Timeout time.Duration 632 Lease // Shared by this object and a background goroutine. 633 } 634 635 // BatchCopStreamResponse comprises the BatchCoprocessorClient , the first result and timeout detector. 636 type BatchCopStreamResponse struct { 637 tikvpb.Tikv_BatchCoprocessorClient 638 *coprocessor.BatchResponse 639 Timeout time.Duration 640 Lease // Shared by this object and a background goroutine. 641 } 642 643 // MPPStreamResponse is indeed a wrapped client that can receive data packet from tiflash mpp server. 644 type MPPStreamResponse struct { 645 tikvpb.Tikv_EstablishMPPConnectionClient 646 *mpp.MPPDataPacket 647 Timeout time.Duration 648 Lease 649 } 650 651 // SetContext set the Context field for the given req to the specified ctx. 652 func SetContext(req *Request, region *metapb.Region, peer *metapb.Peer) error { 653 ctx := &req.Context 654 if region != nil { 655 ctx.RegionId = region.Id 656 ctx.RegionEpoch = region.RegionEpoch 657 } 658 ctx.Peer = peer 659 660 switch req.Type { 661 case CmdGet: 662 req.Get().Context = ctx 663 case CmdScan: 664 req.Scan().Context = ctx 665 case CmdPrewrite: 666 req.Prewrite().Context = ctx 667 case CmdPessimisticLock: 668 req.PessimisticLock().Context = ctx 669 case CmdPessimisticRollback: 670 req.PessimisticRollback().Context = ctx 671 case CmdCommit: 672 req.Commit().Context = ctx 673 case CmdCleanup: 674 req.Cleanup().Context = ctx 675 case CmdBatchGet: 676 req.BatchGet().Context = ctx 677 case CmdBatchRollback: 678 req.BatchRollback().Context = ctx 679 case CmdScanLock: 680 req.ScanLock().Context = ctx 681 case CmdResolveLock: 682 req.ResolveLock().Context = ctx 683 case CmdGC: 684 req.GC().Context = ctx 685 case CmdDeleteRange: 686 req.DeleteRange().Context = ctx 687 case CmdRawGet: 688 req.RawGet().Context = ctx 689 case CmdRawBatchGet: 690 req.RawBatchGet().Context = ctx 691 case CmdRawPut: 692 req.RawPut().Context = ctx 693 case CmdRawBatchPut: 694 req.RawBatchPut().Context = ctx 695 case CmdRawDelete: 696 req.RawDelete().Context = ctx 697 case CmdRawBatchDelete: 698 req.RawBatchDelete().Context = ctx 699 case CmdRawDeleteRange: 700 req.RawDeleteRange().Context = ctx 701 case CmdRawScan: 702 req.RawScan().Context = ctx 703 case CmdUnsafeDestroyRange: 704 req.UnsafeDestroyRange().Context = ctx 705 case CmdGetKeyTTL: 706 req.RawGetKeyTTL().Context = ctx 707 case CmdRawCompareAndSwap: 708 req.RawCompareAndSwap().Context = ctx 709 case CmdRegisterLockObserver: 710 req.RegisterLockObserver().Context = ctx 711 case CmdCheckLockObserver: 712 req.CheckLockObserver().Context = ctx 713 case CmdRemoveLockObserver: 714 req.RemoveLockObserver().Context = ctx 715 case CmdPhysicalScanLock: 716 req.PhysicalScanLock().Context = ctx 717 case CmdCop: 718 req.Cop().Context = ctx 719 case CmdCopStream: 720 req.Cop().Context = ctx 721 case CmdBatchCop: 722 req.BatchCop().Context = ctx 723 case CmdMPPTask: 724 // Dispatching MPP tasks don't need a region context, because it's a request for store but not region. 725 case CmdMvccGetByKey: 726 req.MvccGetByKey().Context = ctx 727 case CmdMvccGetByStartTs: 728 req.MvccGetByStartTs().Context = ctx 729 case CmdSplitRegion: 730 req.SplitRegion().Context = ctx 731 case CmdEmpty: 732 req.SplitRegion().Context = ctx 733 case CmdTxnHeartBeat: 734 req.TxnHeartBeat().Context = ctx 735 case CmdCheckTxnStatus: 736 req.CheckTxnStatus().Context = ctx 737 case CmdCheckSecondaryLocks: 738 req.CheckSecondaryLocks().Context = ctx 739 default: 740 return fmt.Errorf("invalid request type %v", req.Type) 741 } 742 return nil 743 } 744 745 // GenRegionErrorResp returns corresponding Response with specified RegionError 746 // according to the given req. 747 func GenRegionErrorResp(req *Request, e *errorpb.Error) (*Response, error) { 748 var p interface{} 749 resp := &Response{} 750 switch req.Type { 751 case CmdGet: 752 p = &kvrpcpb.GetResponse{ 753 RegionError: e, 754 } 755 case CmdScan: 756 p = &kvrpcpb.ScanResponse{ 757 RegionError: e, 758 } 759 case CmdPrewrite: 760 p = &kvrpcpb.PrewriteResponse{ 761 RegionError: e, 762 } 763 case CmdPessimisticLock: 764 p = &kvrpcpb.PessimisticLockResponse{ 765 RegionError: e, 766 } 767 case CmdPessimisticRollback: 768 p = &kvrpcpb.PessimisticRollbackResponse{ 769 RegionError: e, 770 } 771 case CmdCommit: 772 p = &kvrpcpb.CommitResponse{ 773 RegionError: e, 774 } 775 case CmdCleanup: 776 p = &kvrpcpb.CleanupResponse{ 777 RegionError: e, 778 } 779 case CmdBatchGet: 780 p = &kvrpcpb.BatchGetResponse{ 781 RegionError: e, 782 } 783 case CmdBatchRollback: 784 p = &kvrpcpb.BatchRollbackResponse{ 785 RegionError: e, 786 } 787 case CmdScanLock: 788 p = &kvrpcpb.ScanLockResponse{ 789 RegionError: e, 790 } 791 case CmdResolveLock: 792 p = &kvrpcpb.ResolveLockResponse{ 793 RegionError: e, 794 } 795 case CmdGC: 796 p = &kvrpcpb.GCResponse{ 797 RegionError: e, 798 } 799 case CmdDeleteRange: 800 p = &kvrpcpb.DeleteRangeResponse{ 801 RegionError: e, 802 } 803 case CmdRawGet: 804 p = &kvrpcpb.RawGetResponse{ 805 RegionError: e, 806 } 807 case CmdRawBatchGet: 808 p = &kvrpcpb.RawBatchGetResponse{ 809 RegionError: e, 810 } 811 case CmdRawPut: 812 p = &kvrpcpb.RawPutResponse{ 813 RegionError: e, 814 } 815 case CmdRawBatchPut: 816 p = &kvrpcpb.RawBatchPutResponse{ 817 RegionError: e, 818 } 819 case CmdRawDelete: 820 p = &kvrpcpb.RawDeleteResponse{ 821 RegionError: e, 822 } 823 case CmdRawBatchDelete: 824 p = &kvrpcpb.RawBatchDeleteResponse{ 825 RegionError: e, 826 } 827 case CmdRawDeleteRange: 828 p = &kvrpcpb.RawDeleteRangeResponse{ 829 RegionError: e, 830 } 831 case CmdRawScan: 832 p = &kvrpcpb.RawScanResponse{ 833 RegionError: e, 834 } 835 case CmdUnsafeDestroyRange: 836 p = &kvrpcpb.UnsafeDestroyRangeResponse{ 837 RegionError: e, 838 } 839 case CmdGetKeyTTL: 840 p = &kvrpcpb.RawGetKeyTTLResponse{ 841 RegionError: e, 842 } 843 case CmdRawCompareAndSwap: 844 p = &kvrpcpb.RawCASResponse{ 845 RegionError: e, 846 } 847 case CmdCop: 848 p = &coprocessor.Response{ 849 RegionError: e, 850 } 851 case CmdCopStream: 852 p = &CopStreamResponse{ 853 Response: &coprocessor.Response{ 854 RegionError: e, 855 }, 856 } 857 case CmdMvccGetByKey: 858 p = &kvrpcpb.MvccGetByKeyResponse{ 859 RegionError: e, 860 } 861 case CmdMvccGetByStartTs: 862 p = &kvrpcpb.MvccGetByStartTsResponse{ 863 RegionError: e, 864 } 865 case CmdSplitRegion: 866 p = &kvrpcpb.SplitRegionResponse{ 867 RegionError: e, 868 } 869 case CmdEmpty: 870 case CmdTxnHeartBeat: 871 p = &kvrpcpb.TxnHeartBeatResponse{ 872 RegionError: e, 873 } 874 case CmdCheckTxnStatus: 875 p = &kvrpcpb.CheckTxnStatusResponse{ 876 RegionError: e, 877 } 878 case CmdCheckSecondaryLocks: 879 p = &kvrpcpb.CheckSecondaryLocksResponse{ 880 RegionError: e, 881 } 882 default: 883 return nil, fmt.Errorf("invalid request type %v", req.Type) 884 } 885 resp.Resp = p 886 return resp, nil 887 } 888 889 type getRegionError interface { 890 GetRegionError() *errorpb.Error 891 } 892 893 // GetRegionError returns the RegionError of the underlying concrete response. 894 func (resp *Response) GetRegionError() (*errorpb.Error, error) { 895 if resp.Resp == nil { 896 return nil, nil 897 } 898 err, ok := resp.Resp.(getRegionError) 899 if !ok { 900 if _, isEmpty := resp.Resp.(*tikvpb.BatchCommandsEmptyResponse); isEmpty { 901 return nil, nil 902 } 903 return nil, fmt.Errorf("invalid response type %v", resp) 904 } 905 return err.GetRegionError(), nil 906 } 907 908 // CallRPC launches a rpc call. 909 // ch is needed to implement timeout for coprocessor streaming, the stream object's 910 // cancel function will be sent to the channel, together with a lease checked by a background goroutine. 911 func CallRPC(ctx context.Context, client tikvpb.TikvClient, req *Request) (*Response, error) { 912 resp := &Response{} 913 var err error 914 switch req.Type { 915 case CmdGet: 916 resp.Resp, err = client.KvGet(ctx, req.Get()) 917 case CmdScan: 918 resp.Resp, err = client.KvScan(ctx, req.Scan()) 919 case CmdPrewrite: 920 resp.Resp, err = client.KvPrewrite(ctx, req.Prewrite()) 921 case CmdPessimisticLock: 922 resp.Resp, err = client.KvPessimisticLock(ctx, req.PessimisticLock()) 923 case CmdPessimisticRollback: 924 resp.Resp, err = client.KVPessimisticRollback(ctx, req.PessimisticRollback()) 925 case CmdCommit: 926 resp.Resp, err = client.KvCommit(ctx, req.Commit()) 927 case CmdCleanup: 928 resp.Resp, err = client.KvCleanup(ctx, req.Cleanup()) 929 case CmdBatchGet: 930 resp.Resp, err = client.KvBatchGet(ctx, req.BatchGet()) 931 case CmdBatchRollback: 932 resp.Resp, err = client.KvBatchRollback(ctx, req.BatchRollback()) 933 case CmdScanLock: 934 resp.Resp, err = client.KvScanLock(ctx, req.ScanLock()) 935 case CmdResolveLock: 936 resp.Resp, err = client.KvResolveLock(ctx, req.ResolveLock()) 937 case CmdGC: 938 resp.Resp, err = client.KvGC(ctx, req.GC()) 939 case CmdDeleteRange: 940 resp.Resp, err = client.KvDeleteRange(ctx, req.DeleteRange()) 941 case CmdRawGet: 942 resp.Resp, err = client.RawGet(ctx, req.RawGet()) 943 case CmdRawBatchGet: 944 resp.Resp, err = client.RawBatchGet(ctx, req.RawBatchGet()) 945 case CmdRawPut: 946 resp.Resp, err = client.RawPut(ctx, req.RawPut()) 947 case CmdRawBatchPut: 948 resp.Resp, err = client.RawBatchPut(ctx, req.RawBatchPut()) 949 case CmdRawDelete: 950 resp.Resp, err = client.RawDelete(ctx, req.RawDelete()) 951 case CmdRawBatchDelete: 952 resp.Resp, err = client.RawBatchDelete(ctx, req.RawBatchDelete()) 953 case CmdRawDeleteRange: 954 resp.Resp, err = client.RawDeleteRange(ctx, req.RawDeleteRange()) 955 case CmdRawScan: 956 resp.Resp, err = client.RawScan(ctx, req.RawScan()) 957 case CmdUnsafeDestroyRange: 958 resp.Resp, err = client.UnsafeDestroyRange(ctx, req.UnsafeDestroyRange()) 959 case CmdGetKeyTTL: 960 resp.Resp, err = client.RawGetKeyTTL(ctx, req.RawGetKeyTTL()) 961 case CmdRawCompareAndSwap: 962 resp.Resp, err = client.RawCompareAndSwap(ctx, req.RawCompareAndSwap()) 963 case CmdRegisterLockObserver: 964 resp.Resp, err = client.RegisterLockObserver(ctx, req.RegisterLockObserver()) 965 case CmdCheckLockObserver: 966 resp.Resp, err = client.CheckLockObserver(ctx, req.CheckLockObserver()) 967 case CmdRemoveLockObserver: 968 resp.Resp, err = client.RemoveLockObserver(ctx, req.RemoveLockObserver()) 969 case CmdPhysicalScanLock: 970 resp.Resp, err = client.PhysicalScanLock(ctx, req.PhysicalScanLock()) 971 case CmdCop: 972 resp.Resp, err = client.Coprocessor(ctx, req.Cop()) 973 case CmdMPPTask: 974 resp.Resp, err = client.DispatchMPPTask(ctx, req.DispatchMPPTask()) 975 case CmdMPPAlive: 976 resp.Resp, err = client.IsAlive(ctx, req.IsMPPAlive()) 977 case CmdMPPConn: 978 var streamClient tikvpb.Tikv_EstablishMPPConnectionClient 979 streamClient, err = client.EstablishMPPConnection(ctx, req.EstablishMPPConn()) 980 resp.Resp = &MPPStreamResponse{ 981 Tikv_EstablishMPPConnectionClient: streamClient, 982 } 983 case CmdMPPCancel: 984 // it cannot use the ctx with cancel(), otherwise this cmd will fail. 985 resp.Resp, err = client.CancelMPPTask(ctx, req.CancelMPPTask()) 986 case CmdCopStream: 987 var streamClient tikvpb.Tikv_CoprocessorStreamClient 988 streamClient, err = client.CoprocessorStream(ctx, req.Cop()) 989 resp.Resp = &CopStreamResponse{ 990 Tikv_CoprocessorStreamClient: streamClient, 991 } 992 case CmdBatchCop: 993 var streamClient tikvpb.Tikv_BatchCoprocessorClient 994 streamClient, err = client.BatchCoprocessor(ctx, req.BatchCop()) 995 resp.Resp = &BatchCopStreamResponse{ 996 Tikv_BatchCoprocessorClient: streamClient, 997 } 998 case CmdMvccGetByKey: 999 resp.Resp, err = client.MvccGetByKey(ctx, req.MvccGetByKey()) 1000 case CmdMvccGetByStartTs: 1001 resp.Resp, err = client.MvccGetByStartTs(ctx, req.MvccGetByStartTs()) 1002 case CmdSplitRegion: 1003 resp.Resp, err = client.SplitRegion(ctx, req.SplitRegion()) 1004 case CmdEmpty: 1005 resp.Resp, err = &tikvpb.BatchCommandsEmptyResponse{}, nil 1006 case CmdCheckTxnStatus: 1007 resp.Resp, err = client.KvCheckTxnStatus(ctx, req.CheckTxnStatus()) 1008 case CmdCheckSecondaryLocks: 1009 resp.Resp, err = client.KvCheckSecondaryLocks(ctx, req.CheckSecondaryLocks()) 1010 case CmdTxnHeartBeat: 1011 resp.Resp, err = client.KvTxnHeartBeat(ctx, req.TxnHeartBeat()) 1012 case CmdStoreSafeTS: 1013 resp.Resp, err = client.GetStoreSafeTS(ctx, req.StoreSafeTS()) 1014 case CmdLockWaitInfo: 1015 resp.Resp, err = client.GetLockWaitInfo(ctx, req.LockWaitInfo()) 1016 default: 1017 return nil, errors.Errorf("invalid request type: %v", req.Type) 1018 } 1019 if err != nil { 1020 return nil, errors.Trace(err) 1021 } 1022 return resp, nil 1023 } 1024 1025 // CallDebugRPC launches a debug rpc call. 1026 func CallDebugRPC(ctx context.Context, client debugpb.DebugClient, req *Request) (*Response, error) { 1027 resp := &Response{} 1028 var err error 1029 switch req.Type { 1030 case CmdDebugGetRegionProperties: 1031 resp.Resp, err = client.GetRegionProperties(ctx, req.DebugGetRegionProperties()) 1032 default: 1033 return nil, errors.Errorf("invalid request type: %v", req.Type) 1034 } 1035 return resp, err 1036 } 1037 1038 // Lease is used to implement grpc stream timeout. 1039 type Lease struct { 1040 Cancel context.CancelFunc 1041 deadline int64 // A time.UnixNano value, if time.Now().UnixNano() > deadline, cancel() would be called. 1042 } 1043 1044 // Recv overrides the stream client Recv() function. 1045 func (resp *CopStreamResponse) Recv() (*coprocessor.Response, error) { 1046 deadline := time.Now().Add(resp.Timeout).UnixNano() 1047 atomic.StoreInt64(&resp.Lease.deadline, deadline) 1048 1049 ret, err := resp.Tikv_CoprocessorStreamClient.Recv() 1050 1051 atomic.StoreInt64(&resp.Lease.deadline, 0) // Stop the lease check. 1052 return ret, errors.Trace(err) 1053 } 1054 1055 // Close closes the CopStreamResponse object. 1056 func (resp *CopStreamResponse) Close() { 1057 atomic.StoreInt64(&resp.Lease.deadline, 1) 1058 // We also call cancel here because CheckStreamTimeoutLoop 1059 // is not guaranteed to cancel all items when it exits. 1060 if resp.Lease.Cancel != nil { 1061 resp.Lease.Cancel() 1062 } 1063 } 1064 1065 // Recv overrides the stream client Recv() function. 1066 func (resp *BatchCopStreamResponse) Recv() (*coprocessor.BatchResponse, error) { 1067 deadline := time.Now().Add(resp.Timeout).UnixNano() 1068 atomic.StoreInt64(&resp.Lease.deadline, deadline) 1069 1070 ret, err := resp.Tikv_BatchCoprocessorClient.Recv() 1071 1072 atomic.StoreInt64(&resp.Lease.deadline, 0) // Stop the lease check. 1073 return ret, errors.Trace(err) 1074 } 1075 1076 // Close closes the BatchCopStreamResponse object. 1077 func (resp *BatchCopStreamResponse) Close() { 1078 atomic.StoreInt64(&resp.Lease.deadline, 1) 1079 // We also call cancel here because CheckStreamTimeoutLoop 1080 // is not guaranteed to cancel all items when it exits. 1081 if resp.Lease.Cancel != nil { 1082 resp.Lease.Cancel() 1083 } 1084 } 1085 1086 // Recv overrides the stream client Recv() function. 1087 func (resp *MPPStreamResponse) Recv() (*mpp.MPPDataPacket, error) { 1088 deadline := time.Now().Add(resp.Timeout).UnixNano() 1089 atomic.StoreInt64(&resp.Lease.deadline, deadline) 1090 1091 ret, err := resp.Tikv_EstablishMPPConnectionClient.Recv() 1092 1093 atomic.StoreInt64(&resp.Lease.deadline, 0) // Stop the lease check. 1094 return ret, errors.Trace(err) 1095 } 1096 1097 // Close closes the MPPStreamResponse object. 1098 func (resp *MPPStreamResponse) Close() { 1099 atomic.StoreInt64(&resp.Lease.deadline, 1) 1100 // We also call cancel here because CheckStreamTimeoutLoop 1101 // is not guaranteed to cancel all items when it exits. 1102 if resp.Lease.Cancel != nil { 1103 resp.Lease.Cancel() 1104 } 1105 } 1106 1107 // CheckStreamTimeoutLoop runs periodically to check is there any stream request timed out. 1108 // Lease is an object to track stream requests, call this function with "go CheckStreamTimeoutLoop()" 1109 // It is not guaranteed to call every Lease.Cancel() putting into channel when exits. 1110 // If grpc-go supports SetDeadline(https://github.com/grpc/grpc-go/issues/2917), we can stop using this method. 1111 func CheckStreamTimeoutLoop(ch <-chan *Lease, done <-chan struct{}) { 1112 ticker := time.NewTicker(200 * time.Millisecond) 1113 defer ticker.Stop() 1114 array := make([]*Lease, 0, 1024) 1115 1116 for { 1117 select { 1118 case <-done: 1119 drainLoop: 1120 // Try my best cleaning the channel to make SendRequest which is blocking by it continues. 1121 for { 1122 select { 1123 case <-ch: 1124 default: 1125 break drainLoop 1126 } 1127 } 1128 return 1129 case item := <-ch: 1130 array = append(array, item) 1131 case now := <-ticker.C: 1132 array = keepOnlyActive(array, now.UnixNano()) 1133 } 1134 } 1135 } 1136 1137 // keepOnlyActive removes completed items, call cancel function for timeout items. 1138 func keepOnlyActive(array []*Lease, now int64) []*Lease { 1139 idx := 0 1140 for i := 0; i < len(array); i++ { 1141 item := array[i] 1142 deadline := atomic.LoadInt64(&item.deadline) 1143 if deadline == 0 || deadline > now { 1144 array[idx] = array[i] 1145 idx++ 1146 } else { 1147 item.Cancel() 1148 } 1149 } 1150 return array[:idx] 1151 } 1152 1153 // IsGreenGCRequest checks if the request is used by Green GC's protocol. This is used for failpoints to inject errors 1154 // to specified RPC requests. 1155 func (req *Request) IsGreenGCRequest() bool { 1156 if req.Type == CmdCheckLockObserver || 1157 req.Type == CmdRegisterLockObserver || 1158 req.Type == CmdRemoveLockObserver || 1159 req.Type == CmdPhysicalScanLock { 1160 return true 1161 } 1162 return false 1163 } 1164 1165 // IsTxnWriteRequest checks if the request is a transactional write request. This is used for failpoints to inject 1166 // errors to specified RPC requests. 1167 func (req *Request) IsTxnWriteRequest() bool { 1168 if req.Type == CmdPessimisticLock || 1169 req.Type == CmdPrewrite || 1170 req.Type == CmdCommit || 1171 req.Type == CmdBatchRollback || 1172 req.Type == CmdPessimisticRollback || 1173 req.Type == CmdCheckTxnStatus || 1174 req.Type == CmdCheckSecondaryLocks || 1175 req.Type == CmdCleanup || 1176 req.Type == CmdTxnHeartBeat || 1177 req.Type == CmdResolveLock { 1178 return true 1179 } 1180 return false 1181 }