コード例 #1
0
ファイル: rpc.go プロジェクト: duzhanyuan/tidb
func (h *rpcHandler) handleRequest(req *kvrpcpb.Request) *kvrpcpb.Response {
	resp := &kvrpcpb.Response{
		Type: req.Type,
	}
	if err := h.checkContext(req.GetContext()); err != nil {
		resp.RegionError = err
		return resp
	}
	switch req.GetType() {
	case kvrpcpb.MessageType_CmdGet:
		resp.CmdGetResp = h.onGet(req.CmdGetReq)
	case kvrpcpb.MessageType_CmdScan:
		resp.CmdScanResp = h.onScan(req.CmdScanReq)
	case kvrpcpb.MessageType_CmdPrewrite:
		resp.CmdPrewriteResp = h.onPrewrite(req.CmdPrewriteReq)
	case kvrpcpb.MessageType_CmdCommit:
		resp.CmdCommitResp = h.onCommit(req.CmdCommitReq)
	case kvrpcpb.MessageType_CmdCleanup:
		resp.CmdCleanupResp = h.onCleanup(req.CmdCleanupReq)
	case kvrpcpb.MessageType_CmdCommitThenGet:
		resp.CmdCommitGetResp = h.onCommitThenGet(req.CmdCommitGetReq)
	case kvrpcpb.MessageType_CmdRollbackThenGet:
		resp.CmdRbGetResp = h.onRollbackThenGet(req.CmdRbGetReq)
	case kvrpcpb.MessageType_CmdBatchGet:
		resp.CmdBatchGetResp = h.onBatchGet(req.CmdBatchGetReq)
	}
	return resp
}
コード例 #2
0
ファイル: rpc.go プロジェクト: pingcap/tidb
func (h *rpcHandler) handleRequest(req *kvrpcpb.Request) *kvrpcpb.Response {
	var resp kvrpcpb.Response
	if err := h.checkContext(req.GetContext()); err != nil {
		resp.RegionError = err
		return &resp
	}
	switch req.GetType() {
	case kvrpcpb.MessageType_CmdGet:
		resp.CmdGetResp = h.onGet(req.CmdGetReq)
	case kvrpcpb.MessageType_CmdScan:
		resp.CmdScanResp = h.onScan(req.CmdScanReq)
	case kvrpcpb.MessageType_CmdPrewrite:
		resp.CmdPrewriteResp = h.onPrewrite(req.CmdPrewriteReq)
	case kvrpcpb.MessageType_CmdCommit:
		resp.CmdCommitResp = h.onCommit(req.CmdCommitReq)
	case kvrpcpb.MessageType_CmdCleanup:
		resp.CmdCleanupResp = h.onCleanup(req.CmdCleanupReq)
	case kvrpcpb.MessageType_CmdBatchGet:
		resp.CmdBatchGetResp = h.onBatchGet(req.CmdBatchGetReq)
	case kvrpcpb.MessageType_CmdScanLock:
		resp.CmdResolveLockResp = h.onResolveLock(req.CmdResolveLockReq)
	case kvrpcpb.MessageType_CmdResolveLock:
		resp.CmdResolveLockResp = h.onResolveLock(req.CmdResolveLockReq)

	case kvrpcpb.MessageType_CmdRawGet:
		resp.CmdRawGetResp = h.onRawGet(req.CmdRawGetReq)
	case kvrpcpb.MessageType_CmdRawPut:
		resp.CmdRawPutResp = h.onRawPut(req.CmdRawPutReq)
	case kvrpcpb.MessageType_CmdRawDelete:
		resp.CmdRawDeleteResp = h.onRawDelete(req.CmdRawDeleteReq)
	}
	resp.Type = req.Type
	return &resp
}
コード例 #3
0
ファイル: client_test.go プロジェクト: pingcap/tidb
// Server read message then close, so `Send` will return retry error.
func (s *testClientSuite) TestRetryReadThenClose(c *C) {
	l := startServer(":61236", c, readThenCloseRequest)
	defer l.Close()
	cli := newRPCClient()
	req := new(pb.Request)
	req.Type = pb.MessageType_CmdGet
	resp, err := cli.SendKVReq(":61236", req, readTimeoutShort)
	c.Assert(err, NotNil)
	c.Assert(resp, IsNil)
}
コード例 #4
0
ファイル: client_test.go プロジェクト: pingcap/tidb
// One normally `Send`.
func (s *testClientSuite) TestSendBySelf(c *C) {
	l := startServer(":61234", c, handleRequest)
	defer l.Close()
	cli := newRPCClient()
	req := new(pb.Request)
	req.Type = pb.MessageType_CmdGet
	getReq := new(pb.CmdGetRequest)
	getReq.Key = []byte("a")
	ver := uint64(0)
	getReq.Version = ver
	req.CmdGetReq = getReq
	resp, err := cli.SendKVReq(":61234", req, readTimeoutShort)
	c.Assert(err, IsNil)
	c.Assert(req.GetType(), Equals, resp.GetType())
}
コード例 #5
0
ファイル: kv.go プロジェクト: yangxuanjia/tidb
// sendKVReq sends req to tikv server. It will retry internally to find the right
// region leader if i) fails to establish a connection to server or ii) server
// returns `NotLeader`.
func (s *tikvStore) SendKVReq(bo *Backoffer, req *pb.Request, regionID RegionVerID) (*pb.Response, error) {
	for {
		region := s.regionCache.GetRegionByVerID(regionID)
		if region == nil {
			// If the region is not found in cache, it must be out
			// of date and already be cleaned up. We can skip the
			// RPC by returning RegionError directly.
			return &pb.Response{
				Type:        req.GetType(),
				RegionError: &errorpb.Error{StaleEpoch: &errorpb.StaleEpoch{}},
			}, nil
		}
		req.Context = region.GetContext()
		resp, err := s.client.SendKVReq(region.GetAddress(), req)
		if err != nil {
			s.regionCache.NextPeer(region.VerID())
			err = bo.Backoff(boTiKVRPC, errors.Errorf("send tikv request error: %v, ctx: %s, try next peer later", err, req.Context))
			if err != nil {
				return nil, errors.Trace(err)
			}
			continue
		}
		if regionErr := resp.GetRegionError(); regionErr != nil {
			// Retry if error is `NotLeader`.
			if notLeader := regionErr.GetNotLeader(); notLeader != nil {
				log.Warnf("tikv reports `NotLeader`: %s, ctx: %s, retry later", notLeader, req.Context)
				s.regionCache.UpdateLeader(region.VerID(), notLeader.GetLeader().GetId())
				if notLeader.GetLeader() == nil {
					err = bo.Backoff(boRegionMiss, errors.Errorf("not leader: %v, ctx: %s", notLeader, req.Context))
					if err != nil {
						return nil, errors.Trace(err)
					}
				}
				continue
			}
			// For other errors, we only drop cache here.
			// Because caller may need to re-split the request.
			log.Warnf("tikv reports region error: %s, ctx: %s", resp.GetRegionError(), req.Context)
			s.regionCache.DropRegion(region.VerID())
			return resp, nil
		}
		if resp.GetType() != req.GetType() {
			return nil, errors.Trace(errMismatch(resp, req))
		}
		return resp, nil
	}
}
コード例 #6
0
ファイル: region_request.go プロジェクト: pingcap/tidb
// SendKVReq sends a KV request to tikv server.
func (s *RegionRequestSender) SendKVReq(req *kvrpcpb.Request, regionID RegionVerID, timeout time.Duration) (*kvrpcpb.Response, error) {
	for {
		select {
		case <-s.bo.ctx.Done():
			return nil, errors.Trace(s.bo.ctx.Err())
		default:
		}

		ctx, err := s.regionCache.GetRPCContext(s.bo, regionID)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if ctx == nil {
			// If the region is not found in cache, it must be out
			// of date and already be cleaned up. We can skip the
			// RPC by returning RegionError directly.
			return &kvrpcpb.Response{
				Type:        req.GetType(),
				RegionError: &errorpb.Error{StaleEpoch: &errorpb.StaleEpoch{}},
			}, nil
		}

		resp, retry, err := s.sendKVReqToRegion(ctx, req, timeout)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if retry {
			continue
		}

		if regionErr := resp.GetRegionError(); regionErr != nil {
			retry, err := s.onRegionError(ctx, regionErr)
			if err != nil {
				return nil, errors.Trace(err)
			}
			if retry {
				continue
			}
			return resp, nil
		}

		if resp.GetType() != req.GetType() {
			return nil, errors.Trace(errMismatch(resp, req))
		}
		return resp, nil
	}
}
コード例 #7
0
ファイル: region_request.go プロジェクト: pingcap/tidb
func (s *RegionRequestSender) sendKVReqToRegion(ctx *RPCContext, req *kvrpcpb.Request, timeout time.Duration) (resp *kvrpcpb.Response, retry bool, err error) {
	req.Context = ctx.KVCtx
	resp, err = s.client.SendKVReq(ctx.Addr, req, timeout)
	if err != nil {
		if e := s.onSendFail(ctx, err); e != nil {
			return nil, false, errors.Trace(e)
		}
		return nil, true, nil
	}
	return
}
コード例 #8
0
ファイル: error.go プロジェクト: XuHuaiyu/tidb
// errMismatch if response mismatches request return error.
func errMismatch(resp *pb.Response, req *pb.Request) error {
	return errors.Errorf("message type mismatches, response[%s] request[%s]",
		resp.GetType(), req.GetType())
}