/Users/deen/code/yugabyte-db/src/yb/master/master_cluster_service.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include "yb/gutil/casts.h" |
15 | | |
16 | | #include "yb/master/catalog_manager.h" |
17 | | #include "yb/master/master_cluster.service.h" |
18 | | #include "yb/master/master_heartbeat.pb.h" |
19 | | #include "yb/master/master_service_base.h" |
20 | | #include "yb/master/master_service_base-internal.h" |
21 | | #include "yb/master/ts_descriptor.h" |
22 | | #include "yb/master/ts_manager.h" |
23 | | |
24 | | #include "yb/util/service_util.h" |
25 | | |
26 | | DEFINE_double(master_slow_get_registration_probability, 0, |
27 | | "Probability of injecting delay in GetMasterRegistration."); |
28 | | |
29 | | using namespace std::literals; |
30 | | |
31 | | namespace yb { |
32 | | namespace master { |
33 | | |
34 | | namespace { |
35 | | |
36 | | class MasterClusterServiceImpl : public MasterServiceBase, public MasterClusterIf { |
37 | | public: |
38 | | explicit MasterClusterServiceImpl(Master* master) |
39 | 5.42k | : MasterServiceBase(master), MasterClusterIf(master->metric_entity()) {} |
40 | | |
41 | | void ListTabletServers(const ListTabletServersRequestPB* req, |
42 | | ListTabletServersResponsePB* resp, |
43 | 20.1k | rpc::RpcContext rpc) override { |
44 | 20.1k | SCOPED_LEADER_SHARED_LOCK(l, server_->catalog_manager_impl()); |
45 | 20.1k | if (!l.CheckIsInitializedAndIsLeaderOrRespond(resp, &rpc)) { |
46 | 11.7k | return; |
47 | 11.7k | } |
48 | | |
49 | 8.37k | std::vector<std::shared_ptr<TSDescriptor> > descs; |
50 | 8.37k | if (!req->primary_only()) { |
51 | 5.42k | server_->ts_manager()->GetAllDescriptors(&descs); |
52 | 2.94k | } else { |
53 | 2.94k | server_->ts_manager()->GetAllLiveDescriptorsInCluster( |
54 | 2.94k | &descs, |
55 | 2.94k | server_->catalog_manager_impl()->placement_uuid()); |
56 | 2.94k | } |
57 | | |
58 | 20.4k | for (const std::shared_ptr<TSDescriptor>& desc : descs) { |
59 | 20.4k | ListTabletServersResponsePB::Entry* entry = resp->add_servers(); |
60 | 20.4k | auto ts_info = *desc->GetTSInformationPB(); |
61 | 20.4k | *entry->mutable_instance_id() = std::move(*ts_info.mutable_tserver_instance()); |
62 | 20.4k | *entry->mutable_registration() = std::move(*ts_info.mutable_registration()); |
63 | 20.4k | entry->set_millis_since_heartbeat( |
64 | 20.4k | narrow_cast<int>(desc->TimeSinceHeartbeat().ToMilliseconds())); |
65 | 20.4k | entry->set_alive(desc->IsLive()); |
66 | 20.4k | desc->GetMetrics(entry->mutable_metrics()); |
67 | 20.4k | } |
68 | 8.37k | rpc.RespondSuccess(); |
69 | 8.37k | } |
70 | | |
71 | | void ListLiveTabletServers(const ListLiveTabletServersRequestPB* req, |
72 | | ListLiveTabletServersResponsePB* resp, |
73 | 2 | rpc::RpcContext rpc) override { |
74 | 2 | SCOPED_LEADER_SHARED_LOCK(l, server_->catalog_manager_impl()); |
75 | 2 | if (!l.CheckIsInitializedAndIsLeaderOrRespond(resp, &rpc)) { |
76 | 0 | return; |
77 | 0 | } |
78 | 2 | string placement_uuid = server_->catalog_manager_impl()->placement_uuid(); |
79 | | |
80 | 2 | vector<std::shared_ptr<TSDescriptor> > descs; |
81 | 2 | server_->ts_manager()->GetAllLiveDescriptors(&descs); |
82 | | |
83 | 6 | for (const std::shared_ptr<TSDescriptor>& desc : descs) { |
84 | 6 | ListLiveTabletServersResponsePB::Entry* entry = resp->add_servers(); |
85 | 6 | auto ts_info = *desc->GetTSInformationPB(); |
86 | 6 | *entry->mutable_instance_id() = std::move(*ts_info.mutable_tserver_instance()); |
87 | 6 | *entry->mutable_registration() = std::move(*ts_info.mutable_registration()); |
88 | 6 | bool isPrimary = server_->ts_manager()->IsTsInCluster(desc, placement_uuid); |
89 | 6 | entry->set_isfromreadreplica(!isPrimary); |
90 | 6 | } |
91 | 2 | rpc.RespondSuccess(); |
92 | 2 | } |
93 | | |
94 | | void ListMasters( |
95 | | const ListMastersRequestPB* req, |
96 | | ListMastersResponsePB* resp, |
97 | 50 | rpc::RpcContext rpc) override { |
98 | 50 | std::vector<ServerEntryPB> masters; |
99 | 50 | Status s = server_->ListMasters(&masters); |
100 | 50 | if (s.ok()) { |
101 | 160 | for (const ServerEntryPB& master : masters) { |
102 | 160 | resp->add_masters()->CopyFrom(master); |
103 | 160 | } |
104 | 50 | rpc.RespondSuccess(); |
105 | 0 | } else { |
106 | 0 | SetupErrorAndRespond(resp->mutable_error(), s, MasterErrorPB_Code_UNKNOWN_ERROR, &rpc); |
107 | 0 | } |
108 | 50 | } |
109 | | |
110 | | void ListMasterRaftPeers( |
111 | | const ListMasterRaftPeersRequestPB* req, |
112 | | ListMasterRaftPeersResponsePB* resp, |
113 | 0 | rpc::RpcContext rpc) override { |
114 | 0 | std::vector<consensus::RaftPeerPB> masters; |
115 | 0 | Status s = server_->ListRaftConfigMasters(&masters); |
116 | 0 | if (s.ok()) { |
117 | 0 | for (const consensus::RaftPeerPB& master : masters) { |
118 | 0 | resp->add_masters()->CopyFrom(master); |
119 | 0 | } |
120 | 0 | rpc.RespondSuccess(); |
121 | 0 | } else { |
122 | 0 | SetupErrorAndRespond(resp->mutable_error(), s, MasterErrorPB_Code_UNKNOWN_ERROR, &rpc); |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | | void GetMasterRegistration(const GetMasterRegistrationRequestPB* req, |
127 | | GetMasterRegistrationResponsePB* resp, |
128 | 4.29M | rpc::RpcContext rpc) override { |
129 | | // instance_id must always be set in order for status pages to be useful. |
130 | 4.29M | if (RandomActWithProbability(FLAGS_master_slow_get_registration_probability)) { |
131 | 51 | std::this_thread::sleep_for(20s); |
132 | 51 | } |
133 | 4.29M | resp->mutable_instance_id()->CopyFrom(server_->instance_pb()); |
134 | 4.29M | SCOPED_LEADER_SHARED_LOCK(l, server_->catalog_manager_impl()); |
135 | 4.29M | if (!l.CheckIsInitializedOrRespond(resp, &rpc)) { |
136 | 398k | return; |
137 | 398k | } |
138 | 3.89M | Status s = server_->GetMasterRegistration(resp->mutable_registration()); |
139 | 3.89M | CheckRespErrorOrSetUnknown(s, resp); |
140 | 3.89M | auto role = server_->catalog_manager_impl()->Role(); |
141 | 3.89M | if (role == PeerRole::LEADER) { |
142 | 696k | if (!l.leader_status().ok()) { |
143 | 261k | YB_LOG_EVERY_N_SECS(INFO, 1) |
144 | 2.93k | << "Patching role from leader to follower because of: " << l.leader_status() |
145 | 2.93k | << THROTTLE_MSG; |
146 | 261k | role = PeerRole::FOLLOWER; |
147 | 261k | } |
148 | 696k | } |
149 | 3.89M | resp->set_role(role); |
150 | 3.89M | rpc.RespondSuccess(); |
151 | 3.89M | } |
152 | | |
153 | | void IsMasterLeaderServiceReady( |
154 | | const IsMasterLeaderReadyRequestPB* req, IsMasterLeaderReadyResponsePB* resp, |
155 | 24 | rpc::RpcContext rpc) override { |
156 | 24 | SCOPED_LEADER_SHARED_LOCK(l, server_->catalog_manager_impl()); |
157 | 24 | if (!l.CheckIsInitializedAndIsLeaderOrRespond(resp, &rpc)) { |
158 | 0 | return; |
159 | 0 | } |
160 | | |
161 | 24 | rpc.RespondSuccess(); |
162 | 24 | } |
163 | | |
164 | | void DumpState( |
165 | | const DumpMasterStateRequestPB* req, |
166 | | DumpMasterStateResponsePB* resp, |
167 | 0 | rpc::RpcContext rpc) override { |
168 | 0 | SCOPED_LEADER_SHARED_LOCK(l, server_->catalog_manager_impl()); |
169 | 0 | if (!l.CheckIsInitializedOrRespond(resp, &rpc)) { |
170 | 0 | return; |
171 | 0 | } |
172 | | |
173 | 0 | const string role = (req->has_peers_also() && req->peers_also() ? "Leader" : "Follower"); |
174 | 0 | const string title = role + " Master " + server_->instance_pb().permanent_uuid(); |
175 | |
|
176 | 0 | if (req->return_dump_as_string()) { |
177 | 0 | std::ostringstream ss; |
178 | 0 | server_->catalog_manager_impl()->DumpState(&ss, req->on_disk()); |
179 | 0 | resp->set_dump(title + ":\n" + ss.str()); |
180 | 0 | } else { |
181 | 0 | LOG(INFO) << title; |
182 | 0 | server_->catalog_manager_impl()->DumpState(&LOG(INFO), req->on_disk()); |
183 | 0 | } |
184 | |
|
185 | 0 | if (req->has_peers_also() && req->peers_also()) { |
186 | 0 | std::vector<consensus::RaftPeerPB> masters_raft; |
187 | 0 | Status s = server_->ListRaftConfigMasters(&masters_raft); |
188 | 0 | CheckRespErrorOrSetUnknown(s, resp); |
189 | |
|
190 | 0 | if (!s.ok()) |
191 | 0 | return; |
192 | | |
193 | 0 | LOG(INFO) << "Sending dump command to " << masters_raft.size()-1 << " peers."; |
194 | | |
195 | | // Remove our entry before broadcasting to all peers. |
196 | 0 | bool found = false; |
197 | 0 | for (auto it = masters_raft.begin(); it != masters_raft.end(); it++) { |
198 | 0 | if (server_->instance_pb().permanent_uuid() == it->permanent_uuid()) { |
199 | 0 | masters_raft.erase(it); |
200 | 0 | found = true; |
201 | 0 | break; |
202 | 0 | } |
203 | 0 | } |
204 | |
|
205 | 0 | LOG_IF(DFATAL, !found) << "Did not find leader in Raft config: " |
206 | 0 | << server_->instance_pb().permanent_uuid(); |
207 | |
|
208 | 0 | s = server_->catalog_manager_impl()->PeerStateDump(masters_raft, req, resp); |
209 | 0 | CheckRespErrorOrSetUnknown(s, resp); |
210 | 0 | } |
211 | |
|
212 | 0 | rpc.RespondSuccess(); |
213 | 0 | } |
214 | | |
215 | | void ChangeLoadBalancerState( |
216 | | const ChangeLoadBalancerStateRequestPB* req, ChangeLoadBalancerStateResponsePB* resp, |
217 | 0 | rpc::RpcContext rpc) override { |
218 | | // This should work on both followers and leaders, in order to cover leader failover! |
219 | 0 | if (req->has_is_enabled()) { |
220 | 0 | LOG(INFO) << "Changing balancer state to " << req->is_enabled(); |
221 | 0 | server_->catalog_manager_impl()->SetLoadBalancerEnabled(req->is_enabled()); |
222 | 0 | } |
223 | |
|
224 | 0 | rpc.RespondSuccess(); |
225 | 0 | } |
226 | | |
227 | | void GetLoadBalancerState( |
228 | | const GetLoadBalancerStateRequestPB* req, GetLoadBalancerStateResponsePB* resp, |
229 | 0 | rpc::RpcContext rpc) override { |
230 | 0 | resp->set_is_enabled(server_->catalog_manager_impl()->IsLoadBalancerEnabled()); |
231 | 0 | rpc.RespondSuccess(); |
232 | 0 | } |
233 | | |
234 | | void RemovedMasterUpdate(const RemovedMasterUpdateRequestPB* req, |
235 | | RemovedMasterUpdateResponsePB* resp, |
236 | 27 | rpc::RpcContext rpc) override { |
237 | 27 | SCOPED_LEADER_SHARED_LOCK(l, server_->catalog_manager_impl()); |
238 | 27 | if (!l.CheckIsInitializedOrRespond(resp, &rpc)) { |
239 | 0 | return; |
240 | 0 | } |
241 | | |
242 | 27 | Status s = server_->GoIntoShellMode(); |
243 | 27 | CheckRespErrorOrSetUnknown(s, resp); |
244 | 27 | rpc.RespondSuccess(); |
245 | 27 | } |
246 | | |
247 | | void ChangeMasterClusterConfig( |
248 | | const ChangeMasterClusterConfigRequestPB* req, ChangeMasterClusterConfigResponsePB* resp, |
249 | 109 | rpc::RpcContext rpc) override { |
250 | 109 | HANDLE_ON_LEADER_WITH_LOCK(CatalogManager, SetClusterConfig); |
251 | 109 | } |
252 | | |
253 | | void GetMasterClusterConfig( |
254 | | const GetMasterClusterConfigRequestPB* req, GetMasterClusterConfigResponsePB* resp, |
255 | 206 | rpc::RpcContext rpc) override { |
256 | 206 | HANDLE_ON_LEADER_WITH_LOCK(CatalogManager, GetClusterConfig); |
257 | 206 | } |
258 | | |
259 | | void GetLeaderBlacklistCompletion( |
260 | | const GetLeaderBlacklistPercentRequestPB* req, GetLoadMovePercentResponsePB* resp, |
261 | 194 | rpc::RpcContext rpc) override { |
262 | 194 | HANDLE_ON_LEADER_WITH_LOCK(CatalogManager, GetLeaderBlacklistCompletionPercent); |
263 | 194 | } |
264 | | |
265 | | void GetLoadMoveCompletion( |
266 | | const GetLoadMovePercentRequestPB* req, GetLoadMovePercentResponsePB* resp, |
267 | 1.00k | rpc::RpcContext rpc) override { |
268 | 1.00k | HANDLE_ON_LEADER_WITH_LOCK(CatalogManager, GetLoadMoveCompletionPercent); |
269 | 1.00k | } |
270 | | |
271 | | MASTER_SERVICE_IMPL_ON_LEADER_WITH_LOCK( |
272 | | CatalogManager, |
273 | | (AreLeadersOnPreferredOnly) |
274 | | (IsLoadBalanced) |
275 | | (IsLoadBalancerIdle) |
276 | | (SetPreferredZones) |
277 | | ) |
278 | | }; |
279 | | |
280 | | } // namespace |
281 | | |
282 | 5.42k | std::unique_ptr<rpc::ServiceIf> MakeMasterClusterService(Master* master) { |
283 | 5.42k | return std::make_unique<MasterClusterServiceImpl>(master); |
284 | 5.42k | } |
285 | | |
286 | | } // namespace master |
287 | | } // namespace yb |