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 }