Coverage Report

Created: 2026-05-21 07:49

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