YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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