Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | #include "cloud/cloud_meta_mgr.h" |
18 | | |
19 | | #include <brpc/channel.h> |
20 | | #include <brpc/controller.h> |
21 | | #include <brpc/errno.pb.h> |
22 | | #include <bthread/bthread.h> |
23 | | #include <bthread/condition_variable.h> |
24 | | #include <bthread/mutex.h> |
25 | | #include <gen_cpp/FrontendService.h> |
26 | | #include <gen_cpp/HeartbeatService_types.h> |
27 | | #include <gen_cpp/PlanNodes_types.h> |
28 | | #include <gen_cpp/Types_types.h> |
29 | | #include <gen_cpp/cloud.pb.h> |
30 | | #include <gen_cpp/olap_file.pb.h> |
31 | | #include <glog/logging.h> |
32 | | |
33 | | #include <algorithm> |
34 | | #include <atomic> |
35 | | #include <chrono> |
36 | | #include <cstdint> |
37 | | #include <memory> |
38 | | #include <mutex> |
39 | | #include <random> |
40 | | #include <shared_mutex> |
41 | | #include <string> |
42 | | #include <type_traits> |
43 | | #include <vector> |
44 | | |
45 | | #include "cloud/cloud_ms_backpressure_handler.h" |
46 | | #include "cloud/cloud_ms_rpc_rate_limiters.h" |
47 | | #include "cloud/cloud_storage_engine.h" |
48 | | #include "cloud/cloud_tablet.h" |
49 | | #include "cloud/cloud_warm_up_manager.h" |
50 | | #include "cloud/config.h" |
51 | | #include "cloud/delete_bitmap_file_reader.h" |
52 | | #include "cloud/delete_bitmap_file_writer.h" |
53 | | #include "cloud/pb_convert.h" |
54 | | #include "common/config.h" |
55 | | #include "common/logging.h" |
56 | | #include "common/status.h" |
57 | | #include "cpp/sync_point.h" |
58 | | #include "io/fs/obj_storage_client.h" |
59 | | #include "load/stream_load/stream_load_context.h" |
60 | | #include "runtime/exec_env.h" |
61 | | #include "storage/olap_common.h" |
62 | | #include "storage/rowset/rowset.h" |
63 | | #include "storage/rowset/rowset_factory.h" |
64 | | #include "storage/rowset/rowset_fwd.h" |
65 | | #include "storage/storage_engine.h" |
66 | | #include "storage/tablet/tablet_meta.h" |
67 | | #include "util/client_cache.h" |
68 | | #include "util/client_connection_provider.h" |
69 | | #include "util/network_util.h" |
70 | | #include "util/s3_util.h" |
71 | | #include "util/thrift_rpc_helper.h" |
72 | | |
73 | | namespace doris::cloud { |
74 | | using namespace ErrorCode; |
75 | | |
76 | 1.59M | void* run_bthread_work(void* arg) { |
77 | 1.59M | auto* f = reinterpret_cast<std::function<void()>*>(arg); |
78 | 1.59M | (*f)(); |
79 | 1.59M | delete f; |
80 | 1.59M | return nullptr; |
81 | 1.59M | } |
82 | | |
83 | 286k | Status bthread_fork_join(const std::vector<std::function<Status()>>& tasks, int concurrency) { |
84 | 286k | if (tasks.empty()) { |
85 | 2.24k | return Status::OK(); |
86 | 2.24k | } |
87 | | |
88 | 284k | bthread::Mutex lock; |
89 | 284k | bthread::ConditionVariable cond; |
90 | 284k | Status status; // Guard by lock |
91 | 284k | int count = 0; // Guard by lock |
92 | | |
93 | 1.37M | for (const auto& task : tasks) { |
94 | 1.37M | { |
95 | 1.37M | std::unique_lock lk(lock); |
96 | | // Wait until there are available slots |
97 | 1.44M | while (status.ok() && count >= concurrency) { |
98 | 76.0k | cond.wait(lk); |
99 | 76.0k | } |
100 | 1.37M | if (!status.ok()) { |
101 | 2 | break; |
102 | 2 | } |
103 | | |
104 | | // Increase running task count |
105 | 1.37M | ++count; |
106 | 1.37M | } |
107 | | |
108 | | // dispatch task into bthreads |
109 | 1.36M | auto* fn = new std::function<void()>([&, &task = task] { |
110 | 1.36M | auto st = task(); |
111 | 1.36M | { |
112 | 1.36M | std::lock_guard lk(lock); |
113 | 1.36M | --count; |
114 | 1.36M | if (!st.ok()) { |
115 | 2 | std::swap(st, status); |
116 | 2 | } |
117 | 1.36M | cond.notify_one(); |
118 | 1.36M | } |
119 | 1.36M | }); |
120 | | |
121 | 1.37M | bthread_t bthread_id; |
122 | 1.37M | if (bthread_start_background(&bthread_id, nullptr, run_bthread_work, fn) != 0) { |
123 | 0 | run_bthread_work(fn); |
124 | 0 | } |
125 | 1.37M | } |
126 | | |
127 | | // Wait until all running tasks have done |
128 | 284k | { |
129 | 284k | std::unique_lock lk(lock); |
130 | 921k | while (count > 0) { |
131 | 636k | cond.wait(lk); |
132 | 636k | } |
133 | 284k | } |
134 | | |
135 | 284k | return status; |
136 | 286k | } |
137 | | |
138 | | Status bthread_fork_join(std::vector<std::function<Status()>>&& tasks, int concurrency, |
139 | 226k | std::future<Status>* fut) { |
140 | | // std::function will cause `copy`, we need to use heap memory to avoid copy ctor called |
141 | 226k | auto prom = std::make_shared<std::promise<Status>>(); |
142 | 226k | *fut = prom->get_future(); |
143 | 226k | std::function<void()>* fn = new std::function<void()>( |
144 | 228k | [tasks = std::move(tasks), concurrency, p = std::move(prom)]() mutable { |
145 | 228k | p->set_value(bthread_fork_join(tasks, concurrency)); |
146 | 228k | }); |
147 | | |
148 | 226k | bthread_t bthread_id; |
149 | 226k | if (bthread_start_background(&bthread_id, nullptr, run_bthread_work, fn) != 0) { |
150 | 0 | delete fn; |
151 | 0 | return Status::InternalError<false>("failed to create bthread"); |
152 | 0 | } |
153 | 226k | return Status::OK(); |
154 | 226k | } |
155 | | |
156 | | // Resolve the status code returned by Meta Service (MS) for BE/FE clients of different version. |
157 | | // Assuming MS is always the latest version, it sends both the meta-service error code and a code that |
158 | | // older clients can decode: |
159 | | // |
160 | | // latest MS |
161 | | // +---------------------------------------+ |
162 | | // | actual_code = meta-service error code | |
163 | | // | code = compatible code | |
164 | | // +----------------+----------------------+ |
165 | | // | |
166 | | // +-------------+-------------+ |
167 | | // | | |
168 | | // old BE/FE without old BE/FE with |
169 | | // the actual_code field the actual_code field |
170 | | // | | |
171 | | // ignores actual_code local enum recognizes |
172 | | // and reads code actual_code value? |
173 | | // / \ |
174 | | // yes no |
175 | | // | | |
176 | | // use actual code use code only when it |
177 | | // is explicit and non-OK |
178 | | // | |
179 | | // otherwise return |
180 | | // UNDEFINED_ERR |
181 | | // |
182 | | // After MS adds an error code, an older actual_code-aware client may not have that enum value; |
183 | | // MetaServiceCode_IsValid detects this case. The non-OK fallback check is essential: |
184 | | // if MS ignore or incorrectly converts the compatible code to OK, an unknown error |
185 | | // must remain an error instead of becoming a false success. |
186 | 1.05M | MetaServiceCode get_response_code(const MetaServiceResponseStatus& status) { |
187 | 1.05M | if (status.has_actual_code()) { |
188 | | // Check whether this client build contains the code in its MetaServiceCode enum. |
189 | 1.05M | if (MetaServiceCode_IsValid(status.actual_code())) { |
190 | 1.05M | return static_cast<MetaServiceCode>(status.actual_code()); |
191 | 1.05M | } |
192 | | // An older client may use the compatible code, but unsupported cases must return an explicit error. |
193 | | // Return the non-OK compatible code prepared by MS for older clients. |
194 | 300 | if (status.has_code() && status.code() != MetaServiceCode::OK) { |
195 | 1 | return status.code(); |
196 | 1 | } |
197 | | // Never return OK when the compatible code is absent or invalid. |
198 | 299 | return MetaServiceCode::UNDEFINED_ERR; |
199 | 300 | } |
200 | | // A legacy response has only code, so return its explicit value, including a real OK. |
201 | 18.4E | if (status.has_code()) { |
202 | 2 | return status.code(); |
203 | 2 | } |
204 | | // A response missing both fields is invalid and must be rejected. |
205 | 18.4E | return MetaServiceCode::UNDEFINED_ERR; |
206 | 18.4E | } |
207 | | |
208 | | namespace { |
209 | | constexpr int kBrpcRetryTimes = 3; |
210 | | |
211 | 1.05M | void restore_actual_code(MetaServiceResponseStatus* status) { |
212 | 1.05M | status->set_code(get_response_code(*status)); |
213 | 1.05M | } |
214 | | |
215 | | bvar::LatencyRecorder _get_rowset_latency("doris_cloud_meta_mgr_get_rowset"); |
216 | | bvar::LatencyRecorder g_cloud_commit_txn_resp_redirect_latency("cloud_table_stats_report_latency"); |
217 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_rpc_timeout_count("cloud_meta_mgr_rpc_timeout_count"); |
218 | | bvar::Window<bvar::Adder<uint64_t>> g_cloud_ms_rpc_timeout_count_window( |
219 | | "cloud_meta_mgr_rpc_timeout_qps", &g_cloud_meta_mgr_rpc_timeout_count, 30); |
220 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_ms_too_busy_reason_total_count( |
221 | | "cloud_meta_mgr_ms_too_busy_reason", "total"); |
222 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_ms_too_busy_reason_fdb_cluster_count( |
223 | | "cloud_meta_mgr_ms_too_busy_reason", "fdb_cluster"); |
224 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_ms_too_busy_reason_fdb_client_thread_count( |
225 | | "cloud_meta_mgr_ms_too_busy_reason", "fdb_client_thread"); |
226 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_ms_too_busy_reason_ms_resource_count( |
227 | | "cloud_meta_mgr_ms_too_busy_reason", "ms_resource"); |
228 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_ms_too_busy_reason_test_injection_count( |
229 | | "cloud_meta_mgr_ms_too_busy_reason", "test_injection"); |
230 | | bvar::Adder<uint64_t> g_cloud_meta_mgr_ms_too_busy_reason_no_stress_condition_matched_count( |
231 | | "cloud_meta_mgr_ms_too_busy_reason", "no_stress_condition_matched"); |
232 | | bvar::LatencyRecorder g_cloud_be_mow_get_dbm_lock_backoff_sleep_time( |
233 | | "cloud_be_mow_get_dbm_lock_backoff_sleep_time"); |
234 | | bvar::Adder<uint64_t> g_cloud_version_hole_filled_count("cloud_version_hole_filled_count"); |
235 | | |
236 | | class MetaServiceProxy { |
237 | | public: |
238 | 1.04M | static Status get_proxy(MetaServiceProxy** proxy) { |
239 | | // The 'stub' is a useless parameter, added only to reuse the `get_pooled_client` function. |
240 | 1.04M | std::shared_ptr<MetaService_Stub> stub; |
241 | 1.04M | return get_pooled_client(&stub, proxy); |
242 | 1.04M | } |
243 | | |
244 | 0 | void set_unhealthy() { |
245 | 0 | std::unique_lock lock(_mutex); |
246 | 0 | maybe_unhealthy = true; |
247 | 0 | } |
248 | | |
249 | 2.09M | bool need_reconn(long now) { |
250 | 2.09M | return maybe_unhealthy && ((now - last_reconn_time_ms.front()) > |
251 | 0 | config::meta_service_rpc_reconnect_interval_ms); |
252 | 2.09M | } |
253 | | |
254 | 2.08M | Status get(std::shared_ptr<MetaService_Stub>* stub) { |
255 | 2.08M | using namespace std::chrono; |
256 | | |
257 | 2.08M | auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); |
258 | 2.08M | { |
259 | 2.08M | std::shared_lock lock(_mutex); |
260 | 2.10M | if (_deadline_ms >= now && !is_idle_timeout(now) && !need_reconn(now)) { |
261 | 2.09M | _last_access_at_ms.store(now, std::memory_order_relaxed); |
262 | 2.09M | *stub = _stub; |
263 | 2.09M | return Status::OK(); |
264 | 2.09M | } |
265 | 2.08M | } |
266 | | |
267 | 18.4E | auto channel = std::make_unique<brpc::Channel>(); |
268 | 18.4E | Status s = init_channel(channel.get()); |
269 | 18.4E | if (!s.ok()) [[unlikely]] { |
270 | 0 | return s; |
271 | 0 | } |
272 | | |
273 | 18.4E | *stub = std::make_shared<MetaService_Stub>(channel.release(), |
274 | 18.4E | google::protobuf::Service::STUB_OWNS_CHANNEL); |
275 | | |
276 | 18.4E | long deadline = now; |
277 | | // connection age only works without list endpoint. |
278 | 18.4E | if (config::meta_service_connection_age_base_seconds > 0) { |
279 | 1.38k | std::default_random_engine rng(static_cast<uint32_t>(now)); |
280 | 1.38k | std::uniform_int_distribution<> uni( |
281 | 1.38k | config::meta_service_connection_age_base_seconds, |
282 | 1.38k | config::meta_service_connection_age_base_seconds * 2); |
283 | 1.38k | deadline = now + duration_cast<milliseconds>(seconds(uni(rng))).count(); |
284 | 1.38k | } |
285 | | |
286 | | // Last one WIN |
287 | 18.4E | std::unique_lock lock(_mutex); |
288 | 18.4E | _last_access_at_ms.store(now, std::memory_order_relaxed); |
289 | 18.4E | _deadline_ms = deadline; |
290 | 18.4E | _stub = *stub; |
291 | | |
292 | 18.4E | last_reconn_time_ms.push(now); |
293 | 18.4E | last_reconn_time_ms.pop(); |
294 | 18.4E | maybe_unhealthy = false; |
295 | | |
296 | 18.4E | return Status::OK(); |
297 | 18.4E | } |
298 | | |
299 | | private: |
300 | 2.09M | static bool is_meta_service_endpoint_list() { |
301 | 2.09M | return config::meta_service_endpoint.find(',') != std::string::npos; |
302 | 2.09M | } |
303 | | |
304 | | /** |
305 | | * This function initializes a pool of `MetaServiceProxy` objects and selects one using |
306 | | * round-robin. It returns a client stub via the selected proxy. |
307 | | * |
308 | | * @param stub A pointer to a shared pointer of `MetaService_Stub` to be retrieved. |
309 | | * @param proxy (Optional) A pointer to store the selected `MetaServiceProxy`. |
310 | | * |
311 | | * @return Status Returns `Status::OK()` on success or an error status on failure. |
312 | | */ |
313 | | static Status get_pooled_client(std::shared_ptr<MetaService_Stub>* stub, |
314 | 1.05M | MetaServiceProxy** proxy) { |
315 | 1.05M | static std::once_flag proxies_flag; |
316 | 1.05M | static size_t num_proxies = 1; |
317 | 1.05M | static std::atomic<size_t> index(0); |
318 | 1.05M | static std::unique_ptr<MetaServiceProxy[]> proxies; |
319 | 1.05M | if (config::meta_service_endpoint.empty()) { |
320 | 21 | return Status::InvalidArgument( |
321 | 21 | "Meta service endpoint is empty. Please configure manually or wait for " |
322 | 21 | "heartbeat to obtain."); |
323 | 21 | } |
324 | 1.05M | std::call_once( |
325 | 1.05M | proxies_flag, +[]() { |
326 | 1 | if (config::meta_service_connection_pooled) { |
327 | 1 | num_proxies = config::meta_service_connection_pool_size; |
328 | 1 | } |
329 | 1 | proxies = std::make_unique<MetaServiceProxy[]>(num_proxies); |
330 | 1 | }); |
331 | | |
332 | 18.4E | for (size_t i = 0; i + 1 < num_proxies; ++i) { |
333 | 1.04M | size_t next_index = index.fetch_add(1, std::memory_order_relaxed) % num_proxies; |
334 | 1.04M | Status s = proxies[next_index].get(stub); |
335 | 1.05M | if (proxy != nullptr) { |
336 | 1.05M | *proxy = &(proxies[next_index]); |
337 | 1.05M | } |
338 | 1.04M | if (s.ok()) return Status::OK(); |
339 | 1.04M | } |
340 | | |
341 | 1.82k | size_t next_index = index.fetch_add(1, std::memory_order_relaxed) % num_proxies; |
342 | 1.82k | if (proxy != nullptr) { |
343 | 0 | *proxy = &(proxies[next_index]); |
344 | 0 | } |
345 | 1.82k | return proxies[next_index].get(stub); |
346 | 1.05M | } |
347 | | |
348 | 1.37k | static Status init_channel(brpc::Channel* channel) { |
349 | 1.37k | static std::atomic<size_t> index = 1; |
350 | | |
351 | 1.37k | const char* load_balancer_name = nullptr; |
352 | 1.37k | std::string endpoint; |
353 | 1.37k | if (is_meta_service_endpoint_list()) { |
354 | 0 | endpoint = fmt::format("list://{}", config::meta_service_endpoint); |
355 | 0 | load_balancer_name = "random"; |
356 | 1.37k | } else { |
357 | 1.37k | std::string ip; |
358 | 1.37k | uint16_t port; |
359 | 1.37k | Status s = get_meta_service_ip_and_port(&ip, &port); |
360 | 1.37k | if (!s.ok()) { |
361 | 0 | LOG(WARNING) << "fail to get meta service ip and port: " << s; |
362 | 0 | return s; |
363 | 0 | } |
364 | | |
365 | 1.37k | endpoint = get_host_port(ip, port); |
366 | 1.37k | } |
367 | | |
368 | 1.37k | brpc::ChannelOptions options; |
369 | 1.37k | RETURN_IF_ERROR(doris::client::configure_brpc_channel_options(&options)); |
370 | 1.37k | options.connection_group = |
371 | 1.37k | fmt::format("ms_{}", index.fetch_add(1, std::memory_order_relaxed)); |
372 | 1.37k | if (channel->Init(endpoint.c_str(), load_balancer_name, &options) != 0) { |
373 | 0 | return Status::InvalidArgument("failed to init brpc channel, endpoint: {}", endpoint); |
374 | 0 | } |
375 | 1.37k | return Status::OK(); |
376 | 1.37k | } |
377 | | |
378 | 1.37k | static Status get_meta_service_ip_and_port(std::string* ip, uint16_t* port) { |
379 | 1.37k | std::string parsed_host; |
380 | 1.37k | if (!parse_endpoint(config::meta_service_endpoint, &parsed_host, port)) { |
381 | 0 | return Status::InvalidArgument("invalid meta service endpoint: {}", |
382 | 0 | config::meta_service_endpoint); |
383 | 0 | } |
384 | 1.37k | if (is_valid_ip(parsed_host)) { |
385 | 1.37k | *ip = std::move(parsed_host); |
386 | 1.37k | return Status::OK(); |
387 | 1.37k | } |
388 | 18.4E | return hostname_to_ip(parsed_host, *ip); |
389 | 1.37k | } |
390 | | |
391 | 2.09M | bool is_idle_timeout(long now) { |
392 | 2.09M | auto idle_timeout_ms = config::meta_service_idle_connection_timeout_ms; |
393 | | // idle timeout only works without list endpoint. |
394 | 2.09M | return !is_meta_service_endpoint_list() && idle_timeout_ms > 0 && |
395 | 2.09M | _last_access_at_ms.load(std::memory_order_relaxed) + idle_timeout_ms < now; |
396 | 2.09M | } |
397 | | |
398 | | std::shared_mutex _mutex; |
399 | | std::atomic<long> _last_access_at_ms {0}; |
400 | | long _deadline_ms {0}; |
401 | | std::shared_ptr<MetaService_Stub> _stub; |
402 | | |
403 | | std::queue<long> last_reconn_time_ms {std::deque<long> {0, 0, 0}}; |
404 | | bool maybe_unhealthy = false; |
405 | | }; |
406 | | |
407 | | template <typename T, typename... Ts> |
408 | | struct is_any : std::disjunction<std::is_same<T, Ts>...> {}; |
409 | | |
410 | | template <typename T, typename... Ts> |
411 | | constexpr bool is_any_v = is_any<T, Ts...>::value; |
412 | | |
413 | | template <typename Request> |
414 | 313 | static std::string debug_info(const Request& req) { |
415 | 313 | if constexpr (is_any_v<Request, CommitTxnRequest, AbortTxnRequest, PrecommitTxnRequest>) { |
416 | 0 | return fmt::format(" txn_id={}", req.txn_id()); |
417 | 0 | } else if constexpr (is_any_v<Request, StartTabletJobRequest, FinishTabletJobRequest>) { |
418 | 0 | return fmt::format(" tablet_id={}", req.job().idx().tablet_id()); |
419 | 0 | } else if constexpr (is_any_v<Request, UpdateDeleteBitmapRequest>) { |
420 | 0 | return fmt::format(" tablet_id={}, lock_id={}", req.tablet_id(), req.lock_id()); |
421 | 313 | } else if constexpr (is_any_v<Request, GetDeleteBitmapUpdateLockRequest>) { |
422 | 313 | return fmt::format(" table_id={}, lock_id={}", req.table_id(), req.lock_id()); |
423 | 313 | } else if constexpr (is_any_v<Request, GetTabletRequest>) { |
424 | 0 | return fmt::format(" tablet_id={}", req.tablet_id()); |
425 | | } else if constexpr (is_any_v<Request, GetObjStoreInfoRequest, ListSnapshotRequest, |
426 | 0 | GetInstanceRequest, GetClusterStatusRequest>) { |
427 | 0 | return ""; |
428 | 0 | } else if constexpr (is_any_v<Request, CreateRowsetRequest>) { |
429 | 0 | return fmt::format(" tablet_id={}", req.rowset_meta().tablet_id()); |
430 | | } else if constexpr (is_any_v<Request, RemoveDeleteBitmapRequest>) { |
431 | | return fmt::format(" tablet_id={}", req.tablet_id()); |
432 | 0 | } else if constexpr (is_any_v<Request, RemoveDeleteBitmapUpdateLockRequest>) { |
433 | 0 | return fmt::format(" table_id={}, tablet_id={}, lock_id={}", req.table_id(), |
434 | 0 | req.tablet_id(), req.lock_id()); |
435 | 0 | } else if constexpr (is_any_v<Request, GetDeleteBitmapRequest>) { |
436 | 0 | return fmt::format(" tablet_id={}", req.tablet_id()); |
437 | | } else if constexpr (is_any_v<Request, GetSchemaDictRequest>) { |
438 | | return fmt::format(" index_id={}", req.index_id()); |
439 | 0 | } else if constexpr (is_any_v<Request, RestoreJobRequest>) { |
440 | 0 | return fmt::format(" tablet_id={}", req.tablet_id()); |
441 | 0 | } else if constexpr (is_any_v<Request, UpdatePackedFileInfoRequest>) { |
442 | 0 | return fmt::format(" packed_file_path={}", req.packed_file_path()); |
443 | | } else { |
444 | | static_assert(!sizeof(Request)); |
445 | | } |
446 | 313 | } Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_16GetTabletRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_22GetDeleteBitmapRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_19CreateRowsetRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_16CommitTxnRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_15AbortTxnRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_19PrecommitTxnRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_17RestoreJobRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_22GetObjStoreInfoRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_21StartTabletJobRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_22FinishTabletJobRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_25UpdateDeleteBitmapRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_32GetDeleteBitmapUpdateLockRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Line | Count | Source | 414 | 313 | static std::string debug_info(const Request& req) { | 415 | | if constexpr (is_any_v<Request, CommitTxnRequest, AbortTxnRequest, PrecommitTxnRequest>) { | 416 | | return fmt::format(" txn_id={}", req.txn_id()); | 417 | | } else if constexpr (is_any_v<Request, StartTabletJobRequest, FinishTabletJobRequest>) { | 418 | | return fmt::format(" tablet_id={}", req.job().idx().tablet_id()); | 419 | | } else if constexpr (is_any_v<Request, UpdateDeleteBitmapRequest>) { | 420 | | return fmt::format(" tablet_id={}, lock_id={}", req.tablet_id(), req.lock_id()); | 421 | 313 | } else if constexpr (is_any_v<Request, GetDeleteBitmapUpdateLockRequest>) { | 422 | 313 | return fmt::format(" table_id={}, lock_id={}", req.table_id(), req.lock_id()); | 423 | | } else if constexpr (is_any_v<Request, GetTabletRequest>) { | 424 | | return fmt::format(" tablet_id={}", req.tablet_id()); | 425 | | } else if constexpr (is_any_v<Request, GetObjStoreInfoRequest, ListSnapshotRequest, | 426 | | GetInstanceRequest, GetClusterStatusRequest>) { | 427 | | return ""; | 428 | | } else if constexpr (is_any_v<Request, CreateRowsetRequest>) { | 429 | | return fmt::format(" tablet_id={}", req.rowset_meta().tablet_id()); | 430 | | } else if constexpr (is_any_v<Request, RemoveDeleteBitmapRequest>) { | 431 | | return fmt::format(" tablet_id={}", req.tablet_id()); | 432 | | } else if constexpr (is_any_v<Request, RemoveDeleteBitmapUpdateLockRequest>) { | 433 | | return fmt::format(" table_id={}, tablet_id={}, lock_id={}", req.table_id(), | 434 | | req.tablet_id(), req.lock_id()); | 435 | | } else if constexpr (is_any_v<Request, GetDeleteBitmapRequest>) { | 436 | | return fmt::format(" tablet_id={}", req.tablet_id()); | 437 | | } else if constexpr (is_any_v<Request, GetSchemaDictRequest>) { | 438 | | return fmt::format(" index_id={}", req.index_id()); | 439 | | } else if constexpr (is_any_v<Request, RestoreJobRequest>) { | 440 | | return fmt::format(" tablet_id={}", req.tablet_id()); | 441 | | } else if constexpr (is_any_v<Request, UpdatePackedFileInfoRequest>) { | 442 | | return fmt::format(" packed_file_path={}", req.packed_file_path()); | 443 | | } else { | 444 | | static_assert(!sizeof(Request)); | 445 | | } | 446 | 313 | } |
Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_35RemoveDeleteBitmapUpdateLockRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_19ListSnapshotRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_18GetInstanceRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_27UpdatePackedFileInfoRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_110debug_infoINS0_23GetClusterStatusRequestEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_ |
447 | | |
448 | 877k | inline std::default_random_engine make_random_engine() { |
449 | 877k | return std::default_random_engine( |
450 | 877k | static_cast<uint32_t>(std::chrono::steady_clock::now().time_since_epoch().count())); |
451 | 877k | } |
452 | | |
453 | | // Convert MetaServiceRPC to LoadRelatedRpc |
454 | | // Returns LoadRelatedRpc::COUNT if the RPC is not a load-related RPC |
455 | 891k | LoadRelatedRpc to_load_related_rpc(MetaServiceRPC rpc) { |
456 | 891k | switch (rpc) { |
457 | 386k | case MetaServiceRPC::PREPARE_ROWSET: |
458 | 386k | return LoadRelatedRpc::PREPARE_ROWSET; |
459 | 385k | case MetaServiceRPC::COMMIT_ROWSET: |
460 | 385k | return LoadRelatedRpc::COMMIT_ROWSET; |
461 | 38 | case MetaServiceRPC::UPDATE_TMP_ROWSET: |
462 | 38 | return LoadRelatedRpc::UPDATE_TMP_ROWSET; |
463 | 0 | case MetaServiceRPC::UPDATE_PACKED_FILE_INFO: |
464 | 0 | return LoadRelatedRpc::UPDATE_PACKED_FILE_INFO; |
465 | 117k | case MetaServiceRPC::UPDATE_DELETE_BITMAP: |
466 | 117k | return LoadRelatedRpc::UPDATE_DELETE_BITMAP; |
467 | 0 | default: |
468 | 0 | return LoadRelatedRpc::COUNT; // Not a load-related RPC |
469 | 891k | } |
470 | 891k | } |
471 | | |
472 | | template <typename Request, typename Response> |
473 | | using MetaServiceMethod = void (MetaService_Stub::*)(::google::protobuf::RpcController*, |
474 | | const Request*, Response*, |
475 | | ::google::protobuf::Closure*); |
476 | | |
477 | | template <typename Request, typename Response> |
478 | | void call_ms(MetaService_Stub* stub, MetaServiceMethod<Request, Response> method, |
479 | 1.04M | brpc::Controller* cntl, const Request& req, Response* res) { |
480 | 1.04M | (stub->*method)(cntl, &req, res, nullptr); |
481 | 1.05M | if (!cntl->Failed()) { |
482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. |
483 | 1.05M | restore_actual_code(res->mutable_status()); |
484 | 1.05M | } |
485 | 1.04M | } cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_16GetTabletRequestENS0_17GetTabletResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 354k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 354k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 354k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 354k | restore_actual_code(res->mutable_status()); | 484 | 354k | } | 485 | 354k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_16GetRowsetRequestENS0_17GetRowsetResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 172k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 172k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 173k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 173k | restore_actual_code(res->mutable_status()); | 484 | 173k | } | 485 | 172k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_22GetDeleteBitmapRequestENS0_23GetDeleteBitmapResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 26.0k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 26.0k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 26.2k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 26.2k | restore_actual_code(res->mutable_status()); | 484 | 26.2k | } | 485 | 26.0k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_19CreateRowsetRequestENS0_20CreateRowsetResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 378k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 378k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 387k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 387k | restore_actual_code(res->mutable_status()); | 484 | 387k | } | 485 | 378k | } |
Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_16CommitTxnRequestENS0_17CommitTxnResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_15AbortTxnRequestENS0_16AbortTxnResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 488 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 488 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 488 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 488 | restore_actual_code(res->mutable_status()); | 484 | 488 | } | 485 | 488 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_19PrecommitTxnRequestENS0_20PrecommitTxnResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 33 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 33 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 33 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 33 | restore_actual_code(res->mutable_status()); | 484 | 33 | } | 485 | 33 | } |
Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_17RestoreJobRequestENS0_18RestoreJobResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_22GetObjStoreInfoRequestENS0_23GetObjStoreInfoResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 106 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 106 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 106 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 106 | restore_actual_code(res->mutable_status()); | 484 | 106 | } | 485 | 106 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_21StartTabletJobRequestENS0_22StartTabletJobResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 18.6k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 18.6k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 18.7k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 18.7k | restore_actual_code(res->mutable_status()); | 484 | 18.7k | } | 485 | 18.6k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_22FinishTabletJobRequestENS0_23FinishTabletJobResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 17.0k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 17.0k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 17.3k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 17.3k | restore_actual_code(res->mutable_status()); | 484 | 17.3k | } | 485 | 17.0k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_25UpdateDeleteBitmapRequestENS0_26UpdateDeleteBitmapResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 56.5k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 56.5k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 59.5k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 59.5k | restore_actual_code(res->mutable_status()); | 484 | 59.5k | } | 485 | 56.5k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_32GetDeleteBitmapUpdateLockRequestENS0_33GetDeleteBitmapUpdateLockResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 4.70k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 4.70k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 4.70k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 4.70k | restore_actual_code(res->mutable_status()); | 484 | 4.70k | } | 485 | 4.70k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_35RemoveDeleteBitmapUpdateLockRequestENS0_36RemoveDeleteBitmapUpdateLockResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 36 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 36 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 36 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 36 | restore_actual_code(res->mutable_status()); | 484 | 36 | } | 485 | 36 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_19ListSnapshotRequestENS0_20ListSnapshotResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 2 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 2 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 2 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 2 | restore_actual_code(res->mutable_status()); | 484 | 2 | } | 485 | 2 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_18GetInstanceRequestENS0_19GetInstanceResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 1 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 1 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 1 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 1 | restore_actual_code(res->mutable_status()); | 484 | 1 | } | 485 | 1 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_27UpdatePackedFileInfoRequestENS0_28UpdatePackedFileInfoResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 12.1k | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 12.1k | (stub->*method)(cntl, &req, res, nullptr); | 481 | 12.1k | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 12.1k | restore_actual_code(res->mutable_status()); | 484 | 12.1k | } | 485 | 12.1k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_17call_msINS0_23GetClusterStatusRequestENS0_24GetClusterStatusResponseEEEvPNS0_16MetaService_StubEMS5_FvPN6google8protobuf13RpcControllerEPKT_PT0_PNS8_7ClosureEEPN4brpc10ControllerERSC_SF_ Line | Count | Source | 479 | 56 | brpc::Controller* cntl, const Request& req, Response* res) { | 480 | 56 | (stub->*method)(cntl, &req, res, nullptr); | 481 | 56 | if (!cntl->Failed()) { | 482 | | // Meta Service may downgrade code for wire compatibility; restore the exact value. | 483 | 56 | restore_actual_code(res->mutable_status()); | 484 | 56 | } | 485 | 56 | } |
|
486 | | |
487 | | // Rate limiting context for retry_rpc |
488 | | struct RpcRateLimitCtx { |
489 | | HostLevelMSRpcRateLimiters* host_limiters {nullptr}; |
490 | | MSBackpressureHandler* backpressure_handler {nullptr}; |
491 | | int64_t table_id {-1}; // For table-level backpressure, passed from caller |
492 | | }; |
493 | | |
494 | | // Apply rate limiting before RPC (both host-level and table-level) |
495 | 876k | void apply_rate_limit(MetaServiceRPC rpc, const RpcRateLimitCtx& ctx) { |
496 | | // Table-level rate limit (for load-related RPCs only) |
497 | 878k | if (ctx.backpressure_handler && ctx.table_id > 0) { |
498 | 444k | LoadRelatedRpc load_rpc = to_load_related_rpc(rpc); |
499 | 444k | if (load_rpc != LoadRelatedRpc::COUNT) { |
500 | 441k | auto wait_until = ctx.backpressure_handler->before_rpc(load_rpc, ctx.table_id); |
501 | 441k | auto now = std::chrono::steady_clock::now(); |
502 | 441k | if (wait_until > now) { |
503 | 0 | auto wait_us = |
504 | 0 | std::chrono::duration_cast<std::chrono::microseconds>(wait_until - now) |
505 | 0 | .count(); |
506 | 0 | if (wait_us > 0) { |
507 | 0 | if (auto* recorder = get_throttle_wait_recorder(load_rpc); |
508 | 0 | recorder != nullptr) { |
509 | 0 | *recorder << wait_us; |
510 | 0 | } |
511 | 0 | bthread_usleep(wait_us); |
512 | 0 | } |
513 | 0 | } |
514 | 441k | } |
515 | 444k | } |
516 | | |
517 | | // Host-level rate limit |
518 | 876k | if (ctx.host_limiters) { |
519 | 876k | ctx.host_limiters->limit(rpc); |
520 | 876k | } |
521 | 876k | } |
522 | | |
523 | | // Record RPC QPS statistics after RPC (for table-level tracking) |
524 | 880k | void record_rpc_qps(MetaServiceRPC rpc, const RpcRateLimitCtx& ctx) { |
525 | 881k | if (ctx.backpressure_handler && ctx.table_id > 0) { |
526 | 447k | LoadRelatedRpc load_rpc = to_load_related_rpc(rpc); |
527 | 447k | if (load_rpc != LoadRelatedRpc::COUNT) { |
528 | 447k | ctx.backpressure_handler->after_rpc(load_rpc, ctx.table_id); |
529 | 447k | } |
530 | 447k | } |
531 | 880k | } |
532 | | |
533 | | template <typename Request, typename Response> |
534 | | Status retry_rpc(MetaServiceRPC rpc, const Request& req, Response* res, |
535 | | MetaServiceMethod<Request, Response> method, |
536 | 876k | const RpcRateLimitCtx& rate_limit_ctx = {}) { |
537 | 876k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); |
538 | 876k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); |
539 | | |
540 | 876k | std::string_view op_name = meta_service_rpc_display_name(rpc); |
541 | | |
542 | | // Applies only to the current file, and all req are non-const, but passed as const types. |
543 | 876k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); |
544 | | |
545 | 876k | int retry_times = 0; |
546 | 876k | uint32_t duration_ms = 0; |
547 | 876k | std::string error_msg; |
548 | 876k | std::default_random_engine rng = make_random_engine(); |
549 | 876k | std::uniform_int_distribution<uint32_t> u(20, 200); |
550 | 876k | std::uniform_int_distribution<uint32_t> u2(500, 1000); |
551 | 876k | MetaServiceProxy* proxy; |
552 | 876k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); |
553 | | |
554 | 876k | while (true) { |
555 | 876k | std::shared_ptr<MetaService_Stub> stub; |
556 | 876k | RETURN_IF_ERROR(proxy->get(&stub)); |
557 | | |
558 | | // Apply rate limiting (both host-level and table-level) |
559 | 876k | apply_rate_limit(rpc, rate_limit_ctx); |
560 | 876k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); |
561 | | |
562 | 876k | brpc::Controller cntl; |
563 | 876k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || |
564 | 876k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { |
565 | 84.4k | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); |
566 | 791k | } else { |
567 | 791k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); |
568 | 791k | } |
569 | 876k | cntl.set_max_retry(kBrpcRetryTimes); |
570 | 876k | res->Clear(); |
571 | 876k | int error_code = 0; |
572 | 876k | call_ms(stub.get(), method, &cntl, req, res); |
573 | | |
574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) |
575 | 876k | record_rpc_qps(rpc, rate_limit_ctx); |
576 | | |
577 | 876k | if (cntl.Failed()) [[unlikely]] { |
578 | 0 | error_msg = cntl.ErrorText(); |
579 | 0 | error_code = cntl.ErrorCode(); |
580 | 0 | proxy->set_unhealthy(); |
581 | 879k | } else if (res->status().code() == MetaServiceCode::OK) { |
582 | 879k | return Status::OK(); |
583 | 18.4E | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { |
584 | 9 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, |
585 | 9 | res->status().msg()); |
586 | 18.4E | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { |
587 | | // MS_BUSY should also be retried |
588 | 0 | if (rate_limit_ctx.backpressure_handler) { |
589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); |
590 | 0 | } |
591 | 18.4E | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { |
592 | 806 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, |
593 | 806 | res->status().msg()); |
594 | 18.4E | } else { |
595 | 18.4E | error_msg = res->status().msg(); |
596 | 18.4E | } |
597 | | |
598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { |
599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; |
600 | 0 | } |
601 | | |
602 | 18.4E | ++retry_times; |
603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || |
604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && |
605 | 0 | error_code == brpc::ERPCTIMEDOUT) || |
606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && |
607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { |
608 | 0 | break; |
609 | 0 | } |
610 | | |
611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); |
612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times |
613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); |
614 | 18.4E | bthread_usleep(duration_ms * 1000); |
615 | 18.4E | } |
616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); |
617 | 876k | } cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_16GetTabletRequestENS0_17GetTabletResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 355k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 355k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 355k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 355k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 355k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 355k | int retry_times = 0; | 546 | 355k | uint32_t duration_ms = 0; | 547 | 355k | std::string error_msg; | 548 | 355k | std::default_random_engine rng = make_random_engine(); | 549 | 355k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 355k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 355k | MetaServiceProxy* proxy; | 552 | 355k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 355k | while (true) { | 555 | 354k | std::shared_ptr<MetaService_Stub> stub; | 556 | 354k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 354k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 354k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 354k | brpc::Controller cntl; | 563 | 354k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 355k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 354k | } else { | 567 | 354k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 354k | } | 569 | 354k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 354k | res->Clear(); | 571 | 354k | int error_code = 0; | 572 | 354k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 354k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 354k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 354k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 354k | return Status::OK(); | 583 | 354k | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 459 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 459 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 100 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 100 | res->status().msg()); | 594 | 359 | } else { | 595 | 359 | error_msg = res->status().msg(); | 596 | 359 | } | 597 | | | 598 | 359 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 359 | ++retry_times; | 603 | 359 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 359 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 359 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 359 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 359 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 359 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 359 | bthread_usleep(duration_ms * 1000); | 615 | 359 | } | 616 | 596 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 355k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_22GetDeleteBitmapRequestENS0_23GetDeleteBitmapResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 26.1k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 26.1k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 26.1k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 26.1k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 26.1k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 26.1k | int retry_times = 0; | 546 | 26.1k | uint32_t duration_ms = 0; | 547 | 26.1k | std::string error_msg; | 548 | 26.1k | std::default_random_engine rng = make_random_engine(); | 549 | 26.1k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 26.1k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 26.1k | MetaServiceProxy* proxy; | 552 | 26.1k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 26.1k | while (true) { | 555 | 26.0k | std::shared_ptr<MetaService_Stub> stub; | 556 | 26.0k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 26.0k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 26.0k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 26.0k | brpc::Controller cntl; | 563 | 26.0k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 26.1k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 26.1k | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 18.4E | } else { | 567 | 18.4E | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 18.4E | } | 569 | 26.0k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 26.0k | res->Clear(); | 571 | 26.0k | int error_code = 0; | 572 | 26.0k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 26.0k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 26.0k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 26.1k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 26.1k | return Status::OK(); | 583 | 18.4E | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 18.4E | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 18.4E | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 18.4E | } else { | 595 | 18.4E | error_msg = res->status().msg(); | 596 | 18.4E | } | 597 | | | 598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 18.4E | ++retry_times; | 603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 18.4E | bthread_usleep(duration_ms * 1000); | 615 | 18.4E | } | 616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 26.1k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_19CreateRowsetRequestENS0_20CreateRowsetResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 384k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 384k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 384k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 384k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 384k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 384k | int retry_times = 0; | 546 | 384k | uint32_t duration_ms = 0; | 547 | 384k | std::string error_msg; | 548 | 384k | std::default_random_engine rng = make_random_engine(); | 549 | 384k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 384k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 384k | MetaServiceProxy* proxy; | 552 | 384k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 384k | while (true) { | 555 | 383k | std::shared_ptr<MetaService_Stub> stub; | 556 | 383k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 383k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 383k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 383k | brpc::Controller cntl; | 563 | 383k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 383k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 383k | } else { | 567 | 383k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 383k | } | 569 | 383k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 383k | res->Clear(); | 571 | 383k | int error_code = 0; | 572 | 383k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 383k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 383k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 386k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 386k | return Status::OK(); | 583 | 18.4E | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 18.4E | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 18.4E | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 18.4E | } else { | 595 | 18.4E | error_msg = res->status().msg(); | 596 | 18.4E | } | 597 | | | 598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 18.4E | ++retry_times; | 603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 18.4E | bthread_usleep(duration_ms * 1000); | 615 | 18.4E | } | 616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 384k | } |
Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_16CommitTxnRequestENS0_17CommitTxnResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_15AbortTxnRequestENS0_16AbortTxnResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 488 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 488 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 488 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 488 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 488 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 488 | int retry_times = 0; | 546 | 488 | uint32_t duration_ms = 0; | 547 | 488 | std::string error_msg; | 548 | 488 | std::default_random_engine rng = make_random_engine(); | 549 | 488 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 488 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 488 | MetaServiceProxy* proxy; | 552 | 488 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 488 | while (true) { | 555 | 488 | std::shared_ptr<MetaService_Stub> stub; | 556 | 488 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 488 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 488 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 488 | brpc::Controller cntl; | 563 | 488 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 488 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 488 | } else { | 567 | 488 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 488 | } | 569 | 488 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 488 | res->Clear(); | 571 | 488 | int error_code = 0; | 572 | 488 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 488 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 488 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 488 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 479 | return Status::OK(); | 583 | 479 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 9 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 9 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 9 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 9 | res->status().msg()); | 594 | 9 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 488 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_19PrecommitTxnRequestENS0_20PrecommitTxnResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 33 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 33 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 33 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 33 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 33 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 33 | int retry_times = 0; | 546 | 33 | uint32_t duration_ms = 0; | 547 | 33 | std::string error_msg; | 548 | 33 | std::default_random_engine rng = make_random_engine(); | 549 | 33 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 33 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 33 | MetaServiceProxy* proxy; | 552 | 33 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 33 | while (true) { | 555 | 33 | std::shared_ptr<MetaService_Stub> stub; | 556 | 33 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 33 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 33 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 33 | brpc::Controller cntl; | 563 | 33 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 33 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 33 | } else { | 567 | 33 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 33 | } | 569 | 33 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 33 | res->Clear(); | 571 | 33 | int error_code = 0; | 572 | 33 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 33 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 33 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 33 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 33 | return Status::OK(); | 583 | 33 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 0 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 0 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 0 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 33 | } |
Unexecuted instantiation: cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_17RestoreJobRequestENS0_18RestoreJobResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_22GetObjStoreInfoRequestENS0_23GetObjStoreInfoResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 106 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 106 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 106 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 106 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 106 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 106 | int retry_times = 0; | 546 | 106 | uint32_t duration_ms = 0; | 547 | 106 | std::string error_msg; | 548 | 106 | std::default_random_engine rng = make_random_engine(); | 549 | 106 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 106 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 106 | MetaServiceProxy* proxy; | 552 | 106 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 106 | while (true) { | 555 | 106 | std::shared_ptr<MetaService_Stub> stub; | 556 | 106 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 106 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 106 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 106 | brpc::Controller cntl; | 563 | 106 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 106 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 106 | } else { | 567 | 106 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 106 | } | 569 | 106 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 106 | res->Clear(); | 571 | 106 | int error_code = 0; | 572 | 106 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 106 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 106 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 106 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 106 | return Status::OK(); | 583 | 106 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 0 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 0 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 0 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 106 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_21StartTabletJobRequestENS0_22StartTabletJobResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 18.6k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 18.6k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 18.6k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 18.6k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 18.6k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 18.6k | int retry_times = 0; | 546 | 18.6k | uint32_t duration_ms = 0; | 547 | 18.6k | std::string error_msg; | 548 | 18.6k | std::default_random_engine rng = make_random_engine(); | 549 | 18.6k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 18.6k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 18.6k | MetaServiceProxy* proxy; | 552 | 18.6k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 18.6k | while (true) { | 555 | 18.6k | std::shared_ptr<MetaService_Stub> stub; | 556 | 18.6k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 18.6k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 18.6k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 18.6k | brpc::Controller cntl; | 563 | 18.6k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 18.7k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 18.6k | } else { | 567 | 18.6k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 18.6k | } | 569 | 18.6k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 18.6k | res->Clear(); | 571 | 18.6k | int error_code = 0; | 572 | 18.6k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 18.6k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 18.6k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 18.6k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 18.4k | return Status::OK(); | 583 | 18.4k | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 238 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 290 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 290 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 290 | res->status().msg()); | 594 | 18.4E | } else { | 595 | 18.4E | error_msg = res->status().msg(); | 596 | 18.4E | } | 597 | | | 598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 18.4E | ++retry_times; | 603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 18.4E | bthread_usleep(duration_ms * 1000); | 615 | 18.4E | } | 616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 18.6k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_22FinishTabletJobRequestENS0_23FinishTabletJobResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 17.1k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 17.1k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 17.1k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 17.1k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 17.1k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 17.1k | int retry_times = 0; | 546 | 17.1k | uint32_t duration_ms = 0; | 547 | 17.1k | std::string error_msg; | 548 | 17.1k | std::default_random_engine rng = make_random_engine(); | 549 | 17.1k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 17.1k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 17.1k | MetaServiceProxy* proxy; | 552 | 17.1k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 17.2k | while (true) { | 555 | 17.2k | std::shared_ptr<MetaService_Stub> stub; | 556 | 17.2k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 17.2k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 17.2k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 17.2k | brpc::Controller cntl; | 563 | 17.2k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 17.2k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 17.2k | } else { | 567 | 17.2k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 17.2k | } | 569 | 17.2k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 17.2k | res->Clear(); | 571 | 17.2k | int error_code = 0; | 572 | 17.2k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 17.2k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 17.2k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 17.3k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 17.3k | return Status::OK(); | 583 | 18.4E | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 9 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 9 | res->status().msg()); | 586 | 18.4E | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 18.4E | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 38 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 38 | res->status().msg()); | 594 | 18.4E | } else { | 595 | 18.4E | error_msg = res->status().msg(); | 596 | 18.4E | } | 597 | | | 598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 18.4E | ++retry_times; | 603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 18.4E | bthread_usleep(duration_ms * 1000); | 615 | 18.4E | } | 616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 17.1k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_25UpdateDeleteBitmapRequestENS0_26UpdateDeleteBitmapResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 57.7k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 57.7k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 57.7k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 57.7k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 57.7k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 57.7k | int retry_times = 0; | 546 | 57.7k | uint32_t duration_ms = 0; | 547 | 57.7k | std::string error_msg; | 548 | 57.7k | std::default_random_engine rng = make_random_engine(); | 549 | 57.7k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 57.7k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 57.7k | MetaServiceProxy* proxy; | 552 | 57.7k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 57.9k | while (true) { | 555 | 57.9k | std::shared_ptr<MetaService_Stub> stub; | 556 | 57.9k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 57.9k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 57.9k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 57.9k | brpc::Controller cntl; | 563 | 57.9k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 58.3k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 58.3k | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 18.4E | } else { | 567 | 18.4E | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 18.4E | } | 569 | 57.9k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 57.9k | res->Clear(); | 571 | 57.9k | int error_code = 0; | 572 | 57.9k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 57.9k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 57.9k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 59.4k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 59.4k | return Status::OK(); | 583 | 18.4E | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 18.4E | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 18.4E | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 18 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 18 | res->status().msg()); | 594 | 18.4E | } else { | 595 | 18.4E | error_msg = res->status().msg(); | 596 | 18.4E | } | 597 | | | 598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 18.4E | ++retry_times; | 603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 18.4E | bthread_usleep(duration_ms * 1000); | 615 | 18.4E | } | 616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 57.7k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_32GetDeleteBitmapUpdateLockRequestENS0_33GetDeleteBitmapUpdateLockResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 4.70k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 4.70k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 4.70k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 4.70k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 4.70k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 4.70k | int retry_times = 0; | 546 | 4.70k | uint32_t duration_ms = 0; | 547 | 4.70k | std::string error_msg; | 548 | 4.70k | std::default_random_engine rng = make_random_engine(); | 549 | 4.70k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 4.70k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 4.70k | MetaServiceProxy* proxy; | 552 | 4.70k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 4.70k | while (true) { | 555 | 4.70k | std::shared_ptr<MetaService_Stub> stub; | 556 | 4.70k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 4.70k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 4.70k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 4.70k | brpc::Controller cntl; | 563 | 4.70k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 4.70k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 4.70k | } else { | 567 | 4.70k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 4.70k | } | 569 | 4.70k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 4.70k | res->Clear(); | 571 | 4.70k | int error_code = 0; | 572 | 4.70k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 4.70k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 4.70k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 4.70k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 4.39k | return Status::OK(); | 583 | 4.39k | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 312 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 313 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 313 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 313 | res->status().msg()); | 594 | 18.4E | } else { | 595 | 18.4E | error_msg = res->status().msg(); | 596 | 18.4E | } | 597 | | | 598 | 18.4E | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | | | 602 | 18.4E | ++retry_times; | 603 | 18.4E | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 18.4E | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 18.4E | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 18.4E | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 18.4E | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 18.4E | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 18.4E | bthread_usleep(duration_ms * 1000); | 615 | 18.4E | } | 616 | 18.4E | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 4.70k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_35RemoveDeleteBitmapUpdateLockRequestENS0_36RemoveDeleteBitmapUpdateLockResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 36 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 36 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 36 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 36 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 36 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 36 | int retry_times = 0; | 546 | 36 | uint32_t duration_ms = 0; | 547 | 36 | std::string error_msg; | 548 | 36 | std::default_random_engine rng = make_random_engine(); | 549 | 36 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 36 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 36 | MetaServiceProxy* proxy; | 552 | 36 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 36 | while (true) { | 555 | 36 | std::shared_ptr<MetaService_Stub> stub; | 556 | 36 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 36 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 36 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 36 | brpc::Controller cntl; | 563 | 36 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 36 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 36 | } else { | 567 | 36 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 36 | } | 569 | 36 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 36 | res->Clear(); | 571 | 36 | int error_code = 0; | 572 | 36 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 36 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 36 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 36 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 0 | return Status::OK(); | 583 | 36 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 36 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 36 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 36 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 36 | res->status().msg()); | 594 | 36 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 36 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_19ListSnapshotRequestENS0_20ListSnapshotResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 2 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 2 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 2 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 2 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 2 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 2 | int retry_times = 0; | 546 | 2 | uint32_t duration_ms = 0; | 547 | 2 | std::string error_msg; | 548 | 2 | std::default_random_engine rng = make_random_engine(); | 549 | 2 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 2 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 2 | MetaServiceProxy* proxy; | 552 | 2 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 2 | while (true) { | 555 | 2 | std::shared_ptr<MetaService_Stub> stub; | 556 | 2 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 2 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 2 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 2 | brpc::Controller cntl; | 563 | 2 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 2 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 2 | } else { | 567 | 2 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 2 | } | 569 | 2 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 2 | res->Clear(); | 571 | 2 | int error_code = 0; | 572 | 2 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 2 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 2 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 2 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 0 | return Status::OK(); | 583 | 2 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 2 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 2 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 2 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 2 | res->status().msg()); | 594 | 2 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 2 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_18GetInstanceRequestENS0_19GetInstanceResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 1 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 1 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 1 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 1 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 1 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 1 | int retry_times = 0; | 546 | 1 | uint32_t duration_ms = 0; | 547 | 1 | std::string error_msg; | 548 | 1 | std::default_random_engine rng = make_random_engine(); | 549 | 1 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 1 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 1 | MetaServiceProxy* proxy; | 552 | 1 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 1 | while (true) { | 555 | 1 | std::shared_ptr<MetaService_Stub> stub; | 556 | 1 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 1 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 1 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 1 | brpc::Controller cntl; | 563 | 1 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 1 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 1 | } else { | 567 | 1 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 1 | } | 569 | 1 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 1 | res->Clear(); | 571 | 1 | int error_code = 0; | 572 | 1 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 1 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 1 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 1 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 1 | return Status::OK(); | 583 | 1 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 0 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 0 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 0 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 1 | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_27UpdatePackedFileInfoRequestENS0_28UpdatePackedFileInfoResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 12.1k | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 12.1k | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 12.1k | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 12.1k | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 12.1k | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 12.1k | int retry_times = 0; | 546 | 12.1k | uint32_t duration_ms = 0; | 547 | 12.1k | std::string error_msg; | 548 | 12.1k | std::default_random_engine rng = make_random_engine(); | 549 | 12.1k | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 12.1k | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 12.1k | MetaServiceProxy* proxy; | 552 | 12.1k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 12.1k | while (true) { | 555 | 12.1k | std::shared_ptr<MetaService_Stub> stub; | 556 | 12.1k | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 12.1k | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 12.1k | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 12.1k | brpc::Controller cntl; | 563 | 12.1k | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 12.1k | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 12.1k | } else { | 567 | 12.1k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 12.1k | } | 569 | 12.1k | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 12.1k | res->Clear(); | 571 | 12.1k | int error_code = 0; | 572 | 12.1k | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 12.1k | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 12.1k | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 12.1k | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 12.1k | return Status::OK(); | 583 | 12.1k | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 0 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 0 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 0 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 12.1k | } |
cloud_meta_mgr.cpp:_ZN5doris5cloud12_GLOBAL__N_19retry_rpcINS0_23GetClusterStatusRequestENS0_24GetClusterStatusResponseEEENS_6StatusENS0_14MetaServiceRPCERKT_PT0_MNS0_16MetaService_StubEFvPN6google8protobuf13RpcControllerEPS8_SB_PNSE_7ClosureEERKNS1_15RpcRateLimitCtxE Line | Count | Source | 536 | 56 | const RpcRateLimitCtx& rate_limit_ctx = {}) { | 537 | 56 | static_assert(std::is_base_of_v<::google::protobuf::Message, Request>); | 538 | 56 | static_assert(std::is_base_of_v<::google::protobuf::Message, Response>); | 539 | | | 540 | 56 | std::string_view op_name = meta_service_rpc_display_name(rpc); | 541 | | | 542 | | // Applies only to the current file, and all req are non-const, but passed as const types. | 543 | 56 | const_cast<Request&>(req).set_request_ip(BackendOptions::get_be_endpoint()); | 544 | | | 545 | 56 | int retry_times = 0; | 546 | 56 | uint32_t duration_ms = 0; | 547 | 56 | std::string error_msg; | 548 | 56 | std::default_random_engine rng = make_random_engine(); | 549 | 56 | std::uniform_int_distribution<uint32_t> u(20, 200); | 550 | 56 | std::uniform_int_distribution<uint32_t> u2(500, 1000); | 551 | 56 | MetaServiceProxy* proxy; | 552 | 56 | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); | 553 | | | 554 | 56 | while (true) { | 555 | 56 | std::shared_ptr<MetaService_Stub> stub; | 556 | 56 | RETURN_IF_ERROR(proxy->get(&stub)); | 557 | | | 558 | | // Apply rate limiting (both host-level and table-level) | 559 | 56 | apply_rate_limit(rpc, rate_limit_ctx); | 560 | 56 | TEST_SYNC_POINT_CALLBACK("retry_rpc::after_rate_limit", &rpc); | 561 | | | 562 | 56 | brpc::Controller cntl; | 563 | 56 | if (rpc == MetaServiceRPC::GET_DELETE_BITMAP || | 564 | 56 | rpc == MetaServiceRPC::UPDATE_DELETE_BITMAP) { | 565 | 0 | cntl.set_timeout_ms(3 * config::meta_service_brpc_timeout_ms); | 566 | 56 | } else { | 567 | 56 | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); | 568 | 56 | } | 569 | 56 | cntl.set_max_retry(kBrpcRetryTimes); | 570 | 56 | res->Clear(); | 571 | 56 | int error_code = 0; | 572 | 56 | call_ms(stub.get(), method, &cntl, req, res); | 573 | | | 574 | | // Record QPS statistics for all RPCs sent to MS (success or failure) | 575 | 56 | record_rpc_qps(rpc, rate_limit_ctx); | 576 | | | 577 | 56 | if (cntl.Failed()) [[unlikely]] { | 578 | 0 | error_msg = cntl.ErrorText(); | 579 | 0 | error_code = cntl.ErrorCode(); | 580 | 0 | proxy->set_unhealthy(); | 581 | 56 | } else if (res->status().code() == MetaServiceCode::OK) { | 582 | 56 | return Status::OK(); | 583 | 56 | } else if (res->status().code() == MetaServiceCode::INVALID_ARGUMENT) { | 584 | 0 | return Status::Error<ErrorCode::INVALID_ARGUMENT, false>("failed to {}: {}", op_name, | 585 | 0 | res->status().msg()); | 586 | 0 | } else if (res->status().code() == MetaServiceCode::MS_TOO_BUSY) { | 587 | | // MS_BUSY should also be retried | 588 | 0 | if (rate_limit_ctx.backpressure_handler) { | 589 | 0 | rate_limit_ctx.backpressure_handler->on_ms_busy(); | 590 | 0 | } | 591 | 0 | } else if (res->status().code() != MetaServiceCode::KV_TXN_CONFLICT) { | 592 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to {}: {}", op_name, | 593 | 0 | res->status().msg()); | 594 | 0 | } else { | 595 | 0 | error_msg = res->status().msg(); | 596 | 0 | } | 597 | | | 598 | 0 | if (error_code == brpc::ERPCTIMEDOUT) { | 599 | 0 | g_cloud_meta_mgr_rpc_timeout_count << 1; | 600 | 0 | } | 601 | |
| 602 | 0 | ++retry_times; | 603 | 0 | if (retry_times > config::meta_service_rpc_retry_times || | 604 | 0 | (retry_times > config::meta_service_rpc_timeout_retry_times && | 605 | 0 | error_code == brpc::ERPCTIMEDOUT) || | 606 | 0 | (retry_times > config::meta_service_conflict_error_retry_times && | 607 | 0 | res->status().code() == MetaServiceCode::KV_TXN_CONFLICT)) { | 608 | 0 | break; | 609 | 0 | } | 610 | | | 611 | 0 | duration_ms = retry_times <= 100 ? u(rng) : u2(rng); | 612 | 0 | LOG(WARNING) << "failed to " << op_name << debug_info(req) << " retry_times=" << retry_times | 613 | 0 | << " sleep=" << duration_ms << "ms : " << cntl.ErrorText(); | 614 | 0 | bthread_usleep(duration_ms * 1000); | 615 | 0 | } | 616 | 0 | return Status::RpcError("failed to {}: rpc timeout, last msg={}", op_name, error_msg); | 617 | 56 | } |
|
618 | | |
619 | | } // namespace |
620 | | |
621 | 355k | Status CloudMetaMgr::get_tablet_meta(int64_t tablet_id, TabletMetaSharedPtr* tablet_meta) { |
622 | 18.4E | VLOG_DEBUG << "send GetTabletRequest, tablet_id: " << tablet_id; |
623 | 355k | TEST_SYNC_POINT_RETURN_WITH_VALUE("CloudMetaMgr::get_tablet_meta", Status::OK(), tablet_id, |
624 | 355k | tablet_meta); |
625 | 355k | GetTabletRequest req; |
626 | 355k | GetTabletResponse resp; |
627 | 355k | req.set_cloud_unique_id(config::cloud_unique_id); |
628 | 355k | req.set_tablet_id(tablet_id); |
629 | 355k | Status st = |
630 | 355k | retry_rpc(MetaServiceRPC::GET_TABLET_META, req, &resp, &MetaService_Stub::get_tablet, |
631 | 355k | { |
632 | 355k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
633 | 355k | .backpressure_handler = ms_backpressure_handler_, |
634 | 355k | }); |
635 | 355k | if (!st.ok()) { |
636 | 100 | if (resp.status().code() == MetaServiceCode::TABLET_NOT_FOUND) { |
637 | 100 | return Status::NotFound("failed to get tablet meta: {}", resp.status().msg()); |
638 | 100 | } |
639 | 0 | return st; |
640 | 100 | } |
641 | | |
642 | 355k | *tablet_meta = std::make_shared<TabletMeta>(); |
643 | 355k | (*tablet_meta) |
644 | 355k | ->init_from_pb(cloud_tablet_meta_to_doris(std::move(*resp.mutable_tablet_meta()))); |
645 | 355k | VLOG_DEBUG << "get tablet meta, tablet_id: " << (*tablet_meta)->tablet_id(); |
646 | 355k | return Status::OK(); |
647 | 355k | } |
648 | | |
649 | | Status CloudMetaMgr::sync_tablet_rowsets(CloudTablet* tablet, const SyncOptions& options, |
650 | 126k | SyncRowsetStats* sync_stats) { |
651 | 126k | std::unique_lock lock {tablet->get_sync_meta_lock()}; |
652 | 126k | return sync_tablet_rowsets_unlocked(tablet, lock, options, sync_stats); |
653 | 126k | } |
654 | | |
655 | | Status CloudMetaMgr::_log_mow_delete_bitmap(CloudTablet* tablet, GetRowsetResponse& resp, |
656 | | DeleteBitmap& delete_bitmap, int64_t old_max_version, |
657 | 39.8k | bool full_sync, int32_t read_version) { |
658 | 39.8k | if (config::enable_mow_verbose_log && !resp.rowset_meta().empty() && |
659 | 39.8k | delete_bitmap.cardinality() > 0) { |
660 | 0 | int64_t tablet_id = tablet->tablet_id(); |
661 | 0 | std::vector<std::string> new_rowset_msgs; |
662 | 0 | std::vector<std::string> old_rowset_msgs; |
663 | 0 | std::unordered_set<RowsetId> new_rowset_ids; |
664 | 0 | int64_t new_max_version = resp.rowset_meta().rbegin()->end_version(); |
665 | 0 | for (const auto& rs : resp.rowset_meta()) { |
666 | 0 | RowsetId rowset_id; |
667 | 0 | rowset_id.init(rs.rowset_id_v2()); |
668 | 0 | new_rowset_ids.insert(rowset_id); |
669 | 0 | DeleteBitmap rowset_dbm(tablet_id); |
670 | 0 | delete_bitmap.subset({rowset_id, 0, 0}, |
671 | 0 | {rowset_id, std::numeric_limits<DeleteBitmap::SegmentId>::max(), |
672 | 0 | std::numeric_limits<DeleteBitmap::Version>::max()}, |
673 | 0 | &rowset_dbm); |
674 | 0 | size_t cardinality = rowset_dbm.cardinality(); |
675 | 0 | size_t count = rowset_dbm.get_delete_bitmap_count(); |
676 | 0 | if (cardinality > 0) { |
677 | 0 | new_rowset_msgs.push_back(fmt::format("({}[{}-{}],{},{})", rs.rowset_id_v2(), |
678 | 0 | rs.start_version(), rs.end_version(), count, |
679 | 0 | cardinality)); |
680 | 0 | } |
681 | 0 | } |
682 | |
|
683 | 0 | if (old_max_version > 0) { |
684 | 0 | std::vector<RowsetSharedPtr> old_rowsets; |
685 | 0 | RowsetIdUnorderedSet old_rowset_ids; |
686 | 0 | { |
687 | 0 | std::lock_guard rlock(tablet->get_header_lock()); |
688 | 0 | RETURN_IF_ERROR(tablet->get_all_rs_id_unlocked(old_max_version, &old_rowset_ids)); |
689 | 0 | old_rowsets = tablet->get_rowset_by_ids(&old_rowset_ids); |
690 | 0 | } |
691 | 0 | for (const auto& rs : old_rowsets) { |
692 | 0 | if (!new_rowset_ids.contains(rs->rowset_id())) { |
693 | 0 | DeleteBitmap rowset_dbm(tablet_id); |
694 | 0 | delete_bitmap.subset( |
695 | 0 | {rs->rowset_id(), 0, 0}, |
696 | 0 | {rs->rowset_id(), std::numeric_limits<DeleteBitmap::SegmentId>::max(), |
697 | 0 | std::numeric_limits<DeleteBitmap::Version>::max()}, |
698 | 0 | &rowset_dbm); |
699 | 0 | size_t cardinality = rowset_dbm.cardinality(); |
700 | 0 | size_t count = rowset_dbm.get_delete_bitmap_count(); |
701 | 0 | if (cardinality > 0) { |
702 | 0 | old_rowset_msgs.push_back( |
703 | 0 | fmt::format("({}{},{},{})", rs->rowset_id().to_string(), |
704 | 0 | rs->version().to_string(), count, cardinality)); |
705 | 0 | } |
706 | 0 | } |
707 | 0 | } |
708 | 0 | } |
709 | | |
710 | 0 | std::string tablet_info = fmt::format( |
711 | 0 | "tablet_id={} table_id={} index_id={} partition_id={}", tablet->tablet_id(), |
712 | 0 | tablet->table_id(), tablet->index_id(), tablet->partition_id()); |
713 | 0 | LOG_INFO("[verbose] sync tablet delete bitmap " + tablet_info) |
714 | 0 | .tag("full_sync", full_sync) |
715 | 0 | .tag("read_version", read_version) |
716 | 0 | .tag("old_max_version", old_max_version) |
717 | 0 | .tag("new_max_version", new_max_version) |
718 | 0 | .tag("cumu_compaction_cnt", resp.stats().cumulative_compaction_cnt()) |
719 | 0 | .tag("base_compaction_cnt", resp.stats().base_compaction_cnt()) |
720 | 0 | .tag("cumu_point", resp.stats().cumulative_point()) |
721 | 0 | .tag("rowset_num", resp.rowset_meta().size()) |
722 | 0 | .tag("delete_bitmap_cardinality", delete_bitmap.cardinality()) |
723 | 0 | .tag("old_rowsets(rowset,count,cardinality)", |
724 | 0 | fmt::format("[{}]", fmt::join(old_rowset_msgs, ", "))) |
725 | 0 | .tag("new_rowsets(rowset,count,cardinality)", |
726 | 0 | fmt::format("[{}]", fmt::join(new_rowset_msgs, ", "))); |
727 | 0 | } |
728 | 39.8k | return Status::OK(); |
729 | 39.8k | } |
730 | | |
731 | | Status CloudMetaMgr::sync_tablet_rowsets_unlocked(CloudTablet* tablet, |
732 | | std::unique_lock<bthread::Mutex>& lock, |
733 | | const SyncOptions& options, |
734 | 173k | SyncRowsetStats* sync_stats) { |
735 | 173k | using namespace std::chrono; |
736 | | |
737 | 173k | TEST_SYNC_POINT_RETURN_WITH_VALUE("CloudMetaMgr::sync_tablet_rowsets", Status::OK(), tablet); |
738 | 173k | DBUG_EXECUTE_IF("CloudMetaMgr::sync_tablet_rowsets.before.inject_error", { |
739 | 173k | auto target_tablet_id = dp->param<int64_t>("tablet_id", -1); |
740 | 173k | auto target_table_id = dp->param<int64_t>("table_id", -1); |
741 | 173k | if (target_tablet_id == tablet->tablet_id() || target_table_id == tablet->table_id()) { |
742 | 173k | return Status::InternalError( |
743 | 173k | "[sync_tablet_rowsets_unlocked] injected error for testing"); |
744 | 173k | } |
745 | 173k | }); |
746 | | |
747 | 173k | MetaServiceProxy* proxy; |
748 | 173k | RETURN_IF_ERROR(MetaServiceProxy::get_proxy(&proxy)); |
749 | 173k | std::string tablet_info = |
750 | 173k | fmt::format("tablet_id={} table_id={} index_id={} partition_id={}", tablet->tablet_id(), |
751 | 173k | tablet->table_id(), tablet->index_id(), tablet->partition_id()); |
752 | 173k | int tried = 0; |
753 | 173k | while (true) { |
754 | 172k | std::shared_ptr<MetaService_Stub> stub; |
755 | 172k | RETURN_IF_ERROR(proxy->get(&stub)); |
756 | 172k | brpc::Controller cntl; |
757 | 172k | cntl.set_timeout_ms(config::meta_service_brpc_timeout_ms); |
758 | 172k | GetRowsetRequest req; |
759 | 172k | GetRowsetResponse resp; |
760 | | |
761 | 172k | int64_t tablet_id = tablet->tablet_id(); |
762 | 172k | int64_t table_id = tablet->table_id(); |
763 | 172k | int64_t index_id = tablet->index_id(); |
764 | 172k | req.set_cloud_unique_id(config::cloud_unique_id); |
765 | 172k | auto* idx = req.mutable_idx(); |
766 | 172k | idx->set_tablet_id(tablet_id); |
767 | 172k | idx->set_table_id(table_id); |
768 | 172k | idx->set_index_id(index_id); |
769 | 172k | idx->set_partition_id(tablet->partition_id()); |
770 | 172k | { |
771 | 172k | auto lock_start = std::chrono::steady_clock::now(); |
772 | 172k | std::shared_lock rlock(tablet->get_header_lock()); |
773 | 172k | if (sync_stats) { |
774 | 14.4k | sync_stats->meta_lock_wait_ns += |
775 | 14.4k | std::chrono::duration_cast<std::chrono::nanoseconds>( |
776 | 14.4k | std::chrono::steady_clock::now() - lock_start) |
777 | 14.4k | .count(); |
778 | 14.4k | } |
779 | 172k | if (options.full_sync) { |
780 | 2 | req.set_start_version(0); |
781 | 172k | } else { |
782 | 172k | req.set_start_version(tablet->max_version_unlocked() + 1); |
783 | 172k | } |
784 | 172k | req.set_base_compaction_cnt(tablet->base_compaction_cnt()); |
785 | 172k | req.set_cumulative_compaction_cnt(tablet->cumulative_compaction_cnt()); |
786 | 172k | req.set_full_compaction_cnt(tablet->full_compaction_cnt()); |
787 | 172k | req.set_cumulative_point(tablet->cumulative_layer_point()); |
788 | 172k | } |
789 | 172k | req.set_end_version(-1); |
790 | 172k | VLOG_DEBUG << "send GetRowsetRequest: " << req.ShortDebugString(); |
791 | | |
792 | | // Host-level rate limiting for get_rowset |
793 | 172k | if (host_level_ms_rpc_rate_limiters_) { |
794 | 172k | host_level_ms_rpc_rate_limiters_->limit(MetaServiceRPC::GET_ROWSET); |
795 | 172k | } |
796 | | |
797 | 172k | auto start = std::chrono::steady_clock::now(); |
798 | 172k | call_ms(stub.get(), &MetaService_Stub::get_rowset, &cntl, req, &resp); |
799 | 172k | auto end = std::chrono::steady_clock::now(); |
800 | 172k | int64_t latency = cntl.latency_us(); |
801 | 172k | _get_rowset_latency << latency; |
802 | 172k | int retry_times = config::meta_service_rpc_retry_times; |
803 | 172k | if (cntl.Failed()) { |
804 | 0 | proxy->set_unhealthy(); |
805 | 0 | if (tried++ < retry_times) { |
806 | 0 | auto rng = make_random_engine(); |
807 | 0 | std::uniform_int_distribution<uint32_t> u(20, 200); |
808 | 0 | std::uniform_int_distribution<uint32_t> u1(500, 1000); |
809 | 0 | uint32_t duration_ms = tried >= 100 ? u(rng) : u1(rng); |
810 | 0 | bthread_usleep(duration_ms * 1000); |
811 | 0 | LOG_INFO("failed to get rowset meta, " + tablet_info) |
812 | 0 | .tag("reason", cntl.ErrorText()) |
813 | 0 | .tag("tried", tried) |
814 | 0 | .tag("sleep", duration_ms); |
815 | 0 | continue; |
816 | 0 | } |
817 | 0 | return Status::RpcError("failed to get rowset meta: {}", cntl.ErrorText()); |
818 | 0 | } |
819 | 172k | if (resp.status().code() == MetaServiceCode::TABLET_NOT_FOUND) { |
820 | 0 | LOG(WARNING) << "failed to get rowset meta, err=" << resp.status().msg() << " " |
821 | 0 | << tablet_info; |
822 | 0 | return Status::NotFound("failed to get rowset meta: {}, {}", resp.status().msg(), |
823 | 0 | tablet_info); |
824 | 0 | } |
825 | 172k | if (resp.status().code() == MetaServiceCode::MS_TOO_BUSY) { |
826 | | // MS_BUSY should also be retried |
827 | 0 | if (ms_backpressure_handler_) { |
828 | 0 | ms_backpressure_handler_->on_ms_busy(); |
829 | 0 | } |
830 | 0 | if (tried++ < retry_times) { |
831 | 0 | auto rng = make_random_engine(); |
832 | 0 | std::uniform_int_distribution<uint32_t> u(20, 200); |
833 | 0 | std::uniform_int_distribution<uint32_t> u1(500, 1000); |
834 | 0 | uint32_t duration_ms = tried >= 100 ? u(rng) : u1(rng); |
835 | 0 | bthread_usleep(duration_ms * 1000); |
836 | 0 | LOG_INFO("meta service is too busy when getting rowset meta, " + tablet_info) |
837 | 0 | .tag("reason", resp.status().msg()) |
838 | 0 | .tag("tried", tried) |
839 | 0 | .tag("sleep", duration_ms); |
840 | 0 | continue; |
841 | 0 | } |
842 | 0 | return Status::RpcError("failed to get rowset meta: {}", resp.status().msg()); |
843 | 0 | } |
844 | 172k | if (resp.status().code() != MetaServiceCode::OK) { |
845 | 0 | LOG(WARNING) << " failed to get rowset meta, err=" << resp.status().msg() << " " |
846 | 0 | << tablet_info; |
847 | 0 | return Status::InternalError("failed to get rowset meta: {}, {}", resp.status().msg(), |
848 | 0 | tablet_info); |
849 | 0 | } |
850 | 172k | if (latency > 100 * 1000) { // 100ms |
851 | 32 | LOG(INFO) << "finish get_rowset rpc. rowset_meta.size()=" << resp.rowset_meta().size() |
852 | 32 | << ", latency=" << latency << "us" |
853 | 32 | << " " << tablet_info; |
854 | 172k | } else { |
855 | 172k | LOG_EVERY_N(INFO, 100) |
856 | 1.72k | << "finish get_rowset rpc. rowset_meta.size()=" << resp.rowset_meta().size() |
857 | 1.72k | << ", latency=" << latency << "us" |
858 | 1.72k | << " " << tablet_info; |
859 | 172k | } |
860 | | |
861 | 172k | int64_t now = duration_cast<seconds>(system_clock::now().time_since_epoch()).count(); |
862 | 172k | tablet->last_sync_time_s = now; |
863 | | |
864 | 172k | if (sync_stats) { |
865 | 14.5k | sync_stats->get_remote_rowsets_rpc_ns += |
866 | 14.5k | std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(); |
867 | 14.5k | sync_stats->get_remote_rowsets_num += resp.rowset_meta().size(); |
868 | 14.5k | } |
869 | | |
870 | | // If is mow, the tablet has no delete bitmap in base rowsets. |
871 | | // So dont need to sync it. |
872 | 173k | if (options.sync_delete_bitmap && tablet->enable_unique_key_merge_on_write() && |
873 | 172k | tablet->tablet_state() == TABLET_RUNNING) { |
874 | 39.8k | DBUG_EXECUTE_IF("CloudMetaMgr::sync_tablet_rowsets.sync_tablet_delete_bitmap.block", |
875 | 39.8k | DBUG_BLOCK); |
876 | 39.8k | DeleteBitmap delete_bitmap(tablet_id); |
877 | 39.8k | int64_t old_max_version = req.start_version() - 1; |
878 | 39.8k | auto read_version = config::delete_bitmap_store_read_version; |
879 | 39.8k | auto st = sync_tablet_delete_bitmap(tablet, old_max_version, resp.rowset_meta(), |
880 | 39.8k | resp.stats(), req.idx(), &delete_bitmap, |
881 | 39.8k | options.full_sync, sync_stats, read_version, false); |
882 | 39.8k | if (st.is<ErrorCode::ROWSETS_EXPIRED>() && tried++ < retry_times) { |
883 | 0 | LOG_INFO("rowset meta is expired, need to retry, " + tablet_info) |
884 | 0 | .tag("tried", tried) |
885 | 0 | .error(st); |
886 | 0 | continue; |
887 | 0 | } |
888 | 39.8k | if (!st.ok()) { |
889 | 0 | LOG_WARNING("failed to get delete bitmap, " + tablet_info).error(st); |
890 | 0 | return st; |
891 | 0 | } |
892 | 39.8k | tablet->tablet_meta()->delete_bitmap().merge(delete_bitmap); |
893 | 39.8k | RETURN_IF_ERROR(_log_mow_delete_bitmap(tablet, resp, delete_bitmap, old_max_version, |
894 | 39.8k | options.full_sync, read_version)); |
895 | 39.8k | RETURN_IF_ERROR( |
896 | 39.8k | _check_delete_bitmap_v2_correctness(tablet, req, resp, old_max_version)); |
897 | 39.8k | } |
898 | 172k | DBUG_EXECUTE_IF("CloudMetaMgr::sync_tablet_rowsets.before.modify_tablet_meta", { |
899 | 172k | auto target_tablet_id = dp->param<int64_t>("tablet_id", -1); |
900 | 172k | if (target_tablet_id == tablet->tablet_id()) { |
901 | 172k | DBUG_BLOCK |
902 | 172k | } |
903 | 172k | }); |
904 | 172k | { |
905 | 172k | const auto& stats = resp.stats(); |
906 | 172k | auto lock_start = std::chrono::steady_clock::now(); |
907 | 172k | std::unique_lock wlock(tablet->get_header_lock()); |
908 | 172k | if (sync_stats) { |
909 | 14.5k | sync_stats->meta_lock_wait_ns += |
910 | 14.5k | std::chrono::duration_cast<std::chrono::nanoseconds>( |
911 | 14.5k | std::chrono::steady_clock::now() - lock_start) |
912 | 14.5k | .count(); |
913 | 14.5k | } |
914 | | |
915 | | // ATTN: we are facing following data race |
916 | | // |
917 | | // resp_base_compaction_cnt=0|base_compaction_cnt=0|resp_cumulative_compaction_cnt=0|cumulative_compaction_cnt=1|resp_max_version=11|max_version=8 |
918 | | // |
919 | | // BE-compaction-thread meta-service BE-query-thread |
920 | | // | | | |
921 | | // local | commit cumu-compaction | | |
922 | | // cc_cnt=0 | ---------------------------> | sync rowset (long rpc, local cc_cnt=0 ) | local |
923 | | // | | <----------------------------------------- | cc_cnt=0 |
924 | | // | | -. | |
925 | | // local | done cc_cnt=1 | \ | |
926 | | // cc_cnt=1 | <--------------------------- | \ | |
927 | | // | | \ returned with resp cc_cnt=0 (snapshot) | |
928 | | // | | '------------------------------------> | local |
929 | | // | | | cc_cnt=1 |
930 | | // | | | |
931 | | // | | | CHECK FAIL |
932 | | // | | | need retry |
933 | | // To get rid of just retry syncing tablet |
934 | 172k | if (stats.base_compaction_cnt() < tablet->base_compaction_cnt() || |
935 | 173k | stats.cumulative_compaction_cnt() < tablet->cumulative_compaction_cnt()) |
936 | 1 | [[unlikely]] { |
937 | | // stale request, ignore |
938 | 1 | LOG_WARNING("stale get rowset meta request " + tablet_info) |
939 | 1 | .tag("resp_base_compaction_cnt", stats.base_compaction_cnt()) |
940 | 1 | .tag("base_compaction_cnt", tablet->base_compaction_cnt()) |
941 | 1 | .tag("resp_cumulative_compaction_cnt", stats.cumulative_compaction_cnt()) |
942 | 1 | .tag("cumulative_compaction_cnt", tablet->cumulative_compaction_cnt()) |
943 | 1 | .tag("tried", tried); |
944 | 1 | if (tried++ < 10) continue; |
945 | 0 | return Status::OK(); |
946 | 1 | } |
947 | 172k | std::vector<RowsetSharedPtr> rowsets; |
948 | 172k | rowsets.reserve(resp.rowset_meta().size()); |
949 | 172k | for (const auto& cloud_rs_meta_pb : resp.rowset_meta()) { |
950 | 130k | VLOG_DEBUG << "get rowset meta, tablet_id=" << cloud_rs_meta_pb.tablet_id() |
951 | 124 | << ", version=[" << cloud_rs_meta_pb.start_version() << '-' |
952 | 124 | << cloud_rs_meta_pb.end_version() << ']'; |
953 | 130k | auto existed_rowset = tablet->get_rowset_by_version( |
954 | 130k | {cloud_rs_meta_pb.start_version(), cloud_rs_meta_pb.end_version()}); |
955 | 130k | if (existed_rowset && |
956 | 130k | existed_rowset->rowset_id().to_string() == cloud_rs_meta_pb.rowset_id_v2()) { |
957 | 4 | continue; // Same rowset, skip it |
958 | 4 | } |
959 | 130k | RowsetMetaPB meta_pb = cloud_rowset_meta_to_doris(cloud_rs_meta_pb); |
960 | 130k | auto rs_meta = std::make_shared<RowsetMeta>(); |
961 | 130k | rs_meta->init_from_pb(meta_pb); |
962 | 130k | RowsetSharedPtr rowset; |
963 | | // schema is nullptr implies using RowsetMeta.tablet_schema |
964 | 130k | Status s = RowsetFactory::create_rowset(nullptr, "", rs_meta, &rowset); |
965 | 130k | if (!s.ok()) { |
966 | 0 | LOG_WARNING("create rowset").tag("status", s); |
967 | 0 | return s; |
968 | 0 | } |
969 | 130k | rowsets.push_back(std::move(rowset)); |
970 | 130k | } |
971 | 172k | if (!rowsets.empty()) { |
972 | | // `rowsets.empty()` could happen after doing EMPTY_CUMULATIVE compaction. e.g.: |
973 | | // BE has [0-1][2-11][12-12], [12-12] is delete predicate, cp is 2; |
974 | | // after doing EMPTY_CUMULATIVE compaction, MS cp is 13, get_rowset will return [2-11][12-12]. |
975 | 119k | bool version_overlap = |
976 | 119k | tablet->max_version_unlocked() >= rowsets.front()->start_version(); |
977 | 119k | tablet->add_rowsets(std::move(rowsets), version_overlap, wlock, |
978 | 119k | options.warmup_delta_data || |
979 | 119k | config::enable_warmup_immediately_on_new_rowset); |
980 | 119k | } |
981 | | |
982 | | // Fill version holes |
983 | 172k | int64_t partition_max_version = |
984 | 172k | resp.has_partition_max_version() ? resp.partition_max_version() : -1; |
985 | 172k | RETURN_IF_ERROR(fill_version_holes(tablet, partition_max_version, wlock)); |
986 | | |
987 | 172k | tablet->last_base_compaction_success_time_ms = stats.last_base_compaction_time_ms(); |
988 | 172k | tablet->last_cumu_compaction_success_time_ms = stats.last_cumu_compaction_time_ms(); |
989 | 172k | tablet->set_base_compaction_cnt(stats.base_compaction_cnt()); |
990 | 172k | tablet->set_cumulative_compaction_cnt(stats.cumulative_compaction_cnt()); |
991 | 172k | tablet->set_full_compaction_cnt(stats.full_compaction_cnt()); |
992 | 172k | tablet->set_cumulative_layer_point(stats.cumulative_point()); |
993 | 172k | tablet->reset_approximate_stats(stats.num_rowsets(), stats.num_segments(), |
994 | 172k | stats.num_rows(), stats.data_size()); |
995 | | |
996 | | // Sync last active cluster info for compaction read-write separation |
997 | 172k | if (config::enable_compaction_rw_separation && stats.has_last_active_cluster_id()) { |
998 | 14.1k | tablet->set_last_active_cluster_info(stats.last_active_cluster_id(), |
999 | 14.1k | stats.last_active_time_ms()); |
1000 | 14.1k | } |
1001 | 172k | } |
1002 | 0 | return Status::OK(); |
1003 | 172k | } |
1004 | 173k | } |
1005 | | |
1006 | | bool CloudMetaMgr::sync_tablet_delete_bitmap_by_cache(CloudTablet* tablet, |
1007 | | std::ranges::range auto&& rs_metas, |
1008 | 26.3k | DeleteBitmap* delete_bitmap) { |
1009 | 26.3k | std::set<int64_t> txn_processed; |
1010 | 26.4k | for (auto& rs_meta : rs_metas) { |
1011 | 26.4k | auto txn_id = rs_meta.txn_id(); |
1012 | 26.4k | if (txn_processed.find(txn_id) != txn_processed.end()) { |
1013 | 0 | continue; |
1014 | 0 | } |
1015 | 26.4k | txn_processed.insert(txn_id); |
1016 | 26.4k | DeleteBitmapPtr tmp_delete_bitmap; |
1017 | 26.4k | std::shared_ptr<PublishStatus> publish_status = |
1018 | 26.4k | std::make_shared<PublishStatus>(PublishStatus::INIT); |
1019 | 26.4k | CloudStorageEngine& engine = ExecEnv::GetInstance()->storage_engine().to_cloud(); |
1020 | 26.4k | Status status = engine.txn_delete_bitmap_cache().get_delete_bitmap( |
1021 | 26.4k | txn_id, tablet->tablet_id(), &tmp_delete_bitmap, nullptr, &publish_status); |
1022 | | // CloudMetaMgr::sync_tablet_delete_bitmap_by_cache() is called after we sync rowsets from meta services. |
1023 | | // If the control flows reaches here, it's gauranteed that the rowsets is commited in meta services, so we can |
1024 | | // use the delete bitmap from cache directly if *publish_status == PublishStatus::SUCCEED without checking other |
1025 | | // stats(version or compaction stats) |
1026 | 26.4k | if (status.ok() && *publish_status == PublishStatus::SUCCEED) { |
1027 | | // tmp_delete_bitmap contains sentinel marks, we should remove it before merge it to delete bitmap. |
1028 | | // Also, the version of delete bitmap key in tmp_delete_bitmap is DeleteBitmap::TEMP_VERSION_COMMON, |
1029 | | // we should replace it with the rowset's real version |
1030 | 636 | DCHECK(rs_meta.start_version() == rs_meta.end_version()); |
1031 | 636 | int64_t rowset_version = rs_meta.start_version(); |
1032 | 2.62k | for (const auto& [delete_bitmap_key, bitmap_value] : tmp_delete_bitmap->delete_bitmap) { |
1033 | | // skip sentinel mark, which is used for delete bitmap correctness check |
1034 | 2.62k | if (std::get<1>(delete_bitmap_key) != DeleteBitmap::INVALID_SEGMENT_ID) { |
1035 | 230 | delete_bitmap->merge({std::get<0>(delete_bitmap_key), |
1036 | 230 | std::get<1>(delete_bitmap_key), rowset_version}, |
1037 | 230 | bitmap_value); |
1038 | 230 | } |
1039 | 2.62k | } |
1040 | 636 | engine.txn_delete_bitmap_cache().remove_unused_tablet_txn_info(txn_id, |
1041 | 636 | tablet->tablet_id()); |
1042 | 25.8k | } else { |
1043 | 25.8k | LOG_EVERY_N(INFO, 20) |
1044 | 1.28k | << "delete bitmap not found in cache, will sync rowset to get. tablet_id= " |
1045 | 1.28k | << tablet->tablet_id() << ", txn_id=" << txn_id << ", status=" << status; |
1046 | 25.8k | return false; |
1047 | 25.8k | } |
1048 | 26.4k | } |
1049 | 535 | return true; |
1050 | 26.3k | } |
1051 | | |
1052 | | Status CloudMetaMgr::_get_delete_bitmap_from_ms(GetDeleteBitmapRequest& req, |
1053 | 26.1k | GetDeleteBitmapResponse& res) { |
1054 | 26.1k | VLOG_DEBUG << "send GetDeleteBitmapRequest: " << req.ShortDebugString(); |
1055 | 26.1k | TEST_SYNC_POINT_CALLBACK("CloudMetaMgr::_get_delete_bitmap_from_ms", &req, &res); |
1056 | | |
1057 | 26.1k | auto st = retry_rpc(MetaServiceRPC::GET_DELETE_BITMAP, req, &res, |
1058 | 26.1k | &MetaService_Stub::get_delete_bitmap, |
1059 | 26.1k | { |
1060 | 26.1k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1061 | 26.1k | .backpressure_handler = ms_backpressure_handler_, |
1062 | 26.1k | }); |
1063 | 26.1k | if (st.code() == ErrorCode::THRIFT_RPC_ERROR) { |
1064 | 0 | return st; |
1065 | 0 | } |
1066 | | |
1067 | 26.1k | if (res.status().code() == MetaServiceCode::TABLET_NOT_FOUND) { |
1068 | 1 | return Status::NotFound("failed to get delete bitmap: {}", res.status().msg()); |
1069 | 1 | } |
1070 | | // The delete bitmap of stale rowsets will be removed when commit compaction job, |
1071 | | // then delete bitmap of stale rowsets cannot be obtained. But the rowsets obtained |
1072 | | // by sync_tablet_rowsets may include these stale rowsets. When this case happend, the |
1073 | | // error code of ROWSETS_EXPIRED will be returned, we need to retry sync rowsets again. |
1074 | | // |
1075 | | // Be query thread meta-service Be compaction thread |
1076 | | // | | | |
1077 | | // | get rowset | | |
1078 | | // |--------------------------->| | |
1079 | | // | return get rowset | | |
1080 | | // |<---------------------------| | |
1081 | | // | | commit job | |
1082 | | // | |<------------------------| |
1083 | | // | | return commit job | |
1084 | | // | |------------------------>| |
1085 | | // | get delete bitmap | | |
1086 | | // |--------------------------->| | |
1087 | | // | return get delete bitmap | | |
1088 | | // |<---------------------------| | |
1089 | | // | | | |
1090 | 26.1k | if (res.status().code() == MetaServiceCode::ROWSETS_EXPIRED) { |
1091 | 0 | return Status::Error<ErrorCode::ROWSETS_EXPIRED, false>("failed to get delete bitmap: {}", |
1092 | 0 | res.status().msg()); |
1093 | 0 | } |
1094 | 26.1k | if (res.status().code() != MetaServiceCode::OK) { |
1095 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>("failed to get delete bitmap: {}", |
1096 | 0 | res.status().msg()); |
1097 | 0 | } |
1098 | 26.1k | return Status::OK(); |
1099 | 26.1k | } |
1100 | | |
1101 | | Status CloudMetaMgr::_get_delete_bitmap_from_ms_by_batch(GetDeleteBitmapRequest& req, |
1102 | | GetDeleteBitmapResponse& res, |
1103 | 25.7k | int64_t bytes_threadhold) { |
1104 | 25.7k | std::unordered_set<std::string> finished_rowset_ids {}; |
1105 | 25.7k | int count = 0; |
1106 | 26.0k | do { |
1107 | 26.0k | GetDeleteBitmapRequest cur_req; |
1108 | 26.0k | GetDeleteBitmapResponse cur_res; |
1109 | | |
1110 | 26.0k | cur_req.set_cloud_unique_id(config::cloud_unique_id); |
1111 | 26.0k | cur_req.set_tablet_id(req.tablet_id()); |
1112 | 26.0k | cur_req.set_base_compaction_cnt(req.base_compaction_cnt()); |
1113 | 26.0k | cur_req.set_cumulative_compaction_cnt(req.cumulative_compaction_cnt()); |
1114 | 26.0k | cur_req.set_cumulative_point(req.cumulative_point()); |
1115 | 26.0k | *(cur_req.mutable_idx()) = req.idx(); |
1116 | 26.0k | cur_req.set_store_version(req.store_version()); |
1117 | 26.2k | if (bytes_threadhold > 0) { |
1118 | 26.2k | cur_req.set_dbm_bytes_threshold(bytes_threadhold); |
1119 | 26.2k | } |
1120 | 57.9k | for (int i = 0; i < req.rowset_ids_size(); i++) { |
1121 | 31.9k | if (!finished_rowset_ids.contains(req.rowset_ids(i))) { |
1122 | 30.8k | cur_req.add_rowset_ids(req.rowset_ids(i)); |
1123 | 30.8k | cur_req.add_begin_versions(req.begin_versions(i)); |
1124 | 30.8k | cur_req.add_end_versions(req.end_versions(i)); |
1125 | 30.8k | } |
1126 | 31.9k | } |
1127 | | |
1128 | 26.0k | RETURN_IF_ERROR(_get_delete_bitmap_from_ms(cur_req, cur_res)); |
1129 | 26.0k | ++count; |
1130 | | |
1131 | | // v1 delete bitmap |
1132 | 26.0k | res.mutable_rowset_ids()->MergeFrom(cur_res.rowset_ids()); |
1133 | 26.0k | res.mutable_segment_ids()->MergeFrom(cur_res.segment_ids()); |
1134 | 26.0k | res.mutable_versions()->MergeFrom(cur_res.versions()); |
1135 | 26.0k | res.mutable_segment_delete_bitmaps()->MergeFrom(cur_res.segment_delete_bitmaps()); |
1136 | | |
1137 | | // v2 delete bitmap |
1138 | 26.0k | res.mutable_delta_rowset_ids()->MergeFrom(cur_res.delta_rowset_ids()); |
1139 | 26.0k | res.mutable_delete_bitmap_storages()->MergeFrom(cur_res.delete_bitmap_storages()); |
1140 | | |
1141 | 29.8k | for (const auto& rowset_id : cur_res.returned_rowset_ids()) { |
1142 | 29.8k | finished_rowset_ids.insert(rowset_id); |
1143 | 29.8k | } |
1144 | | |
1145 | 26.0k | bool has_more = cur_res.has_has_more() && cur_res.has_more(); |
1146 | 26.0k | if (!has_more) { |
1147 | 25.9k | break; |
1148 | 25.9k | } |
1149 | 110 | LOG_INFO("batch get delete bitmap, progress={}/{}", finished_rowset_ids.size(), |
1150 | 110 | req.rowset_ids_size()) |
1151 | 110 | .tag("tablet_id", req.tablet_id()) |
1152 | 110 | .tag("cur_returned_rowsets", cur_res.returned_rowset_ids_size()) |
1153 | 110 | .tag("rpc_count", count); |
1154 | 110 | } while (finished_rowset_ids.size() < req.rowset_ids_size()); |
1155 | 25.7k | return Status::OK(); |
1156 | 25.7k | } |
1157 | | |
1158 | | Status CloudMetaMgr::sync_tablet_delete_bitmap(CloudTablet* tablet, int64_t old_max_version, |
1159 | | std::ranges::range auto&& rs_metas, |
1160 | | const TabletStatsPB& stats, const TabletIndexPB& idx, |
1161 | | DeleteBitmap* delete_bitmap, bool full_sync, |
1162 | | SyncRowsetStats* sync_stats, int32_t read_version, |
1163 | 39.6k | bool full_sync_v2) { |
1164 | 39.6k | if (rs_metas.empty()) { |
1165 | 13.3k | return Status::OK(); |
1166 | 13.3k | } |
1167 | | |
1168 | 26.4k | if (!full_sync && config::enable_sync_tablet_delete_bitmap_by_cache && |
1169 | 26.4k | sync_tablet_delete_bitmap_by_cache(tablet, rs_metas, delete_bitmap)) { |
1170 | 603 | if (sync_stats) { |
1171 | 174 | sync_stats->get_local_delete_bitmap_rowsets_num += rs_metas.size(); |
1172 | 174 | } |
1173 | 603 | return Status::OK(); |
1174 | 25.7k | } else { |
1175 | 25.7k | DeleteBitmapPtr new_delete_bitmap = std::make_shared<DeleteBitmap>(tablet->tablet_id()); |
1176 | 25.7k | *delete_bitmap = *new_delete_bitmap; |
1177 | 25.7k | } |
1178 | | |
1179 | 25.7k | if (read_version == 2 && config::delete_bitmap_store_write_version == 1) { |
1180 | 0 | return Status::InternalError( |
1181 | 0 | "please set delete_bitmap_store_read_version to 1 or 3 because " |
1182 | 0 | "delete_bitmap_store_write_version is 1"); |
1183 | 25.7k | } else if (read_version == 1 && config::delete_bitmap_store_write_version == 2) { |
1184 | 0 | return Status::InternalError( |
1185 | 0 | "please set delete_bitmap_store_read_version to 2 or 3 because " |
1186 | 0 | "delete_bitmap_store_write_version is 2"); |
1187 | 0 | } |
1188 | | |
1189 | 25.7k | int64_t new_max_version = std::max(old_max_version, rs_metas.rbegin()->end_version()); |
1190 | | // When there are many delete bitmaps that need to be synchronized, it |
1191 | | // may take a longer time, especially when loading the tablet for the |
1192 | | // first time, so set a relatively long timeout time. |
1193 | 25.7k | GetDeleteBitmapRequest req; |
1194 | 25.7k | GetDeleteBitmapResponse res; |
1195 | 25.7k | req.set_cloud_unique_id(config::cloud_unique_id); |
1196 | 25.7k | req.set_tablet_id(tablet->tablet_id()); |
1197 | 25.7k | req.set_base_compaction_cnt(stats.base_compaction_cnt()); |
1198 | 25.7k | req.set_cumulative_compaction_cnt(stats.cumulative_compaction_cnt()); |
1199 | 25.7k | req.set_cumulative_point(stats.cumulative_point()); |
1200 | 25.7k | *(req.mutable_idx()) = idx; |
1201 | 25.7k | req.set_store_version(read_version); |
1202 | | // New rowset sync all versions of delete bitmap |
1203 | 29.6k | for (const auto& rs_meta : rs_metas) { |
1204 | 29.6k | req.add_rowset_ids(rs_meta.rowset_id_v2()); |
1205 | 29.6k | req.add_begin_versions(0); |
1206 | 29.6k | req.add_end_versions(new_max_version); |
1207 | 29.6k | } |
1208 | | |
1209 | 25.8k | if (!full_sync_v2) { |
1210 | | // old rowset sync incremental versions of delete bitmap |
1211 | 25.8k | if (old_max_version > 0 && old_max_version < new_max_version) { |
1212 | 14 | RowsetIdUnorderedSet all_rs_ids; |
1213 | 14 | RETURN_IF_ERROR(tablet->get_all_rs_id(old_max_version, &all_rs_ids)); |
1214 | 108 | for (const auto& rs_id : all_rs_ids) { |
1215 | 108 | req.add_rowset_ids(rs_id.to_string()); |
1216 | 108 | req.add_begin_versions(old_max_version + 1); |
1217 | 108 | req.add_end_versions(new_max_version); |
1218 | 108 | } |
1219 | 14 | } |
1220 | 18.4E | } else { |
1221 | 18.4E | if (old_max_version > 0) { |
1222 | 0 | RowsetIdUnorderedSet all_rs_ids; |
1223 | 0 | RETURN_IF_ERROR(tablet->get_all_rs_id(old_max_version, &all_rs_ids)); |
1224 | 0 | for (const auto& rs_id : all_rs_ids) { |
1225 | 0 | req.add_rowset_ids(rs_id.to_string()); |
1226 | 0 | req.add_begin_versions(0); |
1227 | 0 | req.add_end_versions(new_max_version); |
1228 | 0 | } |
1229 | 0 | } |
1230 | 18.4E | } |
1231 | 25.7k | if (sync_stats) { |
1232 | 7.92k | sync_stats->get_remote_delete_bitmap_rowsets_num += req.rowset_ids_size(); |
1233 | 7.92k | } |
1234 | | |
1235 | 25.7k | auto start = std::chrono::steady_clock::now(); |
1236 | 25.8k | if (config::enable_batch_get_delete_bitmap) { |
1237 | 25.8k | RETURN_IF_ERROR(_get_delete_bitmap_from_ms_by_batch( |
1238 | 25.8k | req, res, config::get_delete_bitmap_bytes_threshold)); |
1239 | 18.4E | } else { |
1240 | 18.4E | RETURN_IF_ERROR(_get_delete_bitmap_from_ms(req, res)); |
1241 | 18.4E | } |
1242 | 25.7k | auto end = std::chrono::steady_clock::now(); |
1243 | | |
1244 | | // v1 delete bitmap |
1245 | 25.7k | const auto& rowset_ids = res.rowset_ids(); |
1246 | 25.7k | const auto& segment_ids = res.segment_ids(); |
1247 | 25.7k | const auto& vers = res.versions(); |
1248 | 25.7k | const auto& delete_bitmaps = res.segment_delete_bitmaps(); |
1249 | 25.9k | if (rowset_ids.size() != segment_ids.size() || rowset_ids.size() != vers.size() || |
1250 | 25.9k | rowset_ids.size() != delete_bitmaps.size()) { |
1251 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>( |
1252 | 0 | "get delete bitmap data wrong," |
1253 | 0 | "rowset_ids.size={},segment_ids.size={},vers.size={},delete_bitmaps.size={}", |
1254 | 0 | rowset_ids.size(), segment_ids.size(), vers.size(), delete_bitmaps.size()); |
1255 | 0 | } |
1256 | 26.1k | for (int i = 0; i < rowset_ids.size(); i++) { |
1257 | 363 | RowsetId rst_id; |
1258 | 363 | rst_id.init(rowset_ids[i]); |
1259 | 363 | delete_bitmap->merge( |
1260 | 363 | {rst_id, segment_ids[i], vers[i]}, |
1261 | 363 | roaring::Roaring::readSafe(delete_bitmaps[i].data(), delete_bitmaps[i].length())); |
1262 | 363 | } |
1263 | | // v2 delete bitmap |
1264 | 25.7k | const auto& delta_rowset_ids = res.delta_rowset_ids(); |
1265 | 25.7k | const auto& delete_bitmap_storages = res.delete_bitmap_storages(); |
1266 | 25.7k | if (delta_rowset_ids.size() != delete_bitmap_storages.size()) { |
1267 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>( |
1268 | 0 | "get delete bitmap data wrong, delta_rowset_ids.size={}, " |
1269 | 0 | "delete_bitmap_storages.size={}", |
1270 | 0 | delta_rowset_ids.size(), delete_bitmap_storages.size()); |
1271 | 0 | } |
1272 | 25.7k | int64_t remote_delete_bitmap_bytes = 0; |
1273 | 25.7k | RETURN_IF_ERROR(_read_tablet_delete_bitmap_v2(tablet, old_max_version, rs_metas, delete_bitmap, |
1274 | 25.7k | res, remote_delete_bitmap_bytes, full_sync_v2)); |
1275 | | |
1276 | 25.7k | if (sync_stats) { |
1277 | 7.93k | sync_stats->get_remote_delete_bitmap_rpc_ns += |
1278 | 7.93k | std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(); |
1279 | 7.93k | sync_stats->get_remote_delete_bitmap_key_count += |
1280 | 7.93k | delete_bitmaps.size() + delete_bitmap_storages.size(); |
1281 | 7.93k | for (const auto& dbm : delete_bitmaps) { |
1282 | 347 | sync_stats->get_remote_delete_bitmap_bytes += dbm.length(); |
1283 | 347 | } |
1284 | 7.93k | sync_stats->get_remote_delete_bitmap_bytes += remote_delete_bitmap_bytes; |
1285 | 7.93k | } |
1286 | 25.7k | int64_t latency = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count(); |
1287 | 25.7k | if (latency > 100 * 1000) { // 100ms |
1288 | 16 | LOG(INFO) << "finish get_delete_bitmap rpcs. rowset_ids.size()=" << rowset_ids.size() |
1289 | 16 | << ", delete_bitmaps.size()=" << delete_bitmaps.size() |
1290 | 16 | << ", delta_delete_bitmaps.size()=" << delta_rowset_ids.size() |
1291 | 16 | << ", latency=" << latency << "us, read_version=" << read_version; |
1292 | 25.7k | } else { |
1293 | 25.7k | LOG_EVERY_N(INFO, 100) << "finish get_delete_bitmap rpcs. rowset_ids.size()=" |
1294 | 261 | << rowset_ids.size() |
1295 | 261 | << ", delete_bitmaps.size()=" << delete_bitmaps.size() |
1296 | 261 | << ", delta_delete_bitmaps.size()=" << delta_rowset_ids.size() |
1297 | 261 | << ", latency=" << latency << "us, read_version=" << read_version; |
1298 | 25.7k | } |
1299 | 25.7k | return Status::OK(); |
1300 | 25.7k | } |
1301 | | |
1302 | | Status CloudMetaMgr::_check_delete_bitmap_v2_correctness(CloudTablet* tablet, GetRowsetRequest& req, |
1303 | | GetRowsetResponse& resp, |
1304 | 39.7k | int64_t old_max_version) { |
1305 | 39.7k | if (!config::enable_delete_bitmap_store_v2_check_correctness || |
1306 | 39.8k | config::delete_bitmap_store_write_version == 1 || resp.rowset_meta().empty()) { |
1307 | 39.8k | return Status::OK(); |
1308 | 39.8k | } |
1309 | 18.4E | int64_t tablet_id = tablet->tablet_id(); |
1310 | 18.4E | int64_t new_max_version = std::max(old_max_version, resp.rowset_meta().rbegin()->end_version()); |
1311 | | // rowset_id, num_segments |
1312 | 18.4E | std::vector<std::pair<RowsetId, int64_t>> all_rowsets; |
1313 | 18.4E | std::map<std::string, std::string> rowset_to_resource; |
1314 | 18.4E | for (const auto& rs_meta : resp.rowset_meta()) { |
1315 | 0 | RowsetId rowset_id; |
1316 | 0 | rowset_id.init(rs_meta.rowset_id_v2()); |
1317 | 0 | all_rowsets.emplace_back(std::make_pair(rowset_id, rs_meta.num_segments())); |
1318 | 0 | rowset_to_resource[rs_meta.rowset_id_v2()] = rs_meta.resource_id(); |
1319 | 0 | } |
1320 | 18.4E | if (old_max_version > 0) { |
1321 | 0 | RowsetIdUnorderedSet all_rs_ids; |
1322 | 0 | RETURN_IF_ERROR(tablet->get_all_rs_id(old_max_version, &all_rs_ids)); |
1323 | 0 | for (auto& rowset : tablet->get_rowset_by_ids(&all_rs_ids)) { |
1324 | 0 | all_rowsets.emplace_back(std::make_pair(rowset->rowset_id(), rowset->num_segments())); |
1325 | 0 | rowset_to_resource[rowset->rowset_id().to_string()] = |
1326 | 0 | rowset->rowset_meta()->resource_id(); |
1327 | 0 | } |
1328 | 0 | } |
1329 | | |
1330 | 18.4E | auto compare_delete_bitmap = [&](DeleteBitmap* delete_bitmap, int version) { |
1331 | 0 | bool success = true; |
1332 | 0 | for (auto& [rs_id, num_segments] : all_rowsets) { |
1333 | 0 | for (int seg_id = 0; seg_id < num_segments; ++seg_id) { |
1334 | 0 | DeleteBitmap::BitmapKey key = {rs_id, seg_id, new_max_version}; |
1335 | 0 | auto dm1 = tablet->tablet_meta()->delete_bitmap().get_agg(key); |
1336 | 0 | auto dm2 = delete_bitmap->get_agg_without_cache(key); |
1337 | 0 | if (*dm1 != *dm2) { |
1338 | 0 | success = false; |
1339 | 0 | LOG(WARNING) << "failed to check delete bitmap correctness by v" |
1340 | 0 | << std::to_string(version) << ", tablet_id=" << tablet->tablet_id() |
1341 | 0 | << ", rowset_id=" << rs_id.to_string() << ", segment_id=" << seg_id |
1342 | 0 | << ", max_version=" << new_max_version |
1343 | 0 | << ". size1=" << dm1->cardinality() |
1344 | 0 | << ", size2=" << dm2->cardinality(); |
1345 | 0 | } |
1346 | 0 | } |
1347 | 0 | } |
1348 | 0 | if (success) { |
1349 | 0 | LOG(INFO) << "succeed to check delete bitmap correctness by v" |
1350 | 0 | << std::to_string(version) << ", tablet_id=" << tablet->tablet_id() |
1351 | 0 | << ", max_version=" << new_max_version; |
1352 | 0 | } |
1353 | 0 | }; |
1354 | | |
1355 | 18.4E | DeleteBitmap full_delete_bitmap(tablet_id); |
1356 | 18.4E | auto st = sync_tablet_delete_bitmap(tablet, old_max_version, resp.rowset_meta(), resp.stats(), |
1357 | 18.4E | req.idx(), &full_delete_bitmap, false, nullptr, 2, true); |
1358 | 18.4E | if (!st.ok()) { |
1359 | 0 | LOG_WARNING("failed to check delete bitmap correctness by v2") |
1360 | 0 | .tag("tablet", tablet->tablet_id()) |
1361 | 0 | .error(st); |
1362 | 18.4E | } else { |
1363 | 18.4E | compare_delete_bitmap(&full_delete_bitmap, 2); |
1364 | 18.4E | } |
1365 | 18.4E | return Status::OK(); |
1366 | 18.4E | } |
1367 | | |
1368 | | Status CloudMetaMgr::_read_tablet_delete_bitmap_v2(CloudTablet* tablet, int64_t old_max_version, |
1369 | | std::ranges::range auto&& rs_metas, |
1370 | | DeleteBitmap* delete_bitmap, |
1371 | | GetDeleteBitmapResponse& res, |
1372 | | int64_t& remote_delete_bitmap_bytes, |
1373 | 25.8k | bool full_sync_v2) { |
1374 | 25.9k | if (res.delta_rowset_ids().empty()) { |
1375 | 25.9k | return Status::OK(); |
1376 | 25.9k | } |
1377 | 18.4E | const auto& rowset_ids = res.delta_rowset_ids(); |
1378 | 18.4E | const auto& delete_bitmap_storages = res.delete_bitmap_storages(); |
1379 | 18.4E | RowsetIdUnorderedSet all_rs_ids; |
1380 | 18.4E | std::map<std::string, std::string> rowset_to_resource; |
1381 | 18.4E | if (old_max_version > 0) { |
1382 | 0 | RETURN_IF_ERROR(tablet->get_all_rs_id(old_max_version, &all_rs_ids)); |
1383 | 0 | if (full_sync_v2) { |
1384 | 0 | for (auto& rowset : tablet->get_rowset_by_ids(&all_rs_ids)) { |
1385 | 0 | rowset_to_resource[rowset->rowset_id().to_string()] = |
1386 | 0 | rowset->rowset_meta()->resource_id(); |
1387 | 0 | } |
1388 | 0 | } |
1389 | 0 | } |
1390 | 18.4E | for (const auto& rs_meta : rs_metas) { |
1391 | 0 | RowsetId rs_id; |
1392 | 0 | rs_id.init(rs_meta.rowset_id_v2()); |
1393 | 0 | all_rs_ids.emplace(rs_id); |
1394 | 0 | rowset_to_resource[rs_meta.rowset_id_v2()] = rs_meta.resource_id(); |
1395 | 0 | } |
1396 | 18.4E | if (config::enable_mow_verbose_log) { |
1397 | 0 | LOG(INFO) << "read delete bitmap for tablet_id=" << tablet->tablet_id() |
1398 | 0 | << ", old_max_version=" << old_max_version |
1399 | 0 | << ", new rowset num=" << rs_metas.size() |
1400 | 0 | << ", rowset has delete bitmap num=" << rowset_ids.size() |
1401 | 0 | << ". all rowset num=" << all_rs_ids.size(); |
1402 | 0 | } |
1403 | | |
1404 | 18.4E | std::mutex result_mtx; |
1405 | 18.4E | Status result; |
1406 | 18.4E | auto merge_delete_bitmap = [&](const std::string& rowset_id, DeleteBitmapPB& dbm) { |
1407 | 0 | if (dbm.rowset_ids_size() != dbm.segment_ids_size() || |
1408 | 0 | dbm.rowset_ids_size() != dbm.versions_size() || |
1409 | 0 | dbm.rowset_ids_size() != dbm.segment_delete_bitmaps_size()) { |
1410 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>( |
1411 | 0 | "get delete bitmap data wrong, rowset_id={}" |
1412 | 0 | "rowset_ids.size={},segment_ids.size={},vers.size={},delete_bitmaps.size={}", |
1413 | 0 | rowset_id, dbm.rowset_ids_size(), dbm.segment_ids_size(), dbm.versions_size(), |
1414 | 0 | dbm.segment_delete_bitmaps_size()); |
1415 | 0 | } |
1416 | 0 | if (config::enable_mow_verbose_log) { |
1417 | 0 | LOG(INFO) << "get delete bitmap for tablet_id=" << tablet->tablet_id() |
1418 | 0 | << ", rowset_id=" << rowset_id |
1419 | 0 | << ", delete_bitmap num=" << dbm.segment_delete_bitmaps_size(); |
1420 | 0 | } |
1421 | 0 | std::lock_guard lock(result_mtx); |
1422 | 0 | for (int j = 0; j < dbm.rowset_ids_size(); j++) { |
1423 | 0 | RowsetId rst_id; |
1424 | 0 | rst_id.init(dbm.rowset_ids(j)); |
1425 | 0 | if (!all_rs_ids.contains(rst_id)) { |
1426 | 0 | LOG(INFO) << "skip merge delete bitmap for tablet_id=" << tablet->tablet_id() |
1427 | 0 | << ", rowset_id=" << rowset_id << ", unused rowset_id=" << rst_id; |
1428 | 0 | continue; |
1429 | 0 | } |
1430 | 0 | delete_bitmap->merge( |
1431 | 0 | {rst_id, dbm.segment_ids(j), dbm.versions(j)}, |
1432 | 0 | roaring::Roaring::readSafe(dbm.segment_delete_bitmaps(j).data(), |
1433 | 0 | dbm.segment_delete_bitmaps(j).length())); |
1434 | 0 | remote_delete_bitmap_bytes += dbm.segment_delete_bitmaps(j).length(); |
1435 | 0 | } |
1436 | 0 | return Status::OK(); |
1437 | 0 | }; |
1438 | 18.4E | auto get_delete_bitmap_from_file = [&](const std::string& rowset_id, |
1439 | 18.4E | const DeleteBitmapStoragePB& storage) { |
1440 | 0 | if (config::enable_mow_verbose_log) { |
1441 | 0 | LOG(INFO) << "get delete bitmap for tablet_id=" << tablet->tablet_id() |
1442 | 0 | << ", rowset_id=" << rowset_id << " from file" |
1443 | 0 | << ", is_packed=" << storage.has_packed_slice_location(); |
1444 | 0 | } |
1445 | 0 | if (rowset_to_resource.find(rowset_id) == rowset_to_resource.end()) { |
1446 | 0 | return Status::InternalError("vault id not found for tablet_id={}, rowset_id={}", |
1447 | 0 | tablet->tablet_id(), rowset_id); |
1448 | 0 | } |
1449 | 0 | auto resource_id = rowset_to_resource[rowset_id]; |
1450 | 0 | CloudStorageEngine& engine = ExecEnv::GetInstance()->storage_engine().to_cloud(); |
1451 | 0 | auto storage_resource = engine.get_storage_resource(resource_id); |
1452 | 0 | if (!storage_resource) { |
1453 | 0 | return Status::InternalError("vault id not found, maybe not sync, vault id {}", |
1454 | 0 | resource_id); |
1455 | 0 | } |
1456 | | |
1457 | | // Use packed file reader if packed_slice_location is present |
1458 | 0 | std::unique_ptr<DeleteBitmapFileReader> reader; |
1459 | 0 | if (storage.has_packed_slice_location() && |
1460 | 0 | !storage.packed_slice_location().packed_file_path().empty()) { |
1461 | 0 | reader = std::make_unique<DeleteBitmapFileReader>(tablet->tablet_id(), rowset_id, |
1462 | 0 | storage_resource, |
1463 | 0 | storage.packed_slice_location()); |
1464 | 0 | } else { |
1465 | 0 | reader = std::make_unique<DeleteBitmapFileReader>(tablet->tablet_id(), rowset_id, |
1466 | 0 | storage_resource); |
1467 | 0 | } |
1468 | |
|
1469 | 0 | RETURN_IF_ERROR(reader->init()); |
1470 | 0 | DeleteBitmapPB dbm; |
1471 | 0 | RETURN_IF_ERROR(reader->read(dbm)); |
1472 | 0 | RETURN_IF_ERROR(reader->close()); |
1473 | 0 | return merge_delete_bitmap(rowset_id, dbm); |
1474 | 0 | }; |
1475 | 18.4E | CloudStorageEngine& engine = ExecEnv::GetInstance()->storage_engine().to_cloud(); |
1476 | 18.4E | std::unique_ptr<ThreadPoolToken> token = engine.sync_delete_bitmap_thread_pool().new_token( |
1477 | 18.4E | ThreadPool::ExecutionMode::CONCURRENT); |
1478 | 18.4E | bthread::CountdownEvent wait {rowset_ids.size()}; |
1479 | 18.4E | for (int i = 0; i < rowset_ids.size(); i++) { |
1480 | 0 | auto& rowset_id = rowset_ids[i]; |
1481 | 0 | if (delete_bitmap_storages[i].store_in_fdb()) { |
1482 | 0 | wait.signal(); |
1483 | 0 | DeleteBitmapPB dbm = delete_bitmap_storages[i].delete_bitmap(); |
1484 | 0 | RETURN_IF_ERROR(merge_delete_bitmap(rowset_id, dbm)); |
1485 | 0 | } else { |
1486 | 0 | const auto& storage = delete_bitmap_storages[i]; |
1487 | 0 | auto submit_st = token->submit_func([&, rowset_id, storage]() { |
1488 | 0 | auto status = get_delete_bitmap_from_file(rowset_id, storage); |
1489 | 0 | if (!status.ok()) { |
1490 | 0 | LOG(WARNING) << "failed to get delete bitmap for tablet_id=" |
1491 | 0 | << tablet->tablet_id() << ", rowset_id=" << rowset_id |
1492 | 0 | << " from file, st=" << status.to_string(); |
1493 | 0 | std::lock_guard lock(result_mtx); |
1494 | 0 | if (result.ok()) { |
1495 | 0 | result = status; |
1496 | 0 | } |
1497 | 0 | } |
1498 | 0 | wait.signal(); |
1499 | 0 | }); |
1500 | 0 | RETURN_IF_ERROR(submit_st); |
1501 | 0 | } |
1502 | 0 | } |
1503 | | // wait for all finished |
1504 | 18.4E | wait.wait(); |
1505 | 18.4E | token->wait(); |
1506 | 18.4E | return result; |
1507 | 18.4E | } |
1508 | | |
1509 | | Status CloudMetaMgr::prepare_rowset(const RowsetMeta& rs_meta, const std::string& job_id, |
1510 | 194k | int64_t table_id, RowsetMetaSharedPtr* existed_rs_meta) { |
1511 | 194k | VLOG_DEBUG << "prepare rowset, tablet_id: " << rs_meta.tablet_id() |
1512 | 39 | << ", rowset_id: " << rs_meta.rowset_id() << " txn_id: " << rs_meta.txn_id(); |
1513 | 194k | { |
1514 | 194k | Status ret_st; |
1515 | 194k | TEST_INJECTION_POINT_RETURN_WITH_VALUE("CloudMetaMgr::prepare_rowset", ret_st); |
1516 | 194k | } |
1517 | 194k | CreateRowsetRequest req; |
1518 | 194k | CreateRowsetResponse resp; |
1519 | 194k | req.set_cloud_unique_id(config::cloud_unique_id); |
1520 | 194k | req.set_txn_id(rs_meta.txn_id()); |
1521 | 194k | req.set_tablet_job_id(job_id); |
1522 | | |
1523 | 194k | RowsetMetaPB doris_rs_meta = rs_meta.get_rowset_pb(/*skip_schema=*/true); |
1524 | 194k | doris_rowset_meta_to_cloud(req.mutable_rowset_meta(), std::move(doris_rs_meta)); |
1525 | | |
1526 | 194k | Status st = |
1527 | 194k | retry_rpc(MetaServiceRPC::PREPARE_ROWSET, req, &resp, &MetaService_Stub::prepare_rowset, |
1528 | 194k | { |
1529 | 194k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1530 | 194k | .backpressure_handler = ms_backpressure_handler_, |
1531 | 194k | .table_id = table_id, |
1532 | 194k | }); |
1533 | 194k | if (!st.ok() && resp.status().code() == MetaServiceCode::ALREADY_EXISTED) { |
1534 | 0 | if (existed_rs_meta != nullptr && resp.has_existed_rowset_meta()) { |
1535 | 0 | RowsetMetaPB doris_rs_meta_tmp = |
1536 | 0 | cloud_rowset_meta_to_doris(std::move(*resp.mutable_existed_rowset_meta())); |
1537 | 0 | *existed_rs_meta = std::make_shared<RowsetMeta>(); |
1538 | 0 | (*existed_rs_meta)->init_from_pb(doris_rs_meta_tmp); |
1539 | 0 | } |
1540 | 0 | return Status::AlreadyExist("failed to prepare rowset: {}", resp.status().msg()); |
1541 | 0 | } |
1542 | 194k | return st; |
1543 | 194k | } |
1544 | | |
1545 | | Status CloudMetaMgr::commit_rowset(RowsetMeta& rs_meta, const std::string& job_id, int64_t table_id, |
1546 | 193k | RowsetMetaSharedPtr* existed_rs_meta) { |
1547 | 193k | VLOG_DEBUG << "commit rowset, tablet_id: " << rs_meta.tablet_id() |
1548 | 47 | << ", rowset_id: " << rs_meta.rowset_id() << " txn_id: " << rs_meta.txn_id(); |
1549 | 193k | { |
1550 | 193k | Status ret_st; |
1551 | 193k | TEST_INJECTION_POINT_RETURN_WITH_VALUE("CloudMetaMgr::commit_rowset", ret_st); |
1552 | 193k | } |
1553 | 193k | check_table_size_correctness(rs_meta); |
1554 | 193k | CreateRowsetRequest req; |
1555 | 193k | CreateRowsetResponse resp; |
1556 | 193k | req.set_cloud_unique_id(config::cloud_unique_id); |
1557 | 193k | req.set_txn_id(rs_meta.txn_id()); |
1558 | 193k | req.set_tablet_job_id(job_id); |
1559 | | |
1560 | 193k | RowsetMetaPB rs_meta_pb = rs_meta.get_rowset_pb(); |
1561 | 193k | doris_rowset_meta_to_cloud(req.mutable_rowset_meta(), std::move(rs_meta_pb)); |
1562 | 193k | Status st = |
1563 | 193k | retry_rpc(MetaServiceRPC::COMMIT_ROWSET, req, &resp, &MetaService_Stub::commit_rowset, |
1564 | 193k | { |
1565 | 193k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1566 | 193k | .backpressure_handler = ms_backpressure_handler_, |
1567 | 193k | .table_id = table_id, |
1568 | 193k | }); |
1569 | 193k | if (!st.ok() && resp.status().code() == MetaServiceCode::ALREADY_EXISTED) { |
1570 | 0 | if (existed_rs_meta != nullptr && resp.has_existed_rowset_meta()) { |
1571 | 0 | RowsetMetaPB doris_rs_meta = |
1572 | 0 | cloud_rowset_meta_to_doris(std::move(*resp.mutable_existed_rowset_meta())); |
1573 | 0 | *existed_rs_meta = std::make_shared<RowsetMeta>(); |
1574 | 0 | (*existed_rs_meta)->init_from_pb(doris_rs_meta); |
1575 | 0 | } |
1576 | 0 | return Status::AlreadyExist("failed to commit rowset: {}", resp.status().msg()); |
1577 | 0 | } |
1578 | 193k | int64_t timeout_ms = -1; |
1579 | | // if the `job_id` is not empty, it means this rowset was produced by a compaction job. |
1580 | 193k | if (config::enable_compaction_delay_commit_for_warm_up && !job_id.empty()) { |
1581 | | // 1. assume the download speed is 100MB/s |
1582 | | // 2. we double the download time as timeout for safety |
1583 | | // 3. for small rowsets, the timeout we calculate maybe quite small, so we need a min_time_out |
1584 | 0 | const double speed_mbps = 100.0; // 100MB/s |
1585 | 0 | const double safety_factor = 2.0; |
1586 | 0 | timeout_ms = std::min( |
1587 | 0 | std::max(static_cast<int64_t>(static_cast<double>(rs_meta.total_disk_size()) / |
1588 | 0 | (speed_mbps * 1024 * 1024) * safety_factor * 1000), |
1589 | 0 | config::warm_up_rowset_sync_wait_min_timeout_ms), |
1590 | 0 | config::warm_up_rowset_sync_wait_max_timeout_ms); |
1591 | 0 | LOG(INFO) << "warm up rowset: " << rs_meta.version() << ", job_id: " << job_id |
1592 | 0 | << ", with timeout: " << timeout_ms << " ms"; |
1593 | 0 | } |
1594 | 193k | auto& manager = ExecEnv::GetInstance()->storage_engine().to_cloud().cloud_warm_up_manager(); |
1595 | 193k | manager.warm_up_rowset(rs_meta, table_id, timeout_ms); |
1596 | 193k | return st; |
1597 | 193k | } |
1598 | | |
1599 | 125k | void CloudMetaMgr::cache_committed_rowset(RowsetMetaSharedPtr rs_meta, int64_t expiration_time) { |
1600 | | // For load-generated rowsets (job_id is empty), add to pending rowset manager |
1601 | | // so FE can notify BE to promote them later |
1602 | | |
1603 | | // TODO(bobhan1): copy rs_meta? |
1604 | 125k | int64_t txn_id = rs_meta->txn_id(); |
1605 | 125k | int64_t tablet_id = rs_meta->tablet_id(); |
1606 | 125k | ExecEnv::GetInstance()->storage_engine().to_cloud().committed_rs_mgr().add_committed_rowset( |
1607 | 125k | txn_id, tablet_id, std::move(rs_meta), expiration_time); |
1608 | 125k | } |
1609 | | |
1610 | 19 | Status CloudMetaMgr::update_tmp_rowset(const RowsetMeta& rs_meta, int64_t table_id) { |
1611 | 19 | VLOG_DEBUG << "update committed rowset, tablet_id: " << rs_meta.tablet_id() |
1612 | 0 | << ", rowset_id: " << rs_meta.rowset_id(); |
1613 | 19 | CreateRowsetRequest req; |
1614 | 19 | CreateRowsetResponse resp; |
1615 | 19 | req.set_cloud_unique_id(config::cloud_unique_id); |
1616 | | |
1617 | | // Variant schema maybe updated, so we need to update the schema as well. |
1618 | | // The updated rowset meta after `rowset->merge_rowset_meta` in `BaseTablet::update_delete_bitmap` |
1619 | | // will be lost in `update_tmp_rowset` if skip_schema.So in order to keep the latest schema we should keep schema in update_tmp_rowset |
1620 | | // for variant type |
1621 | 19 | bool skip_schema = rs_meta.tablet_schema()->num_variant_columns() == 0; |
1622 | 19 | RowsetMetaPB rs_meta_pb = rs_meta.get_rowset_pb(skip_schema); |
1623 | 19 | doris_rowset_meta_to_cloud(req.mutable_rowset_meta(), std::move(rs_meta_pb)); |
1624 | 19 | Status st = retry_rpc(MetaServiceRPC::UPDATE_TMP_ROWSET, req, &resp, |
1625 | 19 | &MetaService_Stub::update_tmp_rowset, |
1626 | 19 | { |
1627 | 19 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1628 | 19 | .backpressure_handler = ms_backpressure_handler_, |
1629 | 19 | .table_id = table_id, |
1630 | 19 | }); |
1631 | 19 | if (!st.ok() && resp.status().code() == MetaServiceCode::ROWSET_META_NOT_FOUND) { |
1632 | 0 | return Status::InternalError("failed to update committed rowset: {}", resp.status().msg()); |
1633 | 0 | } |
1634 | 19 | return st; |
1635 | 19 | } |
1636 | | |
1637 | | // async send TableStats(in res) to FE coz we are in streamload ctx, response to the user ASAP |
1638 | | static void send_stats_to_fe_async(const int64_t db_id, const int64_t txn_id, |
1639 | | const std::string& label, CommitTxnResponse& res, |
1640 | 7.03k | const std::vector<int64_t>& tablet_ids) { |
1641 | 7.03k | std::string protobufBytes; |
1642 | 7.03k | if (txn_id != -1) { |
1643 | 0 | res.SerializeToString(&protobufBytes); |
1644 | 0 | } |
1645 | 7.03k | auto st = ExecEnv::GetInstance()->send_table_stats_thread_pool()->submit_func( |
1646 | 7.03k | [db_id, txn_id, label, protobufBytes, tablet_ids]() -> Status { |
1647 | 7.03k | TReportCommitTxnResultRequest request; |
1648 | 7.03k | TStatus result; |
1649 | | |
1650 | 7.03k | if (txn_id != -1 && protobufBytes.length() <= 0) { |
1651 | 0 | LOG(WARNING) << "protobufBytes: " << protobufBytes.length(); |
1652 | 0 | return Status::OK(); // nobody cares the return status |
1653 | 0 | } |
1654 | | |
1655 | 7.03k | request.__set_dbId(db_id); |
1656 | 7.03k | request.__set_txnId(txn_id); |
1657 | 7.03k | request.__set_label(label); |
1658 | 7.03k | request.__set_payload(protobufBytes); |
1659 | 7.03k | request.__set_tabletIds(tablet_ids); |
1660 | | |
1661 | 7.03k | Status status; |
1662 | 7.03k | int64_t duration_ns = 0; |
1663 | 7.03k | TNetworkAddress master_addr = |
1664 | 7.03k | ExecEnv::GetInstance()->cluster_info()->master_fe_addr; |
1665 | 7.03k | if (master_addr.hostname.empty() || master_addr.port == 0) { |
1666 | 0 | status = Status::Error<SERVICE_UNAVAILABLE>( |
1667 | 0 | "Have not get FE Master heartbeat yet"); |
1668 | 7.03k | } else { |
1669 | 7.03k | SCOPED_RAW_TIMER(&duration_ns); |
1670 | | |
1671 | 7.03k | RETURN_IF_ERROR(ThriftRpcHelper::rpc<FrontendServiceClient>( |
1672 | 7.03k | master_addr.hostname, master_addr.port, |
1673 | 7.03k | [&request, &result](FrontendServiceConnection& client) { |
1674 | 7.03k | client->reportCommitTxnResult(result, request); |
1675 | 7.03k | })); |
1676 | | |
1677 | 7.03k | status = Status::create<false>(result); |
1678 | 7.03k | } |
1679 | 7.03k | g_cloud_commit_txn_resp_redirect_latency << duration_ns / 1000; |
1680 | | |
1681 | 7.03k | if (!status.ok()) { |
1682 | 0 | LOG(WARNING) << "TableStats report RPC to FE failed, errmsg=" << status |
1683 | 0 | << " dbId=" << db_id << " txnId=" << txn_id << " label=" << label; |
1684 | 0 | return Status::OK(); // nobody cares the return status |
1685 | 7.03k | } else { |
1686 | 7.03k | LOG(INFO) << "TableStats report RPC to FE success, msg=" << status |
1687 | 7.03k | << " dbId=" << db_id << " txnId=" << txn_id << " label=" << label; |
1688 | 7.03k | return Status::OK(); |
1689 | 7.03k | } |
1690 | 7.03k | }); |
1691 | 7.03k | if (!st.ok()) { |
1692 | 0 | LOG(WARNING) << "TableStats report to FE task submission failed: " << st.to_string(); |
1693 | 0 | } |
1694 | 7.03k | } |
1695 | | |
1696 | 0 | Status CloudMetaMgr::commit_txn(const StreamLoadContext& ctx, bool is_2pc) { |
1697 | 0 | VLOG_DEBUG << "commit txn, db_id: " << ctx.db_id << ", txn_id: " << ctx.txn_id |
1698 | 0 | << ", label: " << ctx.label << ", is_2pc: " << is_2pc; |
1699 | 0 | { |
1700 | 0 | Status ret_st; |
1701 | 0 | TEST_INJECTION_POINT_RETURN_WITH_VALUE("CloudMetaMgr::commit_txn", ret_st); |
1702 | 0 | } |
1703 | 0 | CommitTxnRequest req; |
1704 | 0 | CommitTxnResponse res; |
1705 | 0 | req.set_cloud_unique_id(config::cloud_unique_id); |
1706 | 0 | req.set_db_id(ctx.db_id); |
1707 | 0 | req.set_txn_id(ctx.txn_id); |
1708 | 0 | req.set_is_2pc(is_2pc); |
1709 | 0 | req.set_enable_txn_lazy_commit(config::enable_cloud_txn_lazy_commit); |
1710 | 0 | auto st = retry_rpc(MetaServiceRPC::COMMIT_TXN, req, &res, &MetaService_Stub::commit_txn, |
1711 | 0 | { |
1712 | 0 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1713 | 0 | .backpressure_handler = ms_backpressure_handler_, |
1714 | 0 | }); |
1715 | |
|
1716 | 0 | if (st.ok()) { |
1717 | 0 | VLOG_DEBUG << "commit txn succeeded, db_id: " << ctx.db_id << ", txn_id: " << ctx.txn_id |
1718 | 0 | << ", label: " << ctx.label << ", is_lazy_commit: " << res.is_lazy_commit() |
1719 | 0 | << ", is_lazy_commit_incomplete: " << res.is_lazy_commit_incomplete(); |
1720 | 0 | std::vector<int64_t> tablet_ids; |
1721 | 0 | for (auto& commit_info : ctx.commit_infos) { |
1722 | 0 | tablet_ids.emplace_back(commit_info.tabletId); |
1723 | 0 | } |
1724 | 0 | send_stats_to_fe_async(ctx.db_id, ctx.txn_id, ctx.label, res, tablet_ids); |
1725 | 0 | } |
1726 | |
|
1727 | 0 | return st; |
1728 | 0 | } |
1729 | | |
1730 | 488 | Status CloudMetaMgr::abort_txn(const StreamLoadContext& ctx) { |
1731 | 488 | VLOG_DEBUG << "abort txn, db_id: " << ctx.db_id << ", txn_id: " << ctx.txn_id |
1732 | 0 | << ", label: " << ctx.label; |
1733 | 488 | { |
1734 | 488 | Status ret_st; |
1735 | 488 | TEST_INJECTION_POINT_RETURN_WITH_VALUE("CloudMetaMgr::abort_txn", ret_st); |
1736 | 488 | } |
1737 | 488 | AbortTxnRequest req; |
1738 | 488 | AbortTxnResponse res; |
1739 | 488 | req.set_cloud_unique_id(config::cloud_unique_id); |
1740 | 488 | req.set_reason(std::string(ctx.status.msg().substr(0, 1024))); |
1741 | 488 | if (ctx.txn_id > 0) { |
1742 | 488 | req.set_txn_id(ctx.txn_id); |
1743 | 488 | } else if (ctx.db_id > 0 && !ctx.label.empty()) { |
1744 | 0 | req.set_db_id(ctx.db_id); |
1745 | 0 | req.set_label(ctx.label); |
1746 | 0 | } else { |
1747 | 0 | LOG(WARNING) << "failed abort txn, with illegal input, db_id=" << ctx.db_id |
1748 | 0 | << " txn_id=" << ctx.txn_id << " label=" << ctx.label; |
1749 | 0 | return Status::InternalError<false>("failed to abort txn"); |
1750 | 0 | } |
1751 | 488 | TEST_SYNC_POINT_RETURN_WITH_VALUE("CloudMetaMgr::abort_txn.before_rpc", Status::OK(), &req); |
1752 | 488 | return retry_rpc(MetaServiceRPC::ABORT_TXN, req, &res, &MetaService_Stub::abort_txn, |
1753 | 488 | { |
1754 | 488 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1755 | 488 | .backpressure_handler = ms_backpressure_handler_, |
1756 | 488 | }); |
1757 | 488 | } |
1758 | | |
1759 | 33 | Status CloudMetaMgr::precommit_txn(const StreamLoadContext& ctx) { |
1760 | 33 | VLOG_DEBUG << "precommit txn, db_id: " << ctx.db_id << ", txn_id: " << ctx.txn_id |
1761 | 0 | << ", label: " << ctx.label; |
1762 | 33 | { |
1763 | 33 | Status ret_st; |
1764 | 33 | TEST_INJECTION_POINT_RETURN_WITH_VALUE("CloudMetaMgr::precommit_txn", ret_st); |
1765 | 33 | } |
1766 | 33 | PrecommitTxnRequest req; |
1767 | 33 | PrecommitTxnResponse res; |
1768 | 33 | req.set_cloud_unique_id(config::cloud_unique_id); |
1769 | 33 | req.set_db_id(ctx.db_id); |
1770 | 33 | req.set_txn_id(ctx.txn_id); |
1771 | 33 | return retry_rpc(MetaServiceRPC::PRECOMMIT_TXN, req, &res, &MetaService_Stub::precommit_txn, |
1772 | 33 | { |
1773 | 33 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1774 | 33 | .backpressure_handler = ms_backpressure_handler_, |
1775 | 33 | }); |
1776 | 33 | } |
1777 | | |
1778 | 0 | Status CloudMetaMgr::prepare_restore_job(const TabletMetaPB& tablet_meta) { |
1779 | 0 | VLOG_DEBUG << "prepare restore job, tablet_id: " << tablet_meta.tablet_id(); |
1780 | 0 | RestoreJobRequest req; |
1781 | 0 | RestoreJobResponse resp; |
1782 | 0 | req.set_cloud_unique_id(config::cloud_unique_id); |
1783 | 0 | req.set_tablet_id(tablet_meta.tablet_id()); |
1784 | 0 | req.set_expiration(config::snapshot_expire_time_sec); |
1785 | 0 | req.set_action(RestoreJobRequest::PREPARE); |
1786 | |
|
1787 | 0 | doris_tablet_meta_to_cloud(req.mutable_tablet_meta(), std::move(tablet_meta)); |
1788 | 0 | return retry_rpc(MetaServiceRPC::PREPARE_RESTORE_JOB, req, &resp, |
1789 | 0 | &MetaService_Stub::prepare_restore_job, |
1790 | 0 | { |
1791 | 0 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1792 | 0 | .backpressure_handler = ms_backpressure_handler_, |
1793 | 0 | }); |
1794 | 0 | } |
1795 | | |
1796 | 0 | Status CloudMetaMgr::commit_restore_job(const int64_t tablet_id) { |
1797 | 0 | VLOG_DEBUG << "commit restore job, tablet_id: " << tablet_id; |
1798 | 0 | RestoreJobRequest req; |
1799 | 0 | RestoreJobResponse resp; |
1800 | 0 | req.set_cloud_unique_id(config::cloud_unique_id); |
1801 | 0 | req.set_tablet_id(tablet_id); |
1802 | 0 | req.set_action(RestoreJobRequest::COMMIT); |
1803 | 0 | req.set_store_version(config::delete_bitmap_store_write_version); |
1804 | |
|
1805 | 0 | return retry_rpc(MetaServiceRPC::COMMIT_RESTORE_JOB, req, &resp, |
1806 | 0 | &MetaService_Stub::commit_restore_job, |
1807 | 0 | { |
1808 | 0 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1809 | 0 | .backpressure_handler = ms_backpressure_handler_, |
1810 | 0 | }); |
1811 | 0 | } |
1812 | | |
1813 | 0 | Status CloudMetaMgr::finish_restore_job(const int64_t tablet_id, bool is_completed) { |
1814 | 0 | VLOG_DEBUG << "finish restore job, tablet_id: " << tablet_id |
1815 | 0 | << ", is_completed: " << is_completed; |
1816 | 0 | RestoreJobRequest req; |
1817 | 0 | RestoreJobResponse resp; |
1818 | 0 | req.set_cloud_unique_id(config::cloud_unique_id); |
1819 | 0 | req.set_tablet_id(tablet_id); |
1820 | 0 | req.set_action(is_completed ? RestoreJobRequest::COMPLETE : RestoreJobRequest::ABORT); |
1821 | |
|
1822 | 0 | return retry_rpc(MetaServiceRPC::FINISH_RESTORE_JOB, req, &resp, |
1823 | 0 | &MetaService_Stub::finish_restore_job, |
1824 | 0 | { |
1825 | 0 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1826 | 0 | .backpressure_handler = ms_backpressure_handler_, |
1827 | 0 | }); |
1828 | 0 | } |
1829 | | |
1830 | 106 | Status CloudMetaMgr::get_storage_vault_info(StorageVaultInfos* vault_infos, bool* is_vault_mode) { |
1831 | 106 | GetObjStoreInfoRequest req; |
1832 | 106 | GetObjStoreInfoResponse resp; |
1833 | 106 | req.set_cloud_unique_id(config::cloud_unique_id); |
1834 | 106 | Status s = retry_rpc(MetaServiceRPC::GET_OBJ_STORE_INFO, req, &resp, |
1835 | 106 | &MetaService_Stub::get_obj_store_info, |
1836 | 106 | { |
1837 | 106 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1838 | 106 | .backpressure_handler = ms_backpressure_handler_, |
1839 | 106 | }); |
1840 | 106 | if (!s.ok()) { |
1841 | 0 | return s; |
1842 | 0 | } |
1843 | | |
1844 | 106 | *is_vault_mode = resp.enable_storage_vault(); |
1845 | | |
1846 | 106 | auto add_obj_store = [&vault_infos](const auto& obj_store) { |
1847 | 106 | vault_infos->emplace_back(obj_store.id(), S3Conf::get_s3_conf(obj_store), |
1848 | 106 | StorageVaultPB_PathFormat {}); |
1849 | 106 | }; |
1850 | | |
1851 | 106 | std::ranges::for_each(resp.obj_info(), add_obj_store); |
1852 | 106 | std::ranges::for_each(resp.storage_vault(), [&](const auto& vault) { |
1853 | 0 | if (vault.has_hdfs_info()) { |
1854 | 0 | vault_infos->emplace_back(vault.id(), vault.hdfs_info(), vault.path_format()); |
1855 | 0 | } |
1856 | 0 | if (vault.has_obj_info()) { |
1857 | 0 | add_obj_store(vault.obj_info()); |
1858 | 0 | } |
1859 | 0 | }); |
1860 | | |
1861 | | // desensitization, hide secret |
1862 | 212 | for (int i = 0; i < resp.obj_info_size(); ++i) { |
1863 | 106 | resp.mutable_obj_info(i)->set_sk(resp.obj_info(i).sk().substr(0, 2) + "xxx"); |
1864 | 106 | } |
1865 | 106 | for (int i = 0; i < resp.storage_vault_size(); ++i) { |
1866 | 0 | auto* j = resp.mutable_storage_vault(i); |
1867 | 0 | if (!j->has_obj_info()) continue; |
1868 | 0 | j->mutable_obj_info()->set_sk(j->obj_info().sk().substr(0, 2) + "xxx"); |
1869 | 0 | } |
1870 | | |
1871 | 212 | for (int i = 0; i < resp.obj_info_size(); ++i) { |
1872 | 106 | resp.mutable_obj_info(i)->set_ak(hide_access_key(resp.obj_info(i).sk())); |
1873 | 106 | } |
1874 | 106 | for (int i = 0; i < resp.storage_vault_size(); ++i) { |
1875 | 0 | auto* j = resp.mutable_storage_vault(i); |
1876 | 0 | if (!j->has_obj_info()) continue; |
1877 | 0 | j->mutable_obj_info()->set_sk(hide_access_key(j->obj_info().sk())); |
1878 | 0 | } |
1879 | | |
1880 | 106 | LOG(INFO) << "get storage vault, enable_storage_vault=" << *is_vault_mode |
1881 | 106 | << " response=" << resp.ShortDebugString(); |
1882 | 106 | return Status::OK(); |
1883 | 106 | } |
1884 | | |
1885 | 18.7k | Status CloudMetaMgr::prepare_tablet_job(const TabletJobInfoPB& job, StartTabletJobResponse* res) { |
1886 | 18.7k | VLOG_DEBUG << "prepare_tablet_job: " << job.ShortDebugString(); |
1887 | 18.7k | TEST_SYNC_POINT_RETURN_WITH_VALUE("CloudMetaMgr::prepare_tablet_job", Status::OK(), job, res); |
1888 | | |
1889 | 18.7k | StartTabletJobRequest req; |
1890 | 18.7k | req.mutable_job()->CopyFrom(job); |
1891 | 18.7k | req.set_cloud_unique_id(config::cloud_unique_id); |
1892 | 18.7k | return retry_rpc(MetaServiceRPC::START_TABLET_JOB, req, res, |
1893 | 18.7k | &MetaService_Stub::start_tablet_job, |
1894 | 18.7k | { |
1895 | 18.7k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1896 | 18.7k | .backpressure_handler = ms_backpressure_handler_, |
1897 | 18.7k | }); |
1898 | 18.7k | } |
1899 | | |
1900 | 16.9k | Status CloudMetaMgr::commit_tablet_job(const TabletJobInfoPB& job, FinishTabletJobResponse* res) { |
1901 | 16.9k | VLOG_DEBUG << "commit_tablet_job: " << job.ShortDebugString(); |
1902 | 16.9k | TEST_SYNC_POINT_RETURN_WITH_VALUE("CloudMetaMgr::commit_tablet_job", Status::OK(), job, res); |
1903 | 16.9k | DBUG_EXECUTE_IF("CloudMetaMgr::commit_tablet_job.fail", { |
1904 | 16.9k | return Status::InternalError<false>("inject CloudMetaMgr::commit_tablet_job.fail"); |
1905 | 16.9k | }); |
1906 | | |
1907 | 16.9k | FinishTabletJobRequest req; |
1908 | 16.9k | req.mutable_job()->CopyFrom(job); |
1909 | 16.9k | req.set_action(FinishTabletJobRequest::COMMIT); |
1910 | 16.9k | req.set_cloud_unique_id(config::cloud_unique_id); |
1911 | 16.9k | auto st = retry_rpc(MetaServiceRPC::FINISH_TABLET_JOB, req, res, |
1912 | 16.9k | &MetaService_Stub::finish_tablet_job, |
1913 | 16.9k | { |
1914 | 16.9k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1915 | 16.9k | .backpressure_handler = ms_backpressure_handler_, |
1916 | 16.9k | }); |
1917 | 16.9k | if (res->status().code() == MetaServiceCode::KV_TXN_CONFLICT_RETRY_EXCEEDED_MAX_TIMES) { |
1918 | 0 | return Status::Error<ErrorCode::DELETE_BITMAP_LOCK_ERROR, false>( |
1919 | 0 | "txn conflict when commit tablet job {}", job.ShortDebugString()); |
1920 | 0 | } |
1921 | | |
1922 | 17.1k | if (st.ok() && !job.compaction().empty() && job.has_idx()) { |
1923 | 7.03k | CommitTxnResponse commit_txn_resp; |
1924 | 7.03k | std::vector<int64_t> tablet_ids = {job.idx().tablet_id()}; |
1925 | 7.03k | send_stats_to_fe_async(-1, -1, "", commit_txn_resp, tablet_ids); |
1926 | 7.03k | } |
1927 | | |
1928 | 16.9k | return st; |
1929 | 16.9k | } |
1930 | | |
1931 | 47 | Status CloudMetaMgr::abort_tablet_job(const TabletJobInfoPB& job) { |
1932 | 47 | VLOG_DEBUG << "abort_tablet_job: " << job.ShortDebugString(); |
1933 | 47 | TEST_SYNC_POINT_RETURN_WITH_VALUE("CloudMetaMgr::abort_tablet_job", Status::OK(), job); |
1934 | 47 | FinishTabletJobRequest req; |
1935 | 47 | FinishTabletJobResponse res; |
1936 | 47 | req.mutable_job()->CopyFrom(job); |
1937 | 47 | req.set_action(FinishTabletJobRequest::ABORT); |
1938 | 47 | req.set_cloud_unique_id(config::cloud_unique_id); |
1939 | 47 | return retry_rpc(MetaServiceRPC::FINISH_TABLET_JOB, req, &res, |
1940 | 47 | &MetaService_Stub::finish_tablet_job, |
1941 | 47 | { |
1942 | 47 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1943 | 47 | .backpressure_handler = ms_backpressure_handler_, |
1944 | 47 | }); |
1945 | 47 | } |
1946 | | |
1947 | 159 | Status CloudMetaMgr::lease_tablet_job(const TabletJobInfoPB& job) { |
1948 | 159 | VLOG_DEBUG << "lease_tablet_job: " << job.ShortDebugString(); |
1949 | 159 | FinishTabletJobRequest req; |
1950 | 159 | FinishTabletJobResponse res; |
1951 | 159 | req.mutable_job()->CopyFrom(job); |
1952 | 159 | req.set_action(FinishTabletJobRequest::LEASE); |
1953 | 159 | req.set_cloud_unique_id(config::cloud_unique_id); |
1954 | 159 | return retry_rpc(MetaServiceRPC::FINISH_TABLET_JOB, req, &res, |
1955 | 159 | &MetaService_Stub::finish_tablet_job, |
1956 | 159 | { |
1957 | 159 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
1958 | 159 | .backpressure_handler = ms_backpressure_handler_, |
1959 | 159 | }); |
1960 | 159 | } |
1961 | | |
1962 | | static void add_delete_bitmap(DeleteBitmapPB& delete_bitmap_pb, const DeleteBitmap::BitmapKey& key, |
1963 | 0 | roaring::Roaring& bitmap) { |
1964 | 0 | delete_bitmap_pb.add_rowset_ids(std::get<0>(key).to_string()); |
1965 | 0 | delete_bitmap_pb.add_segment_ids(std::get<1>(key)); |
1966 | 0 | delete_bitmap_pb.add_versions(std::get<2>(key)); |
1967 | | // To save space, convert array and bitmap containers to run containers |
1968 | 0 | bitmap.runOptimize(); |
1969 | 0 | std::string bitmap_data(bitmap.getSizeInBytes(), '\0'); |
1970 | 0 | bitmap.write(bitmap_data.data()); |
1971 | 0 | *(delete_bitmap_pb.add_segment_delete_bitmaps()) = std::move(bitmap_data); |
1972 | 0 | } |
1973 | | |
1974 | | static Status store_delete_bitmap(std::string& rowset_id, DeleteBitmapPB& delete_bitmap_pb, |
1975 | | int64_t tablet_id, |
1976 | | std::optional<StorageResource> storage_resource, |
1977 | 0 | UpdateDeleteBitmapRequest& req, int64_t txn_id) { |
1978 | 0 | if (config::enable_mow_verbose_log) { |
1979 | 0 | std::stringstream ss; |
1980 | 0 | for (int i = 0; i < delete_bitmap_pb.rowset_ids_size(); i++) { |
1981 | 0 | ss << "{rid=" << delete_bitmap_pb.rowset_ids(i) |
1982 | 0 | << ", sid=" << delete_bitmap_pb.segment_ids(i) |
1983 | 0 | << ", ver=" << delete_bitmap_pb.versions(i) << "}, "; |
1984 | 0 | } |
1985 | 0 | LOG(INFO) << "handle one rowset delete bitmap for tablet_id: " << tablet_id |
1986 | 0 | << ", rowset_id: " << rowset_id |
1987 | 0 | << ", delete_bitmap num: " << delete_bitmap_pb.rowset_ids_size() |
1988 | 0 | << ", size: " << delete_bitmap_pb.ByteSizeLong() << ", keys=[" << ss.str() |
1989 | 0 | << "]"; |
1990 | 0 | } |
1991 | 0 | if (delete_bitmap_pb.rowset_ids_size() == 0) { |
1992 | 0 | return Status::OK(); |
1993 | 0 | } |
1994 | 0 | DeleteBitmapStoragePB delete_bitmap_storage; |
1995 | 0 | if (config::delete_bitmap_store_v2_max_bytes_in_fdb >= 0 && |
1996 | 0 | delete_bitmap_pb.ByteSizeLong() > config::delete_bitmap_store_v2_max_bytes_in_fdb) { |
1997 | | // Enable packed file only for load (txn_id > 0) |
1998 | 0 | bool enable_packed = config::enable_packed_file && txn_id > 0; |
1999 | 0 | DeleteBitmapFileWriter file_writer(tablet_id, rowset_id, storage_resource, enable_packed, |
2000 | 0 | txn_id); |
2001 | 0 | RETURN_IF_ERROR(file_writer.init()); |
2002 | 0 | RETURN_IF_ERROR(file_writer.write(delete_bitmap_pb)); |
2003 | 0 | RETURN_IF_ERROR(file_writer.close()); |
2004 | 0 | delete_bitmap_pb.Clear(); |
2005 | 0 | delete_bitmap_storage.set_store_in_fdb(false); |
2006 | | |
2007 | | // Store packed slice location if file was written to packed file |
2008 | 0 | if (file_writer.is_packed()) { |
2009 | 0 | io::PackedSliceLocation loc; |
2010 | 0 | RETURN_IF_ERROR(file_writer.get_packed_slice_location(&loc)); |
2011 | 0 | auto* packed_loc = delete_bitmap_storage.mutable_packed_slice_location(); |
2012 | 0 | packed_loc->set_packed_file_path(loc.packed_file_path); |
2013 | 0 | packed_loc->set_offset(loc.offset); |
2014 | 0 | packed_loc->set_size(loc.size); |
2015 | 0 | packed_loc->set_packed_file_size(loc.packed_file_size); |
2016 | 0 | } |
2017 | 0 | } else { |
2018 | 0 | delete_bitmap_storage.set_store_in_fdb(true); |
2019 | 0 | *(delete_bitmap_storage.mutable_delete_bitmap()) = std::move(delete_bitmap_pb); |
2020 | 0 | } |
2021 | 0 | req.add_delta_rowset_ids(rowset_id); |
2022 | 0 | *(req.add_delete_bitmap_storages()) = std::move(delete_bitmap_storage); |
2023 | 0 | return Status::OK(); |
2024 | 0 | } |
2025 | | |
2026 | | Status CloudMetaMgr::update_delete_bitmap(const CloudTablet& tablet, int64_t lock_id, |
2027 | | int64_t initiator, DeleteBitmap* delete_bitmap, |
2028 | | DeleteBitmap* delete_bitmap_v2, std::string rowset_id, |
2029 | | std::optional<StorageResource> storage_resource, |
2030 | | int64_t store_version, int64_t table_id, int64_t txn_id, |
2031 | 55.1k | bool is_explicit_txn, int64_t next_visible_version) { |
2032 | 55.1k | VLOG_DEBUG << "update_delete_bitmap , tablet_id: " << tablet.tablet_id(); |
2033 | 55.1k | if (config::enable_mow_verbose_log) { |
2034 | 0 | std::stringstream ss; |
2035 | 0 | ss << "start update delete bitmap for tablet_id: " << tablet.tablet_id() |
2036 | 0 | << ", rowset_id: " << rowset_id |
2037 | 0 | << ", delete_bitmap num: " << delete_bitmap->delete_bitmap.size() |
2038 | 0 | << ", store_version: " << store_version << ", lock_id=" << lock_id |
2039 | 0 | << ", initiator=" << initiator; |
2040 | 0 | if (store_version == 2 || store_version == 3) { |
2041 | 0 | ss << ", delete_bitmap v2 num: " << delete_bitmap_v2->delete_bitmap.size(); |
2042 | 0 | } |
2043 | 0 | LOG(INFO) << ss.str(); |
2044 | 0 | } |
2045 | 55.1k | UpdateDeleteBitmapRequest req; |
2046 | 55.1k | UpdateDeleteBitmapResponse res; |
2047 | 55.1k | req.set_cloud_unique_id(config::cloud_unique_id); |
2048 | 55.1k | req.set_table_id(tablet.table_id()); |
2049 | 55.1k | req.set_partition_id(tablet.partition_id()); |
2050 | 55.1k | req.set_tablet_id(tablet.tablet_id()); |
2051 | 55.1k | req.set_lock_id(lock_id); |
2052 | 55.1k | req.set_initiator(initiator); |
2053 | 55.1k | req.set_is_explicit_txn(is_explicit_txn); |
2054 | 55.1k | if (txn_id > 0) { |
2055 | 49.6k | req.set_txn_id(txn_id); |
2056 | 49.6k | } |
2057 | 55.1k | if (next_visible_version > 0) { |
2058 | 49.7k | req.set_next_visible_version(next_visible_version); |
2059 | 49.7k | } |
2060 | 55.1k | req.set_store_version(store_version); |
2061 | | |
2062 | 55.1k | bool write_v1 = store_version == 1 || store_version == 3; |
2063 | 55.1k | bool write_v2 = store_version == 2 || store_version == 3; |
2064 | | // write v1 kvs |
2065 | 55.1k | if (write_v1) { |
2066 | 54.3k | for (auto& [key, bitmap] : delete_bitmap->delete_bitmap) { |
2067 | 8.84k | req.add_rowset_ids(std::get<0>(key).to_string()); |
2068 | 8.84k | req.add_segment_ids(std::get<1>(key)); |
2069 | 8.84k | req.add_versions(std::get<2>(key)); |
2070 | | // To save space, convert array and bitmap containers to run containers |
2071 | 8.84k | bitmap.runOptimize(); |
2072 | 8.84k | std::string bitmap_data(bitmap.getSizeInBytes(), '\0'); |
2073 | 8.84k | bitmap.write(bitmap_data.data()); |
2074 | 8.84k | *(req.add_segment_delete_bitmaps()) = std::move(bitmap_data); |
2075 | 8.84k | } |
2076 | 54.3k | } |
2077 | | |
2078 | | // write v2 kvs |
2079 | 55.1k | if (write_v2) { |
2080 | 0 | if (config::enable_mow_verbose_log) { |
2081 | 0 | LOG(INFO) << "update delete bitmap for tablet_id: " << tablet.tablet_id() |
2082 | 0 | << ", rowset_id: " << rowset_id |
2083 | 0 | << ", delete_bitmap num: " << delete_bitmap_v2->delete_bitmap.size() |
2084 | 0 | << ", lock_id=" << lock_id << ", initiator=" << initiator; |
2085 | 0 | } |
2086 | 0 | if (rowset_id.empty()) { |
2087 | 0 | std::string pre_rowset_id = ""; |
2088 | 0 | std::string cur_rowset_id = ""; |
2089 | 0 | DeleteBitmapPB delete_bitmap_pb; |
2090 | 0 | for (auto it = delete_bitmap_v2->delete_bitmap.begin(); |
2091 | 0 | it != delete_bitmap_v2->delete_bitmap.end(); ++it) { |
2092 | 0 | auto& key = it->first; |
2093 | 0 | auto& bitmap = it->second; |
2094 | 0 | cur_rowset_id = std::get<0>(key).to_string(); |
2095 | 0 | if (cur_rowset_id != pre_rowset_id) { |
2096 | 0 | if (!pre_rowset_id.empty() && delete_bitmap_pb.rowset_ids_size() > 0) { |
2097 | 0 | RETURN_IF_ERROR(store_delete_bitmap(pre_rowset_id, delete_bitmap_pb, |
2098 | 0 | tablet.tablet_id(), storage_resource, |
2099 | 0 | req, txn_id)); |
2100 | 0 | } |
2101 | 0 | pre_rowset_id = cur_rowset_id; |
2102 | 0 | DCHECK_EQ(delete_bitmap_pb.rowset_ids_size(), 0); |
2103 | 0 | DCHECK_EQ(delete_bitmap_pb.segment_ids_size(), 0); |
2104 | 0 | DCHECK_EQ(delete_bitmap_pb.versions_size(), 0); |
2105 | 0 | DCHECK_EQ(delete_bitmap_pb.segment_delete_bitmaps_size(), 0); |
2106 | 0 | } |
2107 | 0 | add_delete_bitmap(delete_bitmap_pb, key, bitmap); |
2108 | 0 | } |
2109 | 0 | if (delete_bitmap_pb.rowset_ids_size() > 0) { |
2110 | 0 | DCHECK(!cur_rowset_id.empty()); |
2111 | 0 | RETURN_IF_ERROR(store_delete_bitmap(cur_rowset_id, delete_bitmap_pb, |
2112 | 0 | tablet.tablet_id(), storage_resource, req, |
2113 | 0 | txn_id)); |
2114 | 0 | } |
2115 | 0 | } else { |
2116 | 0 | DeleteBitmapPB delete_bitmap_pb; |
2117 | 0 | for (auto& [key, bitmap] : delete_bitmap_v2->delete_bitmap) { |
2118 | 0 | add_delete_bitmap(delete_bitmap_pb, key, bitmap); |
2119 | 0 | } |
2120 | 0 | RETURN_IF_ERROR(store_delete_bitmap(rowset_id, delete_bitmap_pb, tablet.tablet_id(), |
2121 | 0 | storage_resource, req, txn_id)); |
2122 | 0 | } |
2123 | 0 | DCHECK_EQ(req.delta_rowset_ids_size(), req.delete_bitmap_storages_size()); |
2124 | 0 | } |
2125 | 55.1k | DBUG_EXECUTE_IF("CloudMetaMgr::test_update_big_delete_bitmap", { |
2126 | 55.1k | LOG(INFO) << "test_update_big_delete_bitmap for tablet " << tablet.tablet_id(); |
2127 | 55.1k | auto count = dp->param<int>("count", 30000); |
2128 | 55.1k | if (!delete_bitmap->delete_bitmap.empty()) { |
2129 | 55.1k | auto& key = delete_bitmap->delete_bitmap.begin()->first; |
2130 | 55.1k | auto& bitmap = delete_bitmap->delete_bitmap.begin()->second; |
2131 | 55.1k | for (int i = 1000; i < (1000 + count); i++) { |
2132 | 55.1k | req.add_rowset_ids(std::get<0>(key).to_string()); |
2133 | 55.1k | req.add_segment_ids(std::get<1>(key)); |
2134 | 55.1k | req.add_versions(i); |
2135 | | // To save space, convert array and bitmap containers to run containers |
2136 | 55.1k | bitmap.runOptimize(); |
2137 | 55.1k | std::string bitmap_data(bitmap.getSizeInBytes(), '\0'); |
2138 | 55.1k | bitmap.write(bitmap_data.data()); |
2139 | 55.1k | *(req.add_segment_delete_bitmaps()) = std::move(bitmap_data); |
2140 | 55.1k | } |
2141 | 55.1k | } |
2142 | 55.1k | }); |
2143 | 55.1k | DBUG_EXECUTE_IF("CloudMetaMgr::test_update_delete_bitmap_fail", { |
2144 | 55.1k | return Status::Error<ErrorCode::DELETE_BITMAP_LOCK_ERROR>( |
2145 | 55.1k | "test update delete bitmap failed, tablet_id: {}, lock_id: {}", tablet.tablet_id(), |
2146 | 55.1k | lock_id); |
2147 | 55.1k | }); |
2148 | 55.1k | auto st = retry_rpc(MetaServiceRPC::UPDATE_DELETE_BITMAP, req, &res, |
2149 | 55.1k | &MetaService_Stub::update_delete_bitmap, |
2150 | 55.1k | { |
2151 | 55.1k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2152 | 55.1k | .backpressure_handler = ms_backpressure_handler_, |
2153 | 55.1k | .table_id = table_id, |
2154 | 55.1k | }); |
2155 | 55.1k | if (config::enable_update_delete_bitmap_kv_check_core && |
2156 | 55.1k | res.status().code() == MetaServiceCode::UPDATE_OVERRIDE_EXISTING_KV) { |
2157 | 0 | auto& msg = res.status().msg(); |
2158 | 0 | LOG_WARNING(msg); |
2159 | 0 | CHECK(false) << msg; |
2160 | 0 | } |
2161 | 55.1k | if (res.status().code() == MetaServiceCode::LOCK_EXPIRED) { |
2162 | 18 | return Status::Error<ErrorCode::DELETE_BITMAP_LOCK_ERROR, false>( |
2163 | 18 | "lock expired when update delete bitmap, tablet_id: {}, lock_id: {}, initiator: " |
2164 | 18 | "{}, error_msg: {}", |
2165 | 18 | tablet.tablet_id(), lock_id, initiator, res.status().msg()); |
2166 | 18 | } |
2167 | 55.1k | return st; |
2168 | 55.1k | } |
2169 | | |
2170 | | Status CloudMetaMgr::cloud_update_delete_bitmap_without_lock( |
2171 | | const CloudTablet& tablet, DeleteBitmap* delete_bitmap, |
2172 | | std::map<std::string, int64_t>& rowset_to_versions, int64_t table_id, |
2173 | 3.06k | int64_t pre_rowset_agg_start_version, int64_t pre_rowset_agg_end_version) { |
2174 | 3.06k | if (config::delete_bitmap_store_write_version == 2) { |
2175 | 0 | VLOG_DEBUG << "no need to agg delete bitmap v1 in ms because use v2"; |
2176 | 0 | return Status::OK(); |
2177 | 0 | } |
2178 | 3.06k | LOG(INFO) << "cloud_update_delete_bitmap_without_lock, tablet_id: " << tablet.tablet_id() |
2179 | 3.06k | << ", delete_bitmap size: " << delete_bitmap->delete_bitmap.size(); |
2180 | 3.06k | UpdateDeleteBitmapRequest req; |
2181 | 3.06k | UpdateDeleteBitmapResponse res; |
2182 | 3.06k | req.set_cloud_unique_id(config::cloud_unique_id); |
2183 | 3.06k | req.set_table_id(tablet.table_id()); |
2184 | 3.06k | req.set_partition_id(tablet.partition_id()); |
2185 | 3.06k | req.set_tablet_id(tablet.tablet_id()); |
2186 | | // use a fake lock id to resolve compatibility issues |
2187 | 3.06k | req.set_lock_id(-3); |
2188 | 3.06k | req.set_without_lock(true); |
2189 | 3.06k | for (auto& [key, bitmap] : delete_bitmap->delete_bitmap) { |
2190 | 1.05k | req.add_rowset_ids(std::get<0>(key).to_string()); |
2191 | 1.05k | req.add_segment_ids(std::get<1>(key)); |
2192 | 1.05k | req.add_versions(std::get<2>(key)); |
2193 | 1.05k | if (pre_rowset_agg_end_version > 0) { |
2194 | 1.05k | DCHECK(rowset_to_versions.find(std::get<0>(key).to_string()) != |
2195 | 0 | rowset_to_versions.end()) |
2196 | 0 | << "rowset_to_versions not found for key=" << std::get<0>(key).to_string(); |
2197 | 1.05k | req.add_pre_rowset_versions(rowset_to_versions[std::get<0>(key).to_string()]); |
2198 | 1.05k | } |
2199 | 1.05k | DCHECK(pre_rowset_agg_end_version <= 0 || pre_rowset_agg_end_version == std::get<2>(key)) |
2200 | 0 | << "pre_rowset_agg_end_version=" << pre_rowset_agg_end_version |
2201 | 0 | << " not equal to version=" << std::get<2>(key); |
2202 | | // To save space, convert array and bitmap containers to run containers |
2203 | 1.05k | bitmap.runOptimize(); |
2204 | 1.05k | std::string bitmap_data(bitmap.getSizeInBytes(), '\0'); |
2205 | 1.05k | bitmap.write(bitmap_data.data()); |
2206 | 1.05k | *(req.add_segment_delete_bitmaps()) = std::move(bitmap_data); |
2207 | 1.05k | } |
2208 | 3.06k | if (pre_rowset_agg_start_version > 0 && pre_rowset_agg_end_version > 0) { |
2209 | 3.06k | req.set_pre_rowset_agg_start_version(pre_rowset_agg_start_version); |
2210 | 3.06k | req.set_pre_rowset_agg_end_version(pre_rowset_agg_end_version); |
2211 | 3.06k | } |
2212 | 3.06k | return retry_rpc(MetaServiceRPC::UPDATE_DELETE_BITMAP, req, &res, |
2213 | 3.06k | &MetaService_Stub::update_delete_bitmap, |
2214 | 3.06k | { |
2215 | 3.06k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2216 | 3.06k | .backpressure_handler = ms_backpressure_handler_, |
2217 | 3.06k | .table_id = table_id, |
2218 | 3.06k | }); |
2219 | 3.06k | } |
2220 | | |
2221 | | Status CloudMetaMgr::get_delete_bitmap_update_lock(const CloudTablet& tablet, int64_t lock_id, |
2222 | 4.39k | int64_t initiator) { |
2223 | 4.39k | DBUG_EXECUTE_IF("get_delete_bitmap_update_lock.inject_fail", { |
2224 | 4.39k | auto p = dp->param("percent", 0.01); |
2225 | 4.39k | std::mt19937 gen {std::random_device {}()}; |
2226 | 4.39k | std::bernoulli_distribution inject_fault {p}; |
2227 | 4.39k | if (inject_fault(gen)) { |
2228 | 4.39k | return Status::Error<ErrorCode::DELETE_BITMAP_LOCK_ERROR>( |
2229 | 4.39k | "injection error when get get_delete_bitmap_update_lock, " |
2230 | 4.39k | "tablet_id={}, lock_id={}, initiator={}", |
2231 | 4.39k | tablet.tablet_id(), lock_id, initiator); |
2232 | 4.39k | } |
2233 | 4.39k | }); |
2234 | 4.39k | VLOG_DEBUG << "get_delete_bitmap_update_lock , tablet_id: " << tablet.tablet_id() |
2235 | 2 | << ",lock_id:" << lock_id; |
2236 | 4.39k | GetDeleteBitmapUpdateLockRequest req; |
2237 | 4.39k | GetDeleteBitmapUpdateLockResponse res; |
2238 | 4.39k | req.set_cloud_unique_id(config::cloud_unique_id); |
2239 | 4.39k | req.set_table_id(tablet.table_id()); |
2240 | 4.39k | req.set_lock_id(lock_id); |
2241 | 4.39k | req.set_initiator(initiator); |
2242 | | // set expiration time for compaction and schema_change |
2243 | 4.39k | req.set_expiration(config::delete_bitmap_lock_expiration_seconds); |
2244 | 4.39k | int retry_times = 0; |
2245 | 4.39k | Status st; |
2246 | 4.39k | std::default_random_engine rng = make_random_engine(); |
2247 | 4.39k | std::uniform_int_distribution<uint32_t> u(500, 2000); |
2248 | 4.39k | uint64_t backoff_sleep_time_ms {0}; |
2249 | 4.70k | do { |
2250 | 4.70k | bool test_conflict = false; |
2251 | 4.70k | st = retry_rpc(MetaServiceRPC::GET_DELETE_BITMAP_UPDATE_LOCK, req, &res, |
2252 | 4.70k | &MetaService_Stub::get_delete_bitmap_update_lock, |
2253 | 4.70k | { |
2254 | 4.70k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2255 | 4.70k | .backpressure_handler = ms_backpressure_handler_, |
2256 | 4.70k | }); |
2257 | 4.70k | DBUG_EXECUTE_IF("CloudMetaMgr::test_get_delete_bitmap_update_lock_conflict", |
2258 | 4.70k | { test_conflict = true; }); |
2259 | 4.70k | if (!test_conflict && res.status().code() != MetaServiceCode::LOCK_CONFLICT) { |
2260 | 4.39k | break; |
2261 | 4.39k | } |
2262 | | |
2263 | 314 | uint32_t duration_ms = u(rng); |
2264 | 314 | LOG(WARNING) << "get delete bitmap lock conflict. " << debug_info(req) |
2265 | 314 | << " retry_times=" << retry_times << " sleep=" << duration_ms |
2266 | 314 | << "ms : " << res.status().msg(); |
2267 | 314 | auto start = std::chrono::steady_clock::now(); |
2268 | 314 | bthread_usleep(duration_ms * 1000); |
2269 | 314 | auto end = std::chrono::steady_clock::now(); |
2270 | 314 | backoff_sleep_time_ms += duration_cast<std::chrono::milliseconds>(end - start).count(); |
2271 | 314 | } while (++retry_times <= config::get_delete_bitmap_lock_max_retry_times); |
2272 | 0 | g_cloud_be_mow_get_dbm_lock_backoff_sleep_time << backoff_sleep_time_ms; |
2273 | 4.39k | DBUG_EXECUTE_IF("CloudMetaMgr.get_delete_bitmap_update_lock.inject_sleep", { |
2274 | 4.39k | auto p = dp->param("percent", 0.01); |
2275 | | // 100s > Config.calculate_delete_bitmap_task_timeout_seconds = 60s |
2276 | 4.39k | auto sleep_time = dp->param("sleep", 15); |
2277 | 4.39k | std::mt19937 gen {std::random_device {}()}; |
2278 | 4.39k | std::bernoulli_distribution inject_fault {p}; |
2279 | 4.39k | if (inject_fault(gen)) { |
2280 | 4.39k | LOG_INFO("injection sleep for {} seconds, tablet_id={}", sleep_time, |
2281 | 4.39k | tablet.tablet_id()); |
2282 | 4.39k | std::this_thread::sleep_for(std::chrono::seconds(sleep_time)); |
2283 | 4.39k | } |
2284 | 4.39k | }); |
2285 | 4.39k | if (res.status().code() == MetaServiceCode::KV_TXN_CONFLICT_RETRY_EXCEEDED_MAX_TIMES) { |
2286 | 0 | return Status::Error<ErrorCode::DELETE_BITMAP_LOCK_ERROR, false>( |
2287 | 0 | "txn conflict when get delete bitmap update lock, table_id {}, lock_id {}, " |
2288 | 0 | "initiator {}", |
2289 | 0 | tablet.table_id(), lock_id, initiator); |
2290 | 4.39k | } else if (res.status().code() == MetaServiceCode::LOCK_CONFLICT) { |
2291 | 0 | return Status::Error<ErrorCode::DELETE_BITMAP_LOCK_ERROR, false>( |
2292 | 0 | "lock conflict when get delete bitmap update lock, table_id {}, lock_id {}, " |
2293 | 0 | "initiator {}", |
2294 | 0 | tablet.table_id(), lock_id, initiator); |
2295 | 0 | } |
2296 | 4.39k | return st; |
2297 | 4.39k | } |
2298 | | |
2299 | | void CloudMetaMgr::remove_delete_bitmap_update_lock(int64_t table_id, int64_t lock_id, |
2300 | 36 | int64_t initiator, int64_t tablet_id) { |
2301 | 36 | LOG(INFO) << "remove_delete_bitmap_update_lock ,table_id: " << table_id |
2302 | 36 | << ",lock_id:" << lock_id << ",initiator:" << initiator << ",tablet_id:" << tablet_id; |
2303 | 36 | RemoveDeleteBitmapUpdateLockRequest req; |
2304 | 36 | RemoveDeleteBitmapUpdateLockResponse res; |
2305 | 36 | req.set_cloud_unique_id(config::cloud_unique_id); |
2306 | 36 | req.set_table_id(table_id); |
2307 | 36 | req.set_tablet_id(tablet_id); |
2308 | 36 | req.set_lock_id(lock_id); |
2309 | 36 | req.set_initiator(initiator); |
2310 | 36 | auto st = retry_rpc(MetaServiceRPC::REMOVE_DELETE_BITMAP_UPDATE_LOCK, req, &res, |
2311 | 36 | &MetaService_Stub::remove_delete_bitmap_update_lock, |
2312 | 36 | { |
2313 | 36 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2314 | 36 | .backpressure_handler = ms_backpressure_handler_, |
2315 | 36 | }); |
2316 | 36 | if (!st.ok()) { |
2317 | 36 | LOG(WARNING) << "remove delete bitmap update lock fail,table_id=" << table_id |
2318 | 36 | << ",tablet_id=" << tablet_id << ",lock_id=" << lock_id |
2319 | 36 | << ",st=" << st.to_string(); |
2320 | 36 | } |
2321 | 36 | } |
2322 | | |
2323 | 192k | void CloudMetaMgr::check_table_size_correctness(RowsetMeta& rs_meta) { |
2324 | 193k | if (!config::enable_table_size_correctness_check) { |
2325 | 193k | return; |
2326 | 193k | } |
2327 | 18.4E | int64_t total_segment_size = get_segment_file_size(rs_meta); |
2328 | 18.4E | int64_t total_inverted_index_size = get_inverted_index_file_size(rs_meta); |
2329 | 18.4E | if (rs_meta.data_disk_size() != total_segment_size || |
2330 | 18.4E | rs_meta.index_disk_size() != total_inverted_index_size || |
2331 | 18.4E | rs_meta.data_disk_size() + rs_meta.index_disk_size() != rs_meta.total_disk_size()) { |
2332 | 0 | LOG(WARNING) << "[Cloud table table size check failed]:" |
2333 | 0 | << " tablet id: " << rs_meta.tablet_id() |
2334 | 0 | << ", rowset id:" << rs_meta.rowset_id() |
2335 | 0 | << ", rowset data disk size:" << rs_meta.data_disk_size() |
2336 | 0 | << ", rowset real data disk size:" << total_segment_size |
2337 | 0 | << ", rowset index disk size:" << rs_meta.index_disk_size() |
2338 | 0 | << ", rowset real index disk size:" << total_inverted_index_size |
2339 | 0 | << ", rowset total disk size:" << rs_meta.total_disk_size() |
2340 | 0 | << ", rowset segment path:" |
2341 | 0 | << StorageResource().remote_segment_path(rs_meta.tablet_id(), |
2342 | 0 | rs_meta.rowset_id().to_string(), 0); |
2343 | 0 | DCHECK(false); |
2344 | 0 | } |
2345 | 18.4E | } |
2346 | | |
2347 | 0 | int64_t CloudMetaMgr::get_segment_file_size(RowsetMeta& rs_meta) { |
2348 | 0 | int64_t total_segment_size = 0; |
2349 | 0 | const auto fs = rs_meta.fs(); |
2350 | 0 | if (!fs) { |
2351 | 0 | LOG(WARNING) << "get fs failed, resource_id={}" << rs_meta.resource_id(); |
2352 | 0 | } |
2353 | 0 | for (int64_t seg_id = 0; seg_id < rs_meta.num_segments(); seg_id++) { |
2354 | 0 | std::string segment_path = StorageResource().remote_segment_path( |
2355 | 0 | rs_meta.tablet_id(), rs_meta.rowset_id().to_string(), seg_id); |
2356 | 0 | int64_t segment_file_size = 0; |
2357 | 0 | auto st = fs->file_size(segment_path, &segment_file_size); |
2358 | 0 | if (!st.ok()) { |
2359 | 0 | segment_file_size = 0; |
2360 | 0 | if (st.is<NOT_FOUND>()) { |
2361 | 0 | LOG(INFO) << "cloud table size correctness check get segment size 0 because " |
2362 | 0 | "file not exist! msg:" |
2363 | 0 | << st.msg() << ", segment path:" << segment_path; |
2364 | 0 | } else { |
2365 | 0 | LOG(WARNING) << "cloud table size correctness check get segment size failed! msg:" |
2366 | 0 | << st.msg() << ", segment path:" << segment_path; |
2367 | 0 | } |
2368 | 0 | } |
2369 | 0 | total_segment_size += segment_file_size; |
2370 | 0 | } |
2371 | 0 | return total_segment_size; |
2372 | 0 | } |
2373 | | |
2374 | 0 | int64_t CloudMetaMgr::get_inverted_index_file_size(RowsetMeta& rs_meta) { |
2375 | 0 | int64_t total_inverted_index_size = 0; |
2376 | 0 | const auto fs = rs_meta.fs(); |
2377 | 0 | if (!fs) { |
2378 | 0 | LOG(WARNING) << "get fs failed, resource_id={}" << rs_meta.resource_id(); |
2379 | 0 | } |
2380 | 0 | if (rs_meta.tablet_schema()->get_inverted_index_storage_format() == |
2381 | 0 | InvertedIndexStorageFormatPB::V1) { |
2382 | 0 | const auto& indices = rs_meta.tablet_schema()->inverted_indexes(); |
2383 | 0 | for (auto& index : indices) { |
2384 | 0 | for (int seg_id = 0; seg_id < rs_meta.num_segments(); ++seg_id) { |
2385 | 0 | std::string segment_path = StorageResource().remote_segment_path( |
2386 | 0 | rs_meta.tablet_id(), rs_meta.rowset_id().to_string(), seg_id); |
2387 | 0 | int64_t file_size = 0; |
2388 | |
|
2389 | 0 | std::string inverted_index_file_path = |
2390 | 0 | InvertedIndexDescriptor::get_index_file_path_v1( |
2391 | 0 | InvertedIndexDescriptor::get_index_file_path_prefix(segment_path), |
2392 | 0 | index->index_id(), index->get_index_suffix()); |
2393 | 0 | auto st = fs->file_size(inverted_index_file_path, &file_size); |
2394 | 0 | if (!st.ok()) { |
2395 | 0 | file_size = 0; |
2396 | 0 | if (st.is<NOT_FOUND>()) { |
2397 | 0 | LOG(INFO) << "cloud table size correctness check get inverted index v1 " |
2398 | 0 | "0 because file not exist! msg:" |
2399 | 0 | << st.msg() |
2400 | 0 | << ", inverted index path:" << inverted_index_file_path; |
2401 | 0 | } else { |
2402 | 0 | LOG(WARNING) |
2403 | 0 | << "cloud table size correctness check get inverted index v1 " |
2404 | 0 | "size failed! msg:" |
2405 | 0 | << st.msg() << ", inverted index path:" << inverted_index_file_path; |
2406 | 0 | } |
2407 | 0 | } |
2408 | 0 | total_inverted_index_size += file_size; |
2409 | 0 | } |
2410 | 0 | } |
2411 | 0 | } else { |
2412 | 0 | for (int seg_id = 0; seg_id < rs_meta.num_segments(); ++seg_id) { |
2413 | 0 | int64_t file_size = 0; |
2414 | 0 | std::string segment_path = StorageResource().remote_segment_path( |
2415 | 0 | rs_meta.tablet_id(), rs_meta.rowset_id().to_string(), seg_id); |
2416 | |
|
2417 | 0 | std::string inverted_index_file_path = InvertedIndexDescriptor::get_index_file_path_v2( |
2418 | 0 | InvertedIndexDescriptor::get_index_file_path_prefix(segment_path)); |
2419 | 0 | auto st = fs->file_size(inverted_index_file_path, &file_size); |
2420 | 0 | if (!st.ok()) { |
2421 | 0 | file_size = 0; |
2422 | 0 | if (st.is<NOT_FOUND>()) { |
2423 | 0 | LOG(INFO) << "cloud table size correctness check get inverted index v2 " |
2424 | 0 | "0 because file not exist! msg:" |
2425 | 0 | << st.msg() << ", inverted index path:" << inverted_index_file_path; |
2426 | 0 | } else { |
2427 | 0 | LOG(WARNING) << "cloud table size correctness check get inverted index v2 " |
2428 | 0 | "size failed! msg:" |
2429 | 0 | << st.msg() |
2430 | 0 | << ", inverted index path:" << inverted_index_file_path; |
2431 | 0 | } |
2432 | 0 | } |
2433 | 0 | total_inverted_index_size += file_size; |
2434 | 0 | } |
2435 | 0 | } |
2436 | 0 | return total_inverted_index_size; |
2437 | 0 | } |
2438 | | |
2439 | | Status CloudMetaMgr::fill_version_holes(CloudTablet* tablet, int64_t max_version, |
2440 | 181k | std::unique_lock<BthreadSharedMutex>& wlock) { |
2441 | 181k | if (max_version <= 0) { |
2442 | 115k | return Status::OK(); |
2443 | 115k | } |
2444 | | |
2445 | 66.8k | Versions existing_versions; |
2446 | 237k | for (const auto& [_, rs] : tablet->tablet_meta()->all_rs_metas()) { |
2447 | 237k | existing_versions.emplace_back(rs->version()); |
2448 | 237k | } |
2449 | | |
2450 | | // If there are no existing versions, it may be a new tablet for restore, so skip filling holes. |
2451 | 66.8k | if (existing_versions.empty()) { |
2452 | 1 | return Status::OK(); |
2453 | 1 | } |
2454 | | |
2455 | 66.8k | std::vector<RowsetSharedPtr> hole_rowsets; |
2456 | | // sort the existing versions in ascending order |
2457 | 66.8k | std::sort(existing_versions.begin(), existing_versions.end(), |
2458 | 482k | [](const Version& a, const Version& b) { |
2459 | | // simple because 2 versions are certainly not overlapping |
2460 | 482k | return a.first < b.first; |
2461 | 482k | }); |
2462 | | |
2463 | | // During schema change, get_tablet operations on new tablets trigger sync_tablet_rowsets which calls |
2464 | | // fill_version_holes. For schema change tablets (TABLET_NOTREADY state), we selectively skip hole |
2465 | | // filling for versions <= alter_version to prevent: |
2466 | | // 1. Abnormal compaction score calculations for schema change tablets |
2467 | | // 2. Unexpected -235 errors during load operations |
2468 | | // This allows schema change to proceed normally while still permitting hole filling for versions |
2469 | | // beyond the alter_version threshold. |
2470 | 66.8k | bool is_schema_change_tablet = tablet->tablet_state() == TABLET_NOTREADY; |
2471 | 66.8k | if (is_schema_change_tablet && tablet->alter_version() <= 1) { |
2472 | 10.0k | LOG(INFO) << "Skip version hole filling for new schema change tablet " |
2473 | 10.0k | << tablet->tablet_id() << " with alter_version " << tablet->alter_version(); |
2474 | 10.0k | return Status::OK(); |
2475 | 10.0k | } |
2476 | | |
2477 | 56.7k | int64_t last_version = -1; |
2478 | 227k | for (const Version& version : existing_versions) { |
2479 | 227k | VLOG_NOTICE << "Existing version for tablet " << tablet->tablet_id() << ": [" |
2480 | 8 | << version.first << ", " << version.second << "]"; |
2481 | | // missing versions are those that are not in the existing_versions |
2482 | 227k | if (version.first > last_version + 1) { |
2483 | | // there is a hole between versions |
2484 | 34 | auto prev_non_hole_rowset = tablet->get_rowset_by_version(version); |
2485 | 734 | for (int64_t ver = last_version + 1; ver < version.first; ++ver) { |
2486 | | // Skip hole filling for versions <= alter_version during schema change |
2487 | 700 | if (is_schema_change_tablet && ver <= tablet->alter_version()) { |
2488 | 687 | continue; |
2489 | 687 | } |
2490 | 13 | RowsetSharedPtr hole_rowset; |
2491 | 13 | RETURN_IF_ERROR(create_empty_rowset_for_hole( |
2492 | 13 | tablet, ver, prev_non_hole_rowset->rowset_meta(), &hole_rowset)); |
2493 | 13 | hole_rowsets.push_back(hole_rowset); |
2494 | 13 | } |
2495 | 34 | LOG(INFO) << "Created empty rowset for version hole, from " << last_version + 1 |
2496 | 34 | << " to " << version.first - 1 << " for tablet " << tablet->tablet_id() |
2497 | 34 | << (is_schema_change_tablet |
2498 | 34 | ? (", schema change tablet skipped filling versions <= " + |
2499 | 28 | std::to_string(tablet->alter_version())) |
2500 | 34 | : ""); |
2501 | 34 | } |
2502 | 227k | last_version = version.second; |
2503 | 227k | } |
2504 | | |
2505 | 56.7k | if (last_version + 1 <= max_version) { |
2506 | 5.51k | LOG(INFO) << "Created empty rowset for version hole, from " << last_version + 1 << " to " |
2507 | 5.51k | << max_version << " for tablet " << tablet->tablet_id() |
2508 | 5.51k | << (is_schema_change_tablet |
2509 | 5.51k | ? (", schema change tablet skipped filling versions <= " + |
2510 | 5.08k | std::to_string(tablet->alter_version())) |
2511 | 5.51k | : ""); |
2512 | | // there is a hole after the last existing version |
2513 | 18.3k | for (; last_version + 1 <= max_version; ++last_version) { |
2514 | | // Skip hole filling for versions <= alter_version during schema change |
2515 | 12.8k | if (is_schema_change_tablet && last_version + 1 <= tablet->alter_version()) { |
2516 | 11.5k | continue; |
2517 | 11.5k | } |
2518 | 1.31k | RowsetSharedPtr hole_rowset; |
2519 | 1.31k | auto prev_non_hole_rowset = tablet->get_rowset_by_version(existing_versions.back()); |
2520 | 1.31k | RETURN_IF_ERROR(create_empty_rowset_for_hole( |
2521 | 1.31k | tablet, last_version + 1, prev_non_hole_rowset->rowset_meta(), &hole_rowset)); |
2522 | 1.31k | hole_rowsets.push_back(hole_rowset); |
2523 | 1.31k | } |
2524 | 5.51k | } |
2525 | | |
2526 | 56.7k | if (!hole_rowsets.empty()) { |
2527 | 437 | size_t hole_count = hole_rowsets.size(); |
2528 | 437 | tablet->add_rowsets(std::move(hole_rowsets), false, wlock, false); |
2529 | 437 | g_cloud_version_hole_filled_count << hole_count; |
2530 | 437 | } |
2531 | 56.7k | return Status::OK(); |
2532 | 56.7k | } |
2533 | | |
2534 | | Status CloudMetaMgr::create_empty_rowset_for_hole(CloudTablet* tablet, int64_t version, |
2535 | | RowsetMetaSharedPtr prev_rowset_meta, |
2536 | 1.33k | RowsetSharedPtr* rowset) { |
2537 | | // Create a RowsetMeta for the empty rowset |
2538 | 1.33k | auto rs_meta = std::make_shared<RowsetMeta>(); |
2539 | | |
2540 | | // Generate a deterministic rowset ID for the hole (same tablet_id + version = same rowset_id) |
2541 | 1.33k | RowsetId hole_rowset_id; |
2542 | 1.33k | hole_rowset_id.init(2, 0, tablet->tablet_id(), version); |
2543 | 1.33k | rs_meta->set_rowset_id(hole_rowset_id); |
2544 | | |
2545 | | // Generate a deterministic load_id for the hole rowset (same tablet_id + version = same load_id) |
2546 | 1.33k | PUniqueId load_id; |
2547 | 1.33k | load_id.set_hi(tablet->tablet_id()); |
2548 | 1.33k | load_id.set_lo(version); |
2549 | 1.33k | rs_meta->set_load_id(load_id); |
2550 | | |
2551 | | // Copy schema and other metadata from template |
2552 | 1.33k | rs_meta->set_tablet_schema(prev_rowset_meta->tablet_schema()); |
2553 | 1.33k | rs_meta->set_rowset_type(prev_rowset_meta->rowset_type()); |
2554 | 1.33k | rs_meta->set_tablet_schema_hash(prev_rowset_meta->tablet_schema_hash()); |
2555 | 1.33k | rs_meta->set_resource_id(prev_rowset_meta->resource_id()); |
2556 | | |
2557 | | // Basic tablet information |
2558 | 1.33k | rs_meta->set_tablet_id(tablet->tablet_id()); |
2559 | 1.33k | rs_meta->set_index_id(tablet->index_id()); |
2560 | 1.33k | rs_meta->set_partition_id(tablet->partition_id()); |
2561 | 1.33k | rs_meta->set_tablet_uid(tablet->tablet_uid()); |
2562 | 1.33k | rs_meta->set_version(Version(version, version)); |
2563 | 1.33k | rs_meta->set_txn_id(version); |
2564 | | |
2565 | 1.33k | rs_meta->set_num_rows(0); |
2566 | 1.33k | rs_meta->set_total_disk_size(0); |
2567 | 1.33k | rs_meta->set_data_disk_size(0); |
2568 | 1.33k | rs_meta->set_index_disk_size(0); |
2569 | 1.33k | rs_meta->set_empty(true); |
2570 | 1.33k | rs_meta->set_num_segments(0); |
2571 | 1.33k | rs_meta->set_segments_overlap(NONOVERLAPPING); |
2572 | 1.33k | rs_meta->set_rowset_state(VISIBLE); |
2573 | 1.33k | rs_meta->set_creation_time(UnixSeconds()); |
2574 | 1.33k | rs_meta->set_newest_write_timestamp(UnixSeconds()); |
2575 | | |
2576 | 1.33k | Status s = RowsetFactory::create_rowset(nullptr, "", rs_meta, rowset); |
2577 | 1.33k | if (!s.ok()) { |
2578 | 0 | LOG_WARNING("Failed to create empty rowset for hole") |
2579 | 0 | .tag("tablet_id", tablet->tablet_id()) |
2580 | 0 | .tag("version", version) |
2581 | 0 | .error(s); |
2582 | 0 | return s; |
2583 | 0 | } |
2584 | 1.33k | (*rowset)->set_hole_rowset(true); |
2585 | | |
2586 | 1.33k | return Status::OK(); |
2587 | 1.33k | } |
2588 | | |
2589 | 2 | Status CloudMetaMgr::list_snapshot(std::vector<SnapshotInfoPB>& snapshots) { |
2590 | 2 | ListSnapshotRequest req; |
2591 | 2 | ListSnapshotResponse res; |
2592 | 2 | req.set_cloud_unique_id(config::cloud_unique_id); |
2593 | 2 | req.set_include_aborted(true); |
2594 | 2 | RETURN_IF_ERROR(retry_rpc(MetaServiceRPC::LIST_SNAPSHOTS, req, &res, |
2595 | 2 | &MetaService_Stub::list_snapshot, |
2596 | 2 | { |
2597 | 2 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2598 | 2 | .backpressure_handler = ms_backpressure_handler_, |
2599 | 2 | })); |
2600 | 0 | for (auto& snapshot : res.snapshots()) { |
2601 | 0 | snapshots.emplace_back(snapshot); |
2602 | 0 | } |
2603 | 0 | return Status::OK(); |
2604 | 2 | } |
2605 | | |
2606 | | Status CloudMetaMgr::get_snapshot_properties(SnapshotSwitchStatus& switch_status, |
2607 | | int64_t& max_reserved_snapshots, |
2608 | 1 | int64_t& snapshot_interval_seconds) { |
2609 | 1 | GetInstanceRequest req; |
2610 | 1 | GetInstanceResponse res; |
2611 | 1 | req.set_cloud_unique_id(config::cloud_unique_id); |
2612 | 1 | RETURN_IF_ERROR(retry_rpc(MetaServiceRPC::GET_INSTANCE, req, &res, |
2613 | 1 | &MetaService_Stub::get_instance, |
2614 | 1 | { |
2615 | 1 | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2616 | 1 | .backpressure_handler = ms_backpressure_handler_, |
2617 | 1 | })); |
2618 | 1 | switch_status = res.instance().has_snapshot_switch_status() |
2619 | 1 | ? res.instance().snapshot_switch_status() |
2620 | 1 | : SnapshotSwitchStatus::SNAPSHOT_SWITCH_DISABLED; |
2621 | 1 | max_reserved_snapshots = |
2622 | 1 | res.instance().has_max_reserved_snapshot() ? res.instance().max_reserved_snapshot() : 0; |
2623 | 1 | snapshot_interval_seconds = res.instance().has_snapshot_interval_seconds() |
2624 | 1 | ? res.instance().snapshot_interval_seconds() |
2625 | 1 | : 3600; |
2626 | 1 | return Status::OK(); |
2627 | 1 | } |
2628 | | |
2629 | | Status CloudMetaMgr::update_packed_file_info(const std::string& packed_file_path, |
2630 | | const cloud::PackedFileInfoPB& packed_file_info, |
2631 | 12.1k | int64_t table_id) { |
2632 | 12.1k | VLOG_DEBUG << "Updating meta service for packed file: " << packed_file_path << " with " |
2633 | 0 | << packed_file_info.total_slice_num() << " small files" |
2634 | 0 | << ", total bytes: " << packed_file_info.total_slice_bytes(); |
2635 | | |
2636 | | // Create request |
2637 | 12.1k | cloud::UpdatePackedFileInfoRequest req; |
2638 | 12.1k | cloud::UpdatePackedFileInfoResponse resp; |
2639 | | |
2640 | | // Set required fields |
2641 | 12.1k | req.set_cloud_unique_id(config::cloud_unique_id); |
2642 | 12.1k | req.set_packed_file_path(packed_file_path); |
2643 | 12.1k | *req.mutable_packed_file_info() = packed_file_info; |
2644 | | |
2645 | | // Make RPC call using retry pattern |
2646 | 12.1k | return retry_rpc(MetaServiceRPC::UPDATE_PACKED_FILE_INFO, req, &resp, |
2647 | 12.1k | &cloud::MetaService_Stub::update_packed_file_info, |
2648 | 12.1k | { |
2649 | 12.1k | .host_limiters = host_level_ms_rpc_rate_limiters_, |
2650 | 12.1k | .backpressure_handler = ms_backpressure_handler_, |
2651 | 12.1k | .table_id = table_id, |
2652 | 12.1k | }); |
2653 | 12.1k | } |
2654 | | |
2655 | | Status CloudMetaMgr::get_cluster_status( |
2656 | | std::unordered_map<std::string, std::pair<int32_t, int64_t>>* result, |
2657 | 56 | std::string* my_cluster_id) { |
2658 | 56 | GetClusterStatusRequest req; |
2659 | 56 | GetClusterStatusResponse resp; |
2660 | 56 | req.add_cloud_unique_ids(config::cloud_unique_id); |
2661 | | |
2662 | 56 | Status s = retry_rpc(MetaServiceRPC::GET_CLUSTER_STATUS, req, &resp, |
2663 | 56 | &MetaService_Stub::get_cluster_status, |
2664 | 56 | {.host_limiters = host_level_ms_rpc_rate_limiters_}); |
2665 | 56 | if (!s.ok()) { |
2666 | 0 | return s; |
2667 | 0 | } |
2668 | | |
2669 | 56 | result->clear(); |
2670 | 56 | for (const auto& detail : resp.details()) { |
2671 | 56 | for (const auto& cluster : detail.clusters()) { |
2672 | | // Store cluster status and mtime (mtime is in seconds from MS, convert to ms). |
2673 | | // If mtime is not set, use current time as a conservative default |
2674 | | // to avoid immediate takeover due to elapsed being huge. |
2675 | 56 | int64_t mtime_ms = cluster.has_mtime() ? cluster.mtime() * 1000 : UnixMillis(); |
2676 | 56 | (*result)[cluster.cluster_id()] = {static_cast<int32_t>(cluster.cluster_status()), |
2677 | 56 | mtime_ms}; |
2678 | 56 | } |
2679 | 56 | } |
2680 | | |
2681 | 56 | if (my_cluster_id && resp.has_requester_cluster_id()) { |
2682 | 1 | *my_cluster_id = resp.requester_cluster_id(); |
2683 | 1 | } |
2684 | | |
2685 | 56 | return Status::OK(); |
2686 | 56 | } |
2687 | | |
2688 | | } // namespace doris::cloud |