Coverage Report

Created: 2026-08-15 22:55

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