Coverage Report

Created: 2026-08-01 19:46

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