/Users/deen/code/yugabyte-db/src/yb/master/master_tablet_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/master/master_tablet_service.h" |
15 | | |
16 | | #include "yb/common/common_flags.h" |
17 | | #include "yb/common/entity_ids.h" |
18 | | #include "yb/common/wire_protocol.h" |
19 | | |
20 | | #include "yb/master/catalog_manager_if.h" |
21 | | #include "yb/master/master.h" |
22 | | #include "yb/master/scoped_leader_shared_lock.h" |
23 | | #include "yb/master/scoped_leader_shared_lock-internal.h" |
24 | | |
25 | | #include "yb/rpc/rpc_context.h" |
26 | | |
27 | | #include "yb/util/flag_tags.h" |
28 | | #include "yb/util/logging.h" |
29 | | #include "yb/util/result.h" |
30 | | #include "yb/util/status_format.h" |
31 | | |
32 | | DEFINE_test_flag(int32, ysql_catalog_write_rejection_percentage, 0, |
33 | | "Reject specified percentage of writes to the YSQL catalog tables."); |
34 | | TAG_FLAG(TEST_ysql_catalog_write_rejection_percentage, runtime); |
35 | | |
36 | | using namespace std::chrono_literals; |
37 | | |
38 | | namespace yb { |
39 | | namespace master { |
40 | | |
41 | | // Only SysTablet 0 is bootstrapped on all master peers, and only the master leader |
42 | | // reads other sys tablets. We check only for tablet 0 so as to have same readiness |
43 | | // level across all masters. |
44 | | // Note: If this value changes, then IsTabletServerReady has to be revisited. |
45 | | constexpr int NUM_TABLETS_SYS_CATALOG = 1; |
46 | | |
47 | | MasterTabletServiceImpl::MasterTabletServiceImpl(MasterTabletServer* server, Master* master) |
48 | 5.42k | : TabletServiceImpl(server), master_(master) { |
49 | 5.42k | } |
50 | | |
51 | | Result<std::shared_ptr<tablet::AbstractTablet>> MasterTabletServiceImpl::GetTabletForRead( |
52 | | const TabletId& tablet_id, tablet::TabletPeerPtr tablet_peer, |
53 | 640k | YBConsistencyLevel consistency_level, tserver::AllowSplitTablet allow_split_tablet) { |
54 | | // Ignore looked_up_tablet_peer. |
55 | | |
56 | 640k | SCOPED_LEADER_SHARED_LOCK(l, master_->catalog_manager_impl()); |
57 | 640k | RETURN_NOT_OK(l.first_failed_status()); |
58 | | |
59 | 640k | return master_->catalog_manager()->GetSystemTablet(tablet_id); |
60 | 640k | } |
61 | | |
62 | | void MasterTabletServiceImpl::Write(const tserver::WriteRequestPB* req, |
63 | | tserver::WriteResponsePB* resp, |
64 | 44.1k | rpc::RpcContext context) { |
65 | 44.1k | SCOPED_LEADER_SHARED_LOCK(l, master_->catalog_manager_impl()); |
66 | 44.1k | if (!l.CheckIsInitializedAndIsLeaderOrRespondTServer(resp, &context)) { |
67 | 0 | return; |
68 | 0 | } |
69 | | |
70 | 44.1k | if (PREDICT_FALSE(FLAGS_TEST_ysql_catalog_write_rejection_percentage > 0) && |
71 | 202 | req->pgsql_write_batch_size() > 0 && |
72 | 202 | RandomUniformInt(1, 99) <= FLAGS_TEST_ysql_catalog_write_rejection_percentage) { |
73 | 11 | context.RespondRpcFailure(rpc::ErrorStatusPB::ERROR_APPLICATION, |
74 | 11 | STATUS(InternalError, "Injected random failure for testing.")); |
75 | 11 | return; |
76 | 11 | } |
77 | | |
78 | 44.1k | bool log_versions = false; |
79 | 216k | for (const auto& pg_req : req->pgsql_write_batch()) { |
80 | 216k | if (pg_req.is_ysql_catalog_change()) { |
81 | 0 | const auto &res = master_->catalog_manager()->IncrementYsqlCatalogVersion(); |
82 | 0 | if (!res.ok()) { |
83 | 0 | context.RespondRpcFailure(rpc::ErrorStatusPB::ERROR_APPLICATION, |
84 | 0 | STATUS(InternalError, "Failed to increment YSQL catalog version")); |
85 | 0 | } |
86 | 216k | } else if (FLAGS_log_ysql_catalog_versions && pg_req.table_id() == kPgYbCatalogVersionTableId) { |
87 | 0 | log_versions = true; |
88 | 0 | } |
89 | 216k | } |
90 | | |
91 | 44.1k | tserver::TabletServiceImpl::Write(req, resp, std::move(context)); |
92 | | |
93 | 44.1k | if (log_versions) { |
94 | 0 | uint64_t catalog_version; |
95 | 0 | uint64_t last_breaking_version; |
96 | | // The above Write is async, so delay a bit to hopefully read the newly written values. If the |
97 | | // delay was not sufficient, it's not a big deal since this is just for logging. |
98 | 0 | SleepFor(100ms); |
99 | 0 | if (!master_->catalog_manager()->GetYsqlCatalogVersion(&catalog_version, |
100 | 0 | &last_breaking_version).ok()) { |
101 | 0 | LOG_WITH_FUNC(ERROR) << "failed to get catalog version, ignoring"; |
102 | 0 | } else { |
103 | 0 | LOG_WITH_FUNC(INFO) << "catalog version: " << catalog_version << ", breaking version: " |
104 | 0 | << last_breaking_version; |
105 | 0 | } |
106 | 0 | } |
107 | 44.1k | } |
108 | | |
109 | | void MasterTabletServiceImpl::IsTabletServerReady( |
110 | | const tserver::IsTabletServerReadyRequestPB* req, |
111 | | tserver::IsTabletServerReadyResponsePB* resp, |
112 | 9 | rpc::RpcContext context) { |
113 | 9 | SCOPED_LEADER_SHARED_LOCK(l, master_->catalog_manager_impl()); |
114 | 9 | int total_tablets = NUM_TABLETS_SYS_CATALOG; |
115 | 9 | resp->set_total_tablets(total_tablets); |
116 | 9 | resp->set_num_tablets_not_running(total_tablets); |
117 | | |
118 | | // Tablet 0 being ready corresponds to state_ = kRunning in catalog manager. |
119 | | // If catalog_status_ in not OK, then catalog manager state_ is not kRunning. |
120 | 9 | if (!l.CheckIsInitializedOrRespondTServer(resp, &context, false /* set_error */)) { |
121 | 0 | LOG(INFO) << "Zero tablets not running out of " << total_tablets; |
122 | 9 | } else { |
123 | 9 | LOG(INFO) << "All " << total_tablets << " tablets running."; |
124 | 9 | resp->set_num_tablets_not_running(0); |
125 | 9 | context.RespondSuccess(); |
126 | 9 | } |
127 | 9 | } |
128 | | |
129 | | namespace { |
130 | | |
131 | 0 | void HandleUnsupportedMethod(const char* method_name, rpc::RpcContext* context) { |
132 | 0 | context->RespondRpcFailure(rpc::ErrorStatusPB::ERROR_APPLICATION, |
133 | 0 | STATUS_FORMAT(NotSupported, "$0 Not Supported!", method_name)); |
134 | 0 | } |
135 | | |
136 | | } // namespace |
137 | | |
138 | | void MasterTabletServiceImpl::ListTablets(const tserver::ListTabletsRequestPB* req, |
139 | | tserver::ListTabletsResponsePB* resp, |
140 | 0 | rpc::RpcContext context) { |
141 | 0 | HandleUnsupportedMethod("ListTablets", &context); |
142 | 0 | } |
143 | | |
144 | | void MasterTabletServiceImpl::ListTabletsForTabletServer( |
145 | | const tserver::ListTabletsForTabletServerRequestPB* req, |
146 | | tserver::ListTabletsForTabletServerResponsePB* resp, |
147 | 0 | rpc::RpcContext context) { |
148 | 0 | HandleUnsupportedMethod("ListTabletsForTabletServer", &context); |
149 | 0 | } |
150 | | |
151 | | void MasterTabletServiceImpl::GetLogLocation(const tserver::GetLogLocationRequestPB* req, |
152 | | tserver::GetLogLocationResponsePB* resp, |
153 | 0 | rpc::RpcContext context) { |
154 | 0 | HandleUnsupportedMethod("GetLogLocation", &context); |
155 | 0 | } |
156 | | |
157 | | void MasterTabletServiceImpl::Checksum(const tserver::ChecksumRequestPB* req, |
158 | | tserver::ChecksumResponsePB* resp, |
159 | 0 | rpc::RpcContext context) { |
160 | 0 | HandleUnsupportedMethod("Checksum", &context); |
161 | 0 | } |
162 | | |
163 | | } // namespace master |
164 | | } // namespace yb |