YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/client/tablet_rpc.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright (c) YugaByte, Inc.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
// in compliance with the License.  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 distributed under the License
10
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
// or implied.  See the License for the specific language governing permissions and limitations
12
// under the License.
13
//
14
//
15
16
#ifndef YB_CLIENT_TABLET_RPC_H
17
#define YB_CLIENT_TABLET_RPC_H
18
19
#include <memory>
20
#include <string>
21
#include <unordered_set>
22
23
#include <gflags/gflags_declare.h>
24
#include <gtest/gtest_prod.h>
25
26
#include "yb/client/client_fwd.h"
27
28
#include "yb/common/hybrid_time.h"
29
30
#include "yb/master/master_fwd.h"
31
32
#include "yb/rpc/rpc_fwd.h"
33
#include "yb/rpc/rpc.h"
34
35
#include "yb/tserver/tserver_fwd.h"
36
#include "yb/tserver/tserver_types.pb.h"
37
38
#include "yb/util/status_fwd.h"
39
#include "yb/util/net/net_fwd.h"
40
41
namespace yb {
42
43
namespace tserver {
44
class TabletServerServiceProxy;
45
class TabletServerForwardServiceProxy;
46
}
47
48
namespace rpc {
49
class RpcController;
50
}
51
52
namespace client {
53
namespace internal {
54
55
class TabletRpc {
56
 public:
57
  virtual const tserver::TabletServerErrorPB* response_error() const = 0;
58
  virtual void Failed(const Status& status) = 0;
59
60
  // attempt_num starts with 1.
61
  virtual void SendRpcToTserver(int attempt_num) = 0;
62
63
52.5k
  virtual bool ShouldRetryExpiredRequest() { return false; }
64
65
 protected:
66
7.26M
  ~TabletRpc() {}
67
};
68
69
tserver::TabletServerErrorPB_Code ErrorCode(const tserver::TabletServerErrorPB* error);
70
71
class TabletInvoker {
72
 public:
73
  // If table is specified, TabletInvoker can detect that table partitions are stale in case tablet
74
  // is no longer available and return ClientErrorCode::kTablePartitionListIsStale.
75
  explicit TabletInvoker(const bool local_tserver_only,
76
                         const bool consistent_prefix,
77
                         YBClient* client,
78
                         rpc::RpcCommand* command,
79
                         TabletRpc* rpc,
80
                         RemoteTablet* tablet,
81
                         const std::shared_ptr<const YBTable>& table,
82
                         rpc::RpcRetrier* retrier,
83
                         Trace* trace,
84
                         master::IncludeInactive include_inactive =
85
                            master::IncludeInactive::kFalse);
86
87
  virtual ~TabletInvoker();
88
89
  void Execute(const std::string& tablet_id, bool leader_only = false);
90
91
  // Returns true when whole operation is finished, false otherwise.
92
  bool Done(Status* status);
93
94
  bool IsLocalCall() const;
95
96
  void WriteAsync(const tserver::WriteRequestPB& req, tserver::WriteResponsePB *resp,
97
                  rpc::RpcController *controller, std::function<void()>&& cb);
98
99
  void ReadAsync(const tserver::ReadRequestPB& req, tserver::ReadResponsePB *resp,
100
                 rpc::RpcController *controller, std::function<void()>&& cb);
101
102
14.6M
  const RemoteTabletPtr& tablet() const { return tablet_; }
103
  std::shared_ptr<tserver::TabletServerServiceProxy> proxy() const;
104
  ::yb::HostPort ProxyEndpoint() const;
105
0
  YBClient& client() const { return *client_; }
106
6.03M
  const RemoteTabletServer& current_ts() { return *current_ts_; }
107
0
  bool local_tserver_only() const { return local_tserver_only_; }
108
109
5.95M
  bool is_consistent_prefix() const { return consistent_prefix_; }
110
111
 private:
112
  friend class TabletRpcTest;
113
  FRIEND_TEST(TabletRpcTest, TabletInvokerSelectTabletServerRace);
114
115
  void SelectTabletServer();
116
117
  // This is an implementation of ReadRpc with consistency level as CONSISTENT_PREFIX. As a result,
118
  // there is no requirement that the read needs to hit the leader.
119
  void SelectTabletServerWithConsistentPrefix();
120
121
  // This is for Redis ops which always prefer to invoke the local tablet server. In case when it
122
  // is not the leader, a MOVED response will be returned.
123
  void SelectLocalTabletServer();
124
125
  // Marks all replicas on current_ts_ as failed and retries the write on a
126
  // new replica.
127
  CHECKED_STATUS FailToNewReplica(const Status& reason,
128
                                  const tserver::TabletServerErrorPB* error_code = nullptr);
129
130
  // Called when we finish a lookup (to find the new consensus leader). Retries
131
  // the rpc after a short delay.
132
  void LookupTabletCb(const Result<RemoteTabletPtr>& result);
133
134
  void InitialLookupTabletDone(const Result<RemoteTabletPtr>& result);
135
136
  // If we receive TABLET_NOT_FOUND and current_ts_ is set, that means we contacted a tserver
137
  // with a tablet_id, but the tserver no longer has that tablet.
138
  bool TabletNotFoundOnTServer(const tserver::TabletServerErrorPB* error_code,
139
7.25M
                               const Status& status) {
140
7.25M
    return status.IsNotFound() &&
141
1.97k
        ErrorCode(error_code) == tserver::TabletServerErrorPB::TABLET_NOT_FOUND &&
142
1.94k
        current_ts_ != nullptr;
143
7.25M
  }
144
145
  bool ShouldUseNodeLocalForwardProxy();
146
147
  YBClient* const client_;
148
149
  rpc::RpcCommand* const command_;
150
151
  TabletRpc* const rpc_;
152
153
  // The tablet that should receive this rpc.
154
  RemoteTabletPtr tablet_;
155
156
  std::string tablet_id_;
157
158
  const std::shared_ptr<const YBTable> table_;
159
160
  rpc::RpcRetrier* const retrier_;
161
162
  // Trace is provided externally and owner of this object should guarantee that it will be alive
163
  // while this object is alive.
164
  Trace* const trace_;
165
166
  // Whether or not to allow lookups of inactive (hidden) tablets.
167
  master::IncludeInactive const include_inactive_;
168
169
  // Used to retry some failed RPCs.
170
  // Tablet servers that refused the write because they were followers at the time.
171
  // Cleared when new consensus configuration information arrives from the master.
172
  struct FollowerData {
173
    // Last replica error, i.e. reason why it was marked as follower.
174
    Status status;
175
    // Error time.
176
    CoarseTimePoint time;
177
178
    std::string ToString() const;
179
  };
180
181
  std::unordered_map<RemoteTabletServer*, FollowerData> followers_;
182
183
  const bool local_tserver_only_;
184
185
  const bool consistent_prefix_;
186
187
  // The TS receiving the write. May change if the write is retried.
188
  // RemoteTabletServer is taken from YBClient cache, so it is guaranteed that those objects are
189
  // alive while YBClient is alive. Because we don't delete them, but only add and update.
190
  RemoteTabletServer* current_ts_ = nullptr;
191
192
  // Should we assign new leader in meta cache when successful response is received.
193
  bool assign_new_leader_ = false;
194
195
  // Whether to use the local node proxy or to use the default remote proxy for communication to the
196
  // tablet servers. This flag is true if all of the following conditions are true:
197
  // 1. FLAGS_ysql_forward_rpcs_to_local_tserver is true
198
  // 2. The node local forward proxy is set in the client.
199
  // 3. The destination tserver is not the same as the node local tserver.
200
  // 4. The rpc is not intended for the master.
201
  bool should_use_local_node_proxy_ = false;
202
};
203
204
CHECKED_STATUS ErrorStatus(const tserver::TabletServerErrorPB* error);
205
template <class Response>
206
5.99M
HybridTime GetPropagatedHybridTime(const Response& response) {
207
5.87M
  return response.has_propagated_hybrid_time() ? HybridTime(response.propagated_hybrid_time())
208
120k
                                               : HybridTime::kInvalid;
209
5.99M
}
_ZN2yb6client8internal23GetPropagatedHybridTimeINS_7tserver15WriteResponsePBEEENS_10HybridTimeERKT_
Line
Count
Source
206
1.32M
HybridTime GetPropagatedHybridTime(const Response& response) {
207
1.24M
  return response.has_propagated_hybrid_time() ? HybridTime(response.propagated_hybrid_time())
208
82.1k
                                               : HybridTime::kInvalid;
209
1.32M
}
_ZN2yb6client8internal23GetPropagatedHybridTimeINS_7tserver14ReadResponsePBEEENS_10HybridTimeERKT_
Line
Count
Source
206
4.67M
HybridTime GetPropagatedHybridTime(const Response& response) {
207
4.63M
  return response.has_propagated_hybrid_time() ? HybridTime(response.propagated_hybrid_time())
208
38.0k
                                               : HybridTime::kInvalid;
209
4.67M
}
210
211
} // namespace internal
212
} // namespace client
213
} // namespace yb
214
215
#endif // YB_CLIENT_TABLET_RPC_H