Coverage Report

Created: 2026-08-10 08:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/agent/task_worker_pool.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
18
#include "agent/task_worker_pool.h"
19
20
#include <brpc/controller.h>
21
#include <fmt/format.h>
22
#include <gen_cpp/AgentService_types.h>
23
#include <gen_cpp/DataSinks_types.h>
24
#include <gen_cpp/HeartbeatService_types.h>
25
#include <gen_cpp/MasterService_types.h>
26
#include <gen_cpp/Status_types.h>
27
#include <gen_cpp/Types_types.h>
28
#include <unistd.h>
29
30
#include <algorithm>
31
// IWYU pragma: no_include <bits/chrono.h>
32
#include <thrift/protocol/TDebugProtocol.h>
33
34
#include <atomic>
35
#include <chrono> // IWYU pragma: keep
36
#include <ctime>
37
#include <functional>
38
#include <memory>
39
#include <mutex>
40
#include <shared_mutex>
41
#include <sstream>
42
#include <string>
43
#include <thread>
44
#include <type_traits>
45
#include <utility>
46
#include <vector>
47
48
#include "agent/utils.h"
49
#include "cloud/cloud_delete_task.h"
50
#include "cloud/cloud_engine_calc_delete_bitmap_task.h"
51
#include "cloud/cloud_schema_change_job.h"
52
#include "cloud/cloud_snapshot_loader.h"
53
#include "cloud/cloud_snapshot_mgr.h"
54
#include "cloud/cloud_tablet.h"
55
#include "cloud/cloud_tablet_mgr.h"
56
#include "cloud/config.h"
57
#include "common/config.h"
58
#include "common/logging.h"
59
#include "common/metrics/doris_metrics.h"
60
#include "common/status.h"
61
#include "io/fs/file_system.h"
62
#include "io/fs/hdfs_file_system.h"
63
#include "io/fs/local_file_system.h"
64
#include "io/fs/obj_storage_client.h"
65
#include "io/fs/path.h"
66
#include "io/fs/remote_file_system.h"
67
#include "io/fs/s3_file_system.h"
68
#include "runtime/cluster_info.h"
69
#include "runtime/exec_env.h"
70
#include "runtime/fragment_mgr.h"
71
#include "runtime/index_policy/index_policy_mgr.h"
72
#include "runtime/memory/global_memory_arbitrator.h"
73
#include "runtime/snapshot_loader.h"
74
#include "runtime/user_function_cache.h"
75
#include "service/backend_options.h"
76
#include "storage/compaction/cumulative_compaction_binlog_policy.h"
77
#include "storage/compaction/cumulative_compaction_policy.h"
78
#include "storage/compaction/cumulative_compaction_time_series_policy.h"
79
#include "storage/data_dir.h"
80
#include "storage/olap_common.h"
81
#include "storage/rowset/rowset_meta.h"
82
#include "storage/snapshot/snapshot_manager.h"
83
#include "storage/storage_engine.h"
84
#include "storage/storage_policy.h"
85
#include "storage/tablet/tablet.h"
86
#include "storage/tablet/tablet_manager.h"
87
#include "storage/tablet/tablet_meta.h"
88
#include "storage/tablet/tablet_schema.h"
89
#include "storage/task/engine_batch_load_task.h"
90
#include "storage/task/engine_checksum_task.h"
91
#include "storage/task/engine_clone_task.h"
92
#include "storage/task/engine_cloud_index_change_task.h"
93
#include "storage/task/engine_index_change_task.h"
94
#include "storage/task/engine_publish_version_task.h"
95
#include "storage/task/engine_storage_migration_task.h"
96
#include "storage/txn/txn_manager.h"
97
#include "storage/utils.h"
98
#include "udf/python/python_server.h"
99
#include "util/brpc_client_cache.h"
100
#include "util/debug_points.h"
101
#include "util/jni-util.h"
102
#include "util/mem_info.h"
103
#include "util/random.h"
104
#include "util/s3_util.h"
105
#include "util/stopwatch.hpp"
106
#include "util/threadpool.h"
107
#include "util/time.h"
108
#include "util/trace.h"
109
110
namespace doris {
111
using namespace ErrorCode;
112
113
namespace {
114
115
std::mutex s_task_signatures_mtx;
116
std::unordered_map<TTaskType::type, std::unordered_set<int64_t>> s_task_signatures;
117
118
std::atomic_ulong s_report_version(time(nullptr) * 100000);
119
120
20.5k
void increase_report_version() {
121
20.5k
    s_report_version.fetch_add(1, std::memory_order_relaxed);
122
20.5k
}
123
124
// FIXME(plat1ko): Paired register and remove task info
125
77.2k
bool register_task_info(const TTaskType::type task_type, int64_t signature) {
126
77.2k
    if (task_type == TTaskType::type::PUSH_STORAGE_POLICY ||
127
77.2k
        task_type == TTaskType::type::PUSH_COOLDOWN_CONF ||
128
77.2k
        task_type == TTaskType::type::COMPACTION) {
129
        // no need to report task of these types
130
16
        return true;
131
16
    }
132
133
77.2k
    if (signature == -1) { // No need to report task with unintialized signature
134
5.96k
        return true;
135
5.96k
    }
136
137
71.3k
    std::lock_guard lock(s_task_signatures_mtx);
138
71.3k
    auto& set = s_task_signatures[task_type];
139
71.3k
    return set.insert(signature).second;
140
77.2k
}
141
142
43.3k
void remove_task_info(const TTaskType::type task_type, int64_t signature) {
143
43.3k
    size_t queue_size;
144
43.3k
    {
145
43.3k
        std::lock_guard lock(s_task_signatures_mtx);
146
43.3k
        auto& set = s_task_signatures[task_type];
147
43.3k
        set.erase(signature);
148
43.3k
        queue_size = set.size();
149
43.3k
    }
150
151
18.4E
    VLOG_NOTICE << "remove task info. type=" << task_type << ", signature=" << signature
152
18.4E
                << ", queue_size=" << queue_size;
153
43.3k
}
154
155
42.7k
void finish_task(const TFinishTaskRequest& finish_task_request) {
156
    // Return result to FE
157
42.7k
    TMasterResult result;
158
42.7k
    uint32_t try_time = 0;
159
42.7k
    constexpr int TASK_FINISH_MAX_RETRY = 3;
160
43.1k
    while (try_time < TASK_FINISH_MAX_RETRY) {
161
43.1k
        DorisMetrics::instance()->finish_task_requests_total->increment(1);
162
43.1k
        Status client_status =
163
43.1k
                MasterServerClient::instance()->finish_task(finish_task_request, &result);
164
165
43.3k
        if (client_status.ok()) {
166
43.3k
            break;
167
18.4E
        } else {
168
18.4E
            DorisMetrics::instance()->finish_task_requests_failed->increment(1);
169
18.4E
            LOG_WARNING("failed to finish task")
170
18.4E
                    .tag("type", finish_task_request.task_type)
171
18.4E
                    .tag("signature", finish_task_request.signature)
172
18.4E
                    .error(result.status);
173
18.4E
            try_time += 1;
174
18.4E
        }
175
18.4E
        sleep(1);
176
18.4E
    }
177
42.7k
}
178
179
Status get_tablet_info(StorageEngine& engine, const TTabletId tablet_id,
180
20
                       const TSchemaHash schema_hash, TTabletInfo* tablet_info) {
181
20
    tablet_info->__set_tablet_id(tablet_id);
182
20
    tablet_info->__set_schema_hash(schema_hash);
183
20
    return engine.tablet_manager()->report_tablet_info(tablet_info);
184
20
}
185
186
1.31k
void random_sleep(int second) {
187
1.31k
    Random rnd(static_cast<uint32_t>(UnixMillis()));
188
1.31k
    sleep(rnd.Uniform(second) + 1);
189
1.31k
}
190
191
void alter_tablet(StorageEngine& engine, const TAgentTaskRequest& agent_task_req, int64_t signature,
192
20
                  const TTaskType::type task_type, TFinishTaskRequest* finish_task_request) {
193
20
    Status status;
194
195
20
    std::string_view process_name = "alter tablet";
196
    // Check last schema change status, if failed delete tablet file
197
    // Do not need to adjust delete success or not
198
    // Because if delete failed create rollup will failed
199
20
    TTabletId new_tablet_id = 0;
200
20
    TSchemaHash new_schema_hash = 0;
201
20
    if (status.ok()) {
202
20
        new_tablet_id = agent_task_req.alter_tablet_req_v2.new_tablet_id;
203
20
        new_schema_hash = agent_task_req.alter_tablet_req_v2.new_schema_hash;
204
20
        auto mem_tracker = MemTrackerLimiter::create_shared(
205
20
                MemTrackerLimiter::Type::SCHEMA_CHANGE,
206
20
                fmt::format("EngineAlterTabletTask#baseTabletId={}:newTabletId={}",
207
20
                            std::to_string(agent_task_req.alter_tablet_req_v2.base_tablet_id),
208
20
                            std::to_string(agent_task_req.alter_tablet_req_v2.new_tablet_id),
209
20
                            engine.memory_limitation_bytes_per_thread_for_schema_change()));
210
20
        SCOPED_ATTACH_TASK(mem_tracker);
211
20
        DorisMetrics::instance()->create_rollup_requests_total->increment(1);
212
20
        Status res = Status::OK();
213
20
        try {
214
20
            LOG_INFO("start {}", process_name)
215
20
                    .tag("signature", agent_task_req.signature)
216
20
                    .tag("base_tablet_id", agent_task_req.alter_tablet_req_v2.base_tablet_id)
217
20
                    .tag("new_tablet_id", new_tablet_id)
218
20
                    .tag("mem_limit",
219
20
                         engine.memory_limitation_bytes_per_thread_for_schema_change());
220
20
            SchemaChangeJob job(engine, agent_task_req.alter_tablet_req_v2,
221
20
                                std::to_string(agent_task_req.alter_tablet_req_v2.__isset.job_id
222
20
                                                       ? agent_task_req.alter_tablet_req_v2.job_id
223
20
                                                       : 0));
224
20
            status = job.process_alter_tablet(agent_task_req.alter_tablet_req_v2);
225
20
        } catch (const Exception& e) {
226
0
            status = e.to_status();
227
0
        }
228
20
        if (!status.ok()) {
229
0
            DorisMetrics::instance()->create_rollup_requests_failed->increment(1);
230
0
        }
231
20
    }
232
233
20
    if (status.ok()) {
234
20
        increase_report_version();
235
20
    }
236
237
    // Return result to fe
238
20
    finish_task_request->__set_backend(BackendOptions::get_local_backend());
239
20
    finish_task_request->__set_report_version(s_report_version);
240
20
    finish_task_request->__set_task_type(task_type);
241
20
    finish_task_request->__set_signature(signature);
242
243
20
    std::vector<TTabletInfo> finish_tablet_infos;
244
20
    if (status.ok()) {
245
20
        TTabletInfo tablet_info;
246
20
        status = get_tablet_info(engine, new_tablet_id, new_schema_hash, &tablet_info);
247
20
        if (status.ok()) {
248
18
            finish_tablet_infos.push_back(tablet_info);
249
18
        }
250
20
    }
251
252
20
    if (!status.ok() && !status.is<NOT_IMPLEMENTED_ERROR>()) {
253
0
        LOG_WARNING("failed to {}", process_name)
254
0
                .tag("signature", agent_task_req.signature)
255
0
                .tag("base_tablet_id", agent_task_req.alter_tablet_req_v2.base_tablet_id)
256
0
                .tag("new_tablet_id", new_tablet_id)
257
0
                .error(status);
258
20
    } else {
259
20
        finish_task_request->__set_finish_tablet_infos(finish_tablet_infos);
260
20
        LOG_INFO("successfully {}", process_name)
261
20
                .tag("signature", agent_task_req.signature)
262
20
                .tag("base_tablet_id", agent_task_req.alter_tablet_req_v2.base_tablet_id)
263
20
                .tag("new_tablet_id", new_tablet_id);
264
20
    }
265
20
    finish_task_request->__set_task_status(status.to_thrift());
266
20
}
267
268
void alter_cloud_tablet(CloudStorageEngine& engine, const TAgentTaskRequest& agent_task_req,
269
                        int64_t signature, const TTaskType::type task_type,
270
9.47k
                        TFinishTaskRequest* finish_task_request) {
271
9.47k
    Status status;
272
273
9.47k
    std::string_view process_name = "alter tablet";
274
    // Check last schema change status, if failed delete tablet file
275
    // Do not need to adjust delete success or not
276
    // Because if delete failed create rollup will failed
277
9.47k
    TTabletId new_tablet_id = 0;
278
9.47k
    new_tablet_id = agent_task_req.alter_tablet_req_v2.new_tablet_id;
279
9.47k
    auto mem_tracker = MemTrackerLimiter::create_shared(
280
9.47k
            MemTrackerLimiter::Type::SCHEMA_CHANGE,
281
9.47k
            fmt::format("EngineAlterTabletTask#baseTabletId={}:newTabletId={}",
282
9.47k
                        std::to_string(agent_task_req.alter_tablet_req_v2.base_tablet_id),
283
9.47k
                        std::to_string(agent_task_req.alter_tablet_req_v2.new_tablet_id),
284
9.47k
                        engine.memory_limitation_bytes_per_thread_for_schema_change()));
285
9.47k
    SCOPED_ATTACH_TASK(mem_tracker);
286
9.47k
    DorisMetrics::instance()->create_rollup_requests_total->increment(1);
287
288
9.47k
    LOG_INFO("start {}", process_name)
289
9.47k
            .tag("signature", agent_task_req.signature)
290
9.47k
            .tag("base_tablet_id", agent_task_req.alter_tablet_req_v2.base_tablet_id)
291
9.47k
            .tag("new_tablet_id", new_tablet_id)
292
9.47k
            .tag("mem_limit", engine.memory_limitation_bytes_per_thread_for_schema_change());
293
9.47k
    DCHECK(agent_task_req.alter_tablet_req_v2.__isset.job_id);
294
9.47k
    CloudSchemaChangeJob job(engine, std::to_string(agent_task_req.alter_tablet_req_v2.job_id),
295
9.47k
                             agent_task_req.alter_tablet_req_v2.expiration);
296
9.47k
    status = [&]() {
297
9.47k
        HANDLE_EXCEPTION_IF_CATCH_EXCEPTION(
298
9.47k
                job.process_alter_tablet(agent_task_req.alter_tablet_req_v2),
299
9.47k
                [&](const doris::Exception& ex) {
300
9.47k
                    DorisMetrics::instance()->create_rollup_requests_failed->increment(1);
301
9.47k
                    job.clean_up_on_failure();
302
9.47k
                });
303
9.14k
        return Status::OK();
304
9.47k
    }();
305
306
9.47k
    if (status.ok()) {
307
8.95k
        increase_report_version();
308
8.95k
        LOG_INFO("successfully {}", process_name)
309
8.95k
                .tag("signature", agent_task_req.signature)
310
8.95k
                .tag("base_tablet_id", agent_task_req.alter_tablet_req_v2.base_tablet_id)
311
8.95k
                .tag("new_tablet_id", new_tablet_id);
312
8.95k
    } else {
313
514
        LOG_WARNING("failed to {}", process_name)
314
514
                .tag("signature", agent_task_req.signature)
315
514
                .tag("base_tablet_id", agent_task_req.alter_tablet_req_v2.base_tablet_id)
316
514
                .tag("new_tablet_id", new_tablet_id)
317
514
                .error(status);
318
514
    }
319
320
    // Return result to fe
321
9.47k
    finish_task_request->__set_backend(BackendOptions::get_local_backend());
322
9.47k
    finish_task_request->__set_report_version(s_report_version);
323
9.47k
    finish_task_request->__set_task_type(task_type);
324
9.47k
    finish_task_request->__set_signature(signature);
325
9.47k
    finish_task_request->__set_task_status(status.to_thrift());
326
9.47k
}
327
328
Status check_migrate_request(StorageEngine& engine, const TStorageMediumMigrateReq& req,
329
0
                             TabletSharedPtr& tablet, DataDir** dest_store) {
330
0
    int64_t tablet_id = req.tablet_id;
331
0
    tablet = engine.tablet_manager()->get_tablet(tablet_id);
332
0
    if (tablet == nullptr) {
333
0
        return Status::InternalError("could not find tablet {}", tablet_id);
334
0
    }
335
336
0
    if (req.__isset.data_dir) {
337
        // request specify the data dir
338
0
        *dest_store = engine.get_store(req.data_dir);
339
0
        if (*dest_store == nullptr) {
340
0
            return Status::InternalError("could not find data dir {}", req.data_dir);
341
0
        }
342
0
    } else {
343
        // this is a storage medium
344
        // get data dir by storage medium
345
346
        // judge case when no need to migrate
347
0
        uint32_t count = engine.available_storage_medium_type_count();
348
0
        if (count <= 1) {
349
0
            return Status::InternalError("available storage medium type count is less than 1");
350
0
        }
351
        // check current tablet storage medium
352
0
        TStorageMedium::type storage_medium = req.storage_medium;
353
0
        TStorageMedium::type src_storage_medium = tablet->data_dir()->storage_medium();
354
0
        if (src_storage_medium == storage_medium) {
355
0
            return Status::InternalError("tablet is already on specified storage medium {}",
356
0
                                         storage_medium);
357
0
        }
358
        // get a random store of specified storage medium
359
0
        auto stores = engine.get_stores_for_create_tablet(tablet->partition_id(), storage_medium);
360
0
        if (stores.empty()) {
361
0
            return Status::InternalError("failed to get root path for create tablet");
362
0
        }
363
364
0
        *dest_store = stores[0];
365
0
    }
366
0
    if (tablet->data_dir()->path() == (*dest_store)->path()) {
367
0
        LOG_WARNING("tablet is already on specified path").tag("path", tablet->data_dir()->path());
368
0
        return Status::Error<FILE_ALREADY_EXIST, false>("tablet is already on specified path: {}",
369
0
                                                        tablet->data_dir()->path());
370
0
    }
371
372
    // check local disk capacity
373
0
    int64_t tablet_size = tablet->tablet_local_size();
374
0
    if ((*dest_store)->reach_capacity_limit(tablet_size)) {
375
0
        return Status::Error<EXCEEDED_LIMIT>("reach the capacity limit of path {}, tablet_size={}",
376
0
                                             (*dest_store)->path(), tablet_size);
377
0
    }
378
0
    return Status::OK();
379
0
}
380
381
// Return `true` if report success
382
bool handle_report(const TReportRequest& request, const ClusterInfo* cluster_info,
383
2.99k
                   std::string_view name) {
384
2.99k
    TMasterResult result;
385
2.99k
    Status status = MasterServerClient::instance()->report(request, &result);
386
2.99k
    if (!status.ok()) [[unlikely]] {
387
0
        LOG_WARNING("failed to report {}", name)
388
0
                .tag("host", cluster_info->master_fe_addr.hostname)
389
0
                .tag("port", cluster_info->master_fe_addr.port)
390
0
                .error(status);
391
0
        return false;
392
0
    }
393
394
2.99k
    else if (result.status.status_code != TStatusCode::OK) [[unlikely]] {
395
0
        LOG_WARNING("failed to report {}", name)
396
0
                .tag("host", cluster_info->master_fe_addr.hostname)
397
0
                .tag("port", cluster_info->master_fe_addr.port)
398
0
                .error(result.status);
399
0
        return false;
400
0
    }
401
402
2.99k
    return true;
403
2.99k
}
404
405
Status _submit_task(const TAgentTaskRequest& task,
406
77.2k
                    std::function<Status(const TAgentTaskRequest&)> submit_op) {
407
77.2k
    const TTaskType::type task_type = task.task_type;
408
77.2k
    int64_t signature = task.signature;
409
410
77.2k
    std::string type_str;
411
77.2k
    EnumToString(TTaskType, task_type, type_str);
412
18.4E
    VLOG_CRITICAL << "submitting task. type=" << type_str << ", signature=" << signature;
413
414
77.2k
    if (!register_task_info(task_type, signature)) {
415
488
        LOG_WARNING("failed to register task").tag("type", type_str).tag("signature", signature);
416
        // Duplicated task request, just return OK
417
488
        return Status::OK();
418
488
    }
419
420
    // TODO(plat1ko): check task request member
421
422
    // Set the receiving time of task so that we can determine whether it is timed out later
423
    // exist a path task_worker_pool <- agent_server <- backend_service <- BackendService
424
    // use the arg BackendService_submit_tasks_args.tasks is not const, so modify is ok
425
76.7k
    (const_cast<TAgentTaskRequest&>(task)).__set_recv_time(time(nullptr));
426
76.7k
    auto st = submit_op(task);
427
76.7k
    if (!st.ok()) [[unlikely]] {
428
1
        LOG_INFO("failed to submit task").tag("type", type_str).tag("signature", signature);
429
1
        return st;
430
1
    }
431
432
76.7k
    LOG_INFO("successfully submit task").tag("type", type_str).tag("signature", signature);
433
76.7k
    return Status::OK();
434
76.7k
}
435
436
bvar::LatencyRecorder g_publish_version_latency("doris_pk", "publish_version");
437
438
bvar::Adder<uint64_t> ALTER_INVERTED_INDEX_count("task", "ALTER_INVERTED_INDEX");
439
bvar::Adder<uint64_t> CHECK_CONSISTENCY_count("task", "CHECK_CONSISTENCY");
440
bvar::Adder<uint64_t> UPLOAD_count("task", "UPLOAD");
441
bvar::Adder<uint64_t> DOWNLOAD_count("task", "DOWNLOAD");
442
bvar::Adder<uint64_t> MAKE_SNAPSHOT_count("task", "MAKE_SNAPSHOT");
443
bvar::Adder<uint64_t> RELEASE_SNAPSHOT_count("task", "RELEASE_SNAPSHOT");
444
bvar::Adder<uint64_t> MOVE_count("task", "MOVE");
445
bvar::Adder<uint64_t> COMPACTION_count("task", "COMPACTION");
446
bvar::Adder<uint64_t> PUSH_STORAGE_POLICY_count("task", "PUSH_STORAGE_POLICY");
447
bvar::Adder<uint64_t> PUSH_INDEX_POLICY_count("task", "PUSH_INDEX_POLICY");
448
bvar::Adder<uint64_t> PUSH_COOLDOWN_CONF_count("task", "PUSH_COOLDOWN_CONF");
449
bvar::Adder<uint64_t> CREATE_count("task", "CREATE_TABLE");
450
bvar::Adder<uint64_t> DROP_count("task", "DROP_TABLE");
451
bvar::Adder<uint64_t> PUBLISH_VERSION_count("task", "PUBLISH_VERSION");
452
bvar::Adder<uint64_t> CLEAR_TRANSACTION_TASK_count("task", "CLEAR_TRANSACTION_TASK");
453
bvar::Adder<uint64_t> DELETE_count("task", "DELETE");
454
bvar::Adder<uint64_t> PUSH_count("task", "PUSH");
455
bvar::Adder<uint64_t> UPDATE_TABLET_META_INFO_count("task", "UPDATE_TABLET_META_INFO");
456
bvar::Adder<uint64_t> ALTER_count("task", "ALTER_TABLE");
457
bvar::Adder<uint64_t> CLONE_count("task", "CLONE");
458
bvar::Adder<uint64_t> STORAGE_MEDIUM_MIGRATE_count("task", "STORAGE_MEDIUM_MIGRATE");
459
bvar::Adder<uint64_t> GC_BINLOG_count("task", "GC_BINLOG");
460
bvar::Adder<uint64_t> UPDATE_VISIBLE_VERSION_count("task", "UPDATE_VISIBLE_VERSION");
461
bvar::Adder<uint64_t> CALCULATE_DELETE_BITMAP_count("task", "CALCULATE_DELETE_BITMAP");
462
463
153k
void add_task_count(const TAgentTaskRequest& task, int n) {
464
    // clang-format off
465
153k
    switch (task.task_type) {
466
0
    #define ADD_TASK_COUNT(type) \
467
73.1k
    case TTaskType::type:        \
468
146k
        type##_count << n;       \
469
73.1k
        return;
470
1.17k
    ADD_TASK_COUNT(ALTER_INVERTED_INDEX)
471
0
    ADD_TASK_COUNT(CHECK_CONSISTENCY)
472
32
    ADD_TASK_COUNT(UPLOAD)
473
44
    ADD_TASK_COUNT(DOWNLOAD)
474
640
    ADD_TASK_COUNT(MAKE_SNAPSHOT)
475
640
    ADD_TASK_COUNT(RELEASE_SNAPSHOT)
476
344
    ADD_TASK_COUNT(MOVE)
477
6
    ADD_TASK_COUNT(COMPACTION)
478
22
    ADD_TASK_COUNT(PUSH_STORAGE_POLICY)
479
32
    ADD_TASK_COUNT(PUSH_INDEX_POLICY)
480
4
    ADD_TASK_COUNT(PUSH_COOLDOWN_CONF)
481
16.2k
    ADD_TASK_COUNT(CREATE)
482
11.9k
    ADD_TASK_COUNT(DROP)
483
12.2k
    ADD_TASK_COUNT(PUBLISH_VERSION)
484
44
    ADD_TASK_COUNT(CLEAR_TRANSACTION_TASK)
485
0
    ADD_TASK_COUNT(UPDATE_TABLET_META_INFO)
486
0
    ADD_TASK_COUNT(CLONE)
487
0
    ADD_TASK_COUNT(STORAGE_MEDIUM_MIGRATE)
488
0
    ADD_TASK_COUNT(GC_BINLOG)
489
11.8k
    ADD_TASK_COUNT(UPDATE_VISIBLE_VERSION)
490
17.9k
    ADD_TASK_COUNT(CALCULATE_DELETE_BITMAP)
491
0
    #undef ADD_TASK_COUNT
492
6.41k
    case TTaskType::REALTIME_PUSH:
493
6.41k
    case TTaskType::PUSH:
494
6.41k
        if (task.push_req.push_type == TPushType::LOAD_V2) {
495
0
            PUSH_count << n;
496
6.41k
        } else if (task.push_req.push_type == TPushType::DELETE) {
497
6.41k
            DELETE_count << n;
498
6.41k
        }
499
6.41k
        return;
500
18.9k
    case TTaskType::ALTER:
501
18.9k
    {
502
18.9k
        ALTER_count << n;
503
        // cloud auto stop need sc jobs, a tablet's sc can also be considered a fragment
504
18.9k
        if (n > 0) {
505
            // only count fragment when task is actually starting
506
9.49k
            doris::g_fragment_executing_count << 1;
507
9.49k
            int64_t now = duration_cast<std::chrono::milliseconds>(
508
9.49k
                                std::chrono::system_clock::now().time_since_epoch())
509
9.49k
                                .count();
510
9.49k
            g_fragment_last_active_time.set_value(now);
511
9.49k
        }
512
18.9k
        return;
513
6.41k
    }
514
54.9k
    default:
515
54.9k
        return;
516
153k
    }
517
    // clang-format on
518
153k
}
519
520
bvar::Adder<uint64_t> report_task_total("report", "task_total");
521
bvar::Adder<uint64_t> report_task_failed("report", "task_failed");
522
bvar::Adder<uint64_t> report_disk_total("report", "disk_total");
523
bvar::Adder<uint64_t> report_disk_failed("report", "disk_failed");
524
bvar::Adder<uint64_t> report_tablet_total("report", "tablet_total");
525
bvar::Adder<uint64_t> report_tablet_failed("report", "tablet_failed");
526
bvar::Adder<uint64_t> report_index_policy_total("report", "index_policy_total");
527
bvar::Adder<uint64_t> report_index_policy_failed("report", "index_policy_failed");
528
529
} // namespace
530
531
TaskWorkerPool::TaskWorkerPool(
532
        std::string_view name, int worker_count,
533
        std::function<void(const TAgentTaskRequest& task)> callback,
534
        std::function<void(const TAgentTaskRequest& task)> pre_submit_callback)
535
129
        : _callback(std::move(callback)), _pre_submit_callback(std::move(pre_submit_callback)) {
536
129
    auto st = ThreadPoolBuilder(fmt::format("TaskWP_{}", name))
537
129
                      .set_min_threads(worker_count)
538
129
                      .set_max_threads(worker_count)
539
129
                      .build(&_thread_pool);
540
129
    CHECK(st.ok()) << name << ": " << st;
541
129
}
542
543
49
TaskWorkerPool::~TaskWorkerPool() {
544
49
    stop();
545
49
}
546
547
54
void TaskWorkerPool::stop() {
548
54
    if (_stopped.exchange(true)) {
549
5
        return;
550
5
    }
551
552
49
    if (_thread_pool) {
553
49
        _thread_pool->shutdown();
554
49
    }
555
49
}
556
557
77.2k
Status TaskWorkerPool::submit_task(const TAgentTaskRequest& task) {
558
77.2k
    return _submit_task(task, [this](auto&& task) {
559
76.8k
        if (_pre_submit_callback) {
560
9.47k
            _pre_submit_callback(task);
561
9.47k
        }
562
76.8k
        add_task_count(task, 1);
563
76.8k
        return _thread_pool->submit_func([this, task]() {
564
76.8k
            _callback(task);
565
76.8k
            add_task_count(task, -1);
566
76.8k
        });
567
76.8k
    });
568
77.2k
}
569
570
PriorTaskWorkerPool::PriorTaskWorkerPool(
571
        const std::string& name, int normal_worker_count, int high_prior_worker_count,
572
        std::function<void(const TAgentTaskRequest& task)> callback)
573
11
        : _callback(std::move(callback)) {
574
42
    for (int i = 0; i < normal_worker_count; ++i) {
575
31
        auto st = Thread::create(
576
31
                "Normal", name, [this] { normal_loop(); }, &_workers.emplace_back());
577
31
        CHECK(st.ok()) << name << ": " << st;
578
31
    }
579
580
42
    for (int i = 0; i < high_prior_worker_count; ++i) {
581
31
        auto st = Thread::create(
582
31
                "HighPrior", name, [this] { high_prior_loop(); }, &_workers.emplace_back());
583
31
        CHECK(st.ok()) << name << ": " << st;
584
31
    }
585
11
}
586
587
5
PriorTaskWorkerPool::~PriorTaskWorkerPool() {
588
5
    stop();
589
5
}
590
591
8
void PriorTaskWorkerPool::stop() {
592
8
    {
593
8
        std::lock_guard lock(_mtx);
594
8
        if (_stopped) {
595
3
            return;
596
3
        }
597
598
5
        _stopped = true;
599
5
    }
600
0
    _normal_condv.notify_all();
601
5
    _high_prior_condv.notify_all();
602
603
26
    for (auto&& w : _workers) {
604
26
        if (w) {
605
26
            w->join();
606
26
        }
607
26
    }
608
5
}
609
610
6
Status PriorTaskWorkerPool::submit_task(const TAgentTaskRequest& task) {
611
6
    return _submit_task(task, [this](auto&& task) {
612
6
        auto req = std::make_unique<TAgentTaskRequest>(task);
613
6
        add_task_count(*req, 1);
614
6
        if (req->__isset.priority && req->priority == TPriority::HIGH) {
615
4
            std::lock_guard lock(_mtx);
616
4
            _high_prior_queue.push_back(std::move(req));
617
4
            _high_prior_condv.notify_one();
618
4
            _normal_condv.notify_one();
619
4
        } else {
620
2
            std::lock_guard lock(_mtx);
621
2
            _normal_queue.push_back(std::move(req));
622
2
            _normal_condv.notify_one();
623
2
        }
624
6
        return Status::OK();
625
6
    });
626
6
}
627
628
0
Status PriorTaskWorkerPool::submit_high_prior_and_cancel_low(TAgentTaskRequest& task) {
629
0
    const TTaskType::type task_type = task.task_type;
630
0
    int64_t signature = task.signature;
631
0
    std::string type_str;
632
0
    EnumToString(TTaskType, task_type, type_str);
633
0
    auto req = std::make_unique<TAgentTaskRequest>(task);
634
635
0
    DCHECK(req->__isset.priority && req->priority == TPriority::HIGH);
636
0
    do {
637
0
        std::lock_guard lock(s_task_signatures_mtx);
638
0
        auto& set = s_task_signatures[task_type];
639
0
        if (!set.contains(signature)) {
640
            // If it doesn't exist, put it directly into the priority queue
641
0
            add_task_count(*req, 1);
642
0
            set.insert(signature);
643
0
            std::lock_guard temp_lock(_mtx);
644
0
            _high_prior_queue.push_back(std::move(req));
645
0
            _high_prior_condv.notify_one();
646
0
            _normal_condv.notify_one();
647
0
            break;
648
0
        } else {
649
0
            std::lock_guard temp_lock(_mtx);
650
0
            for (auto it = _normal_queue.begin(); it != _normal_queue.end();) {
651
                // If it exists in the normal queue, cancel the task in the normal queue
652
0
                if ((*it)->signature == signature) {
653
0
                    _normal_queue.erase(it);                     // cancel the original task
654
0
                    _high_prior_queue.push_back(std::move(req)); // add the new task to the queue
655
0
                    _high_prior_condv.notify_one();
656
0
                    _normal_condv.notify_one();
657
0
                    break;
658
0
                } else {
659
0
                    ++it; // doesn't meet the condition, continue to the next one
660
0
                }
661
0
            }
662
            // If it exists in the high priority queue, no operation is needed
663
0
            LOG_INFO("task has already existed in high prior queue.").tag("signature", signature);
664
0
        }
665
0
    } while (false);
666
667
    // Set the receiving time of task so that we can determine whether it is timed out later
668
0
    task.__set_recv_time(time(nullptr));
669
670
0
    LOG_INFO("successfully submit task").tag("type", type_str).tag("signature", signature);
671
0
    return Status::OK();
672
0
}
673
674
31
void PriorTaskWorkerPool::normal_loop() {
675
52
    while (true) {
676
34
        std::unique_ptr<TAgentTaskRequest> req;
677
678
34
        {
679
34
            std::unique_lock lock(_mtx);
680
50
            _normal_condv.wait(lock, [&] {
681
50
                return !_normal_queue.empty() || !_high_prior_queue.empty() || _stopped;
682
50
            });
683
684
34
            if (_stopped) {
685
13
                return;
686
13
            }
687
688
21
            if (!_high_prior_queue.empty()) {
689
1
                req = std::move(_high_prior_queue.front());
690
1
                _high_prior_queue.pop_front();
691
20
            } else if (!_normal_queue.empty()) {
692
2
                req = std::move(_normal_queue.front());
693
2
                _normal_queue.pop_front();
694
18
            } else {
695
18
                continue;
696
18
            }
697
21
        }
698
699
3
        _callback(*req);
700
3
        add_task_count(*req, -1);
701
3
    }
702
31
}
703
704
31
void PriorTaskWorkerPool::high_prior_loop() {
705
51
    while (true) {
706
33
        std::unique_ptr<TAgentTaskRequest> req;
707
708
33
        {
709
33
            std::unique_lock lock(_mtx);
710
48
            _high_prior_condv.wait(lock, [&] { return !_high_prior_queue.empty() || _stopped; });
711
712
33
            if (_stopped) {
713
13
                return;
714
13
            }
715
716
20
            if (_high_prior_queue.empty()) {
717
0
                continue;
718
0
            }
719
720
20
            req = std::move(_high_prior_queue.front());
721
20
            _high_prior_queue.pop_front();
722
20
        }
723
724
0
        _callback(*req);
725
20
        add_task_count(*req, -1);
726
20
    }
727
31
}
728
729
ReportWorker::ReportWorker(std::string name, const ClusterInfo* cluster_info, int report_interval_s,
730
                           std::function<void()> callback)
731
25
        : _name(std::move(name)) {
732
25
    auto report_loop = [this, cluster_info, report_interval_s, callback = std::move(callback)] {
733
25
        auto& engine = ExecEnv::GetInstance()->storage_engine();
734
25
        engine.register_report_listener(this);
735
3.08k
        while (true) {
736
3.07k
            {
737
3.07k
                std::unique_lock lock(_mtx);
738
3.07k
                _condv.wait_for(lock, std::chrono::seconds(report_interval_s),
739
6.12k
                                [&] { return _stopped || _signal; });
740
741
3.07k
                if (_stopped) {
742
9
                    break;
743
9
                }
744
745
3.06k
                if (_signal) {
746
                    // Consume received signal
747
52
                    _signal = false;
748
52
                }
749
3.06k
            }
750
751
3.06k
            if (cluster_info->master_fe_addr.port == 0) {
752
                // port == 0 means not received heartbeat yet
753
43
                LOG(INFO) << "waiting to receive first heartbeat from frontend before doing report";
754
43
                continue;
755
43
            }
756
757
3.02k
            callback();
758
3.02k
        }
759
25
        engine.deregister_report_listener(this);
760
25
    };
761
762
25
    auto st = Thread::create("ReportWorker", _name, report_loop, &_thread);
763
25
    CHECK(st.ok()) << _name << ": " << st;
764
25
}
765
766
9
ReportWorker::~ReportWorker() {
767
9
    stop();
768
9
}
769
770
53
void ReportWorker::notify() {
771
53
    {
772
53
        std::lock_guard lock(_mtx);
773
53
        _signal = true;
774
53
    }
775
53
    _condv.notify_all();
776
53
}
777
778
10
void ReportWorker::stop() {
779
10
    {
780
10
        std::lock_guard lock(_mtx);
781
10
        if (_stopped) {
782
1
            return;
783
1
        }
784
785
9
        _stopped = true;
786
9
    }
787
0
    _condv.notify_all();
788
9
    if (_thread) {
789
9
        _thread->join();
790
9
    }
791
9
}
792
793
586
void alter_cloud_index_callback(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
794
586
    const auto& alter_inverted_index_rq = req.alter_inverted_index_req;
795
586
    LOG(INFO) << "[index_change]get alter index task. signature=" << req.signature
796
586
              << ", tablet_id=" << alter_inverted_index_rq.tablet_id
797
586
              << ", job_id=" << alter_inverted_index_rq.job_id;
798
799
586
    Status status = Status::OK();
800
586
    auto tablet_ptr = engine.tablet_mgr().get_tablet(alter_inverted_index_rq.tablet_id);
801
586
    if (tablet_ptr != nullptr) {
802
585
        EngineCloudIndexChangeTask engine_task(engine, req.alter_inverted_index_req);
803
585
        status = engine_task.execute();
804
585
    } else {
805
1
        status = Status::NotFound("could not find tablet {}", alter_inverted_index_rq.tablet_id);
806
1
    }
807
808
    // Return result to fe
809
586
    TFinishTaskRequest finish_task_request;
810
586
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
811
586
    finish_task_request.__set_task_type(req.task_type);
812
586
    finish_task_request.__set_signature(req.signature);
813
586
    if (!status.ok()) {
814
9
        LOG(WARNING) << "[index_change]failed to alter inverted index task, signature="
815
9
                     << req.signature << ", tablet_id=" << alter_inverted_index_rq.tablet_id
816
9
                     << ", job_id=" << alter_inverted_index_rq.job_id << ", error=" << status;
817
577
    } else {
818
577
        LOG(INFO) << "[index_change]successfully alter inverted index task, signature="
819
577
                  << req.signature << ", tablet_id=" << alter_inverted_index_rq.tablet_id
820
577
                  << ", job_id=" << alter_inverted_index_rq.job_id;
821
577
    }
822
586
    finish_task_request.__set_task_status(status.to_thrift());
823
586
    finish_task(finish_task_request);
824
586
    remove_task_info(req.task_type, req.signature);
825
586
}
826
827
0
void alter_inverted_index_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
828
0
    const auto& alter_inverted_index_rq = req.alter_inverted_index_req;
829
0
    LOG(INFO) << "get alter inverted index task. signature=" << req.signature
830
0
              << ", tablet_id=" << alter_inverted_index_rq.tablet_id
831
0
              << ", job_id=" << alter_inverted_index_rq.job_id;
832
833
0
    Status status = Status::OK();
834
0
    auto tablet_ptr = engine.tablet_manager()->get_tablet(alter_inverted_index_rq.tablet_id);
835
0
    if (tablet_ptr != nullptr) {
836
0
        EngineIndexChangeTask engine_task(engine, alter_inverted_index_rq);
837
0
        SCOPED_ATTACH_TASK(engine_task.mem_tracker());
838
0
        status = engine_task.execute();
839
0
    } else {
840
0
        status = Status::NotFound("could not find tablet {}", alter_inverted_index_rq.tablet_id);
841
0
    }
842
843
    // Return result to fe
844
0
    TFinishTaskRequest finish_task_request;
845
0
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
846
0
    finish_task_request.__set_task_type(req.task_type);
847
0
    finish_task_request.__set_signature(req.signature);
848
0
    std::vector<TTabletInfo> finish_tablet_infos;
849
0
    if (!status.ok()) {
850
0
        LOG(WARNING) << "failed to alter inverted index task, signature=" << req.signature
851
0
                     << ", tablet_id=" << alter_inverted_index_rq.tablet_id
852
0
                     << ", job_id=" << alter_inverted_index_rq.job_id << ", error=" << status;
853
0
    } else {
854
0
        LOG(INFO) << "successfully alter inverted index task, signature=" << req.signature
855
0
                  << ", tablet_id=" << alter_inverted_index_rq.tablet_id
856
0
                  << ", job_id=" << alter_inverted_index_rq.job_id;
857
0
        TTabletInfo tablet_info;
858
0
        status = get_tablet_info(engine, alter_inverted_index_rq.tablet_id,
859
0
                                 alter_inverted_index_rq.schema_hash, &tablet_info);
860
0
        if (status.ok()) {
861
0
            finish_tablet_infos.push_back(tablet_info);
862
0
        }
863
0
        finish_task_request.__set_finish_tablet_infos(finish_tablet_infos);
864
0
    }
865
0
    finish_task_request.__set_task_status(status.to_thrift());
866
0
    finish_task(finish_task_request);
867
0
    remove_task_info(req.task_type, req.signature);
868
0
}
869
870
0
void update_tablet_meta_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
871
0
    LOG(INFO) << "get update tablet meta task. signature=" << req.signature;
872
873
0
    Status status;
874
0
    const auto& update_tablet_meta_req = req.update_tablet_meta_info_req;
875
0
    for (const auto& tablet_meta_info : update_tablet_meta_req.tabletMetaInfos) {
876
0
        auto tablet = engine.tablet_manager()->get_tablet(tablet_meta_info.tablet_id);
877
0
        if (tablet == nullptr) {
878
0
            status = Status::NotFound("tablet not found");
879
0
            LOG(WARNING) << "could not find tablet when update tablet meta. tablet_id="
880
0
                         << tablet_meta_info.tablet_id;
881
0
            continue;
882
0
        }
883
0
        bool need_to_save = false;
884
0
        if (tablet_meta_info.__isset.partition_id) {
885
            // for fix partition_id = 0
886
0
            LOG(WARNING) << "change be tablet id: " << tablet->tablet_meta()->tablet_id()
887
0
                         << "partition id from : " << tablet->tablet_meta()->partition_id()
888
0
                         << " to : " << tablet_meta_info.partition_id;
889
0
            auto succ = engine.tablet_manager()->update_tablet_partition_id(
890
0
                    tablet_meta_info.partition_id, tablet->tablet_meta()->tablet_id());
891
0
            if (!succ) {
892
0
                std::string err_msg = fmt::format(
893
0
                        "change be tablet id : {} partition_id : {} failed",
894
0
                        tablet->tablet_meta()->tablet_id(), tablet_meta_info.partition_id);
895
0
                LOG(WARNING) << err_msg;
896
0
                status = Status::InvalidArgument(err_msg);
897
0
                continue;
898
0
            }
899
0
            need_to_save = true;
900
0
        }
901
0
        if (tablet_meta_info.__isset.storage_policy_id) {
902
0
            tablet->tablet_meta()->set_storage_policy_id(tablet_meta_info.storage_policy_id);
903
0
            need_to_save = true;
904
0
        }
905
0
        if (tablet_meta_info.__isset.is_in_memory) {
906
0
            tablet->tablet_meta()->mutable_tablet_schema()->set_is_in_memory(
907
0
                    tablet_meta_info.is_in_memory);
908
0
            std::shared_lock rlock(tablet->get_header_lock());
909
0
            for (auto& [_, rowset_meta] : tablet->tablet_meta()->all_mutable_rs_metas()) {
910
0
                rowset_meta->tablet_schema()->set_is_in_memory(tablet_meta_info.is_in_memory);
911
0
            }
912
0
            tablet->tablet_schema_unlocked()->set_is_in_memory(tablet_meta_info.is_in_memory);
913
0
            need_to_save = true;
914
0
        }
915
0
        if (tablet_meta_info.__isset.compaction_policy) {
916
0
            if (tablet_meta_info.compaction_policy != CUMULATIVE_SIZE_BASED_POLICY &&
917
0
                tablet_meta_info.compaction_policy != CUMULATIVE_TIME_SERIES_POLICY &&
918
0
                tablet_meta_info.compaction_policy != CUMULATIVE_BINLOG_POLICY) {
919
0
                status = Status::InvalidArgument(
920
0
                        "invalid compaction policy, only support for size_based or "
921
0
                        "time_series or binlog");
922
0
                continue;
923
0
            }
924
0
            tablet->tablet_meta()->set_compaction_policy(tablet_meta_info.compaction_policy);
925
0
            need_to_save = true;
926
0
        }
927
0
        if (tablet_meta_info.__isset.time_series_compaction_goal_size_mbytes) {
928
0
            if (tablet->tablet_meta()->compaction_policy() != CUMULATIVE_TIME_SERIES_POLICY) {
929
0
                status = Status::InvalidArgument(
930
0
                        "only time series compaction policy support time series config");
931
0
                continue;
932
0
            }
933
0
            tablet->tablet_meta()->set_time_series_compaction_goal_size_mbytes(
934
0
                    tablet_meta_info.time_series_compaction_goal_size_mbytes);
935
0
            need_to_save = true;
936
0
        }
937
0
        if (tablet_meta_info.__isset.time_series_compaction_file_count_threshold) {
938
0
            if (tablet->tablet_meta()->compaction_policy() != CUMULATIVE_TIME_SERIES_POLICY) {
939
0
                status = Status::InvalidArgument(
940
0
                        "only time series compaction policy support time series config");
941
0
                continue;
942
0
            }
943
0
            tablet->tablet_meta()->set_time_series_compaction_file_count_threshold(
944
0
                    tablet_meta_info.time_series_compaction_file_count_threshold);
945
0
            need_to_save = true;
946
0
        }
947
0
        if (tablet_meta_info.__isset.time_series_compaction_time_threshold_seconds) {
948
0
            if (tablet->tablet_meta()->compaction_policy() != CUMULATIVE_TIME_SERIES_POLICY) {
949
0
                status = Status::InvalidArgument(
950
0
                        "only time series compaction policy support time series config");
951
0
                continue;
952
0
            }
953
0
            tablet->tablet_meta()->set_time_series_compaction_time_threshold_seconds(
954
0
                    tablet_meta_info.time_series_compaction_time_threshold_seconds);
955
0
            need_to_save = true;
956
0
        }
957
0
        if (tablet_meta_info.__isset.time_series_compaction_empty_rowsets_threshold) {
958
0
            if (tablet->tablet_meta()->compaction_policy() != CUMULATIVE_TIME_SERIES_POLICY) {
959
0
                status = Status::InvalidArgument(
960
0
                        "only time series compaction policy support time series config");
961
0
                continue;
962
0
            }
963
0
            tablet->tablet_meta()->set_time_series_compaction_empty_rowsets_threshold(
964
0
                    tablet_meta_info.time_series_compaction_empty_rowsets_threshold);
965
0
            need_to_save = true;
966
0
        }
967
0
        if (tablet_meta_info.__isset.time_series_compaction_level_threshold) {
968
0
            if (tablet->tablet_meta()->compaction_policy() != CUMULATIVE_TIME_SERIES_POLICY) {
969
0
                status = Status::InvalidArgument(
970
0
                        "only time series compaction policy support time series config");
971
0
                continue;
972
0
            }
973
0
            tablet->tablet_meta()->set_time_series_compaction_level_threshold(
974
0
                    tablet_meta_info.time_series_compaction_level_threshold);
975
0
            need_to_save = true;
976
0
        }
977
0
        if (tablet_meta_info.__isset.vertical_compaction_num_columns_per_group) {
978
0
            tablet->tablet_meta()->set_vertical_compaction_num_columns_per_group(
979
0
                    tablet_meta_info.vertical_compaction_num_columns_per_group);
980
0
            need_to_save = true;
981
0
        }
982
0
        if (tablet_meta_info.__isset.replica_id) {
983
0
            tablet->tablet_meta()->set_replica_id(tablet_meta_info.replica_id);
984
0
        }
985
0
        if (tablet_meta_info.__isset.binlog_config) {
986
            // check binlog_config require fields: enable, ttl_seconds, max_bytes, max_history_nums
987
0
            const auto& t_binlog_config = tablet_meta_info.binlog_config;
988
0
            if (!t_binlog_config.__isset.enable || !t_binlog_config.__isset.ttl_seconds ||
989
0
                !t_binlog_config.__isset.max_bytes || !t_binlog_config.__isset.max_history_nums) {
990
0
                status = Status::InvalidArgument("invalid binlog config, some fields not set");
991
0
                LOG(WARNING) << fmt::format(
992
0
                        "invalid binlog config, some fields not set, tablet_id={}, "
993
0
                        "t_binlog_config={}",
994
0
                        tablet_meta_info.tablet_id,
995
0
                        apache::thrift::ThriftDebugString(t_binlog_config));
996
0
                continue;
997
0
            }
998
999
0
            BinlogConfig new_binlog_config;
1000
0
            new_binlog_config = tablet_meta_info.binlog_config;
1001
0
            LOG(INFO) << fmt::format(
1002
0
                    "update tablet meta binlog config. tablet_id={}, old_binlog_config={}, "
1003
0
                    "new_binlog_config={}",
1004
0
                    tablet_meta_info.tablet_id, tablet->tablet_meta()->binlog_config().to_string(),
1005
0
                    new_binlog_config.to_string());
1006
0
            tablet->set_binlog_config(new_binlog_config);
1007
0
            need_to_save = true;
1008
0
        }
1009
0
        if (tablet_meta_info.__isset.disable_auto_compaction) {
1010
0
            std::shared_lock rlock(tablet->get_header_lock());
1011
0
            tablet->tablet_meta()->mutable_tablet_schema()->set_disable_auto_compaction(
1012
0
                    tablet_meta_info.disable_auto_compaction);
1013
0
            for (auto& [_, rowset_meta] : tablet->tablet_meta()->all_mutable_rs_metas()) {
1014
0
                rowset_meta->tablet_schema()->set_disable_auto_compaction(
1015
0
                        tablet_meta_info.disable_auto_compaction);
1016
0
            }
1017
0
            tablet->tablet_schema_unlocked()->set_disable_auto_compaction(
1018
0
                    tablet_meta_info.disable_auto_compaction);
1019
0
            need_to_save = true;
1020
0
        }
1021
1022
0
        if (tablet_meta_info.__isset.skip_write_index_on_load) {
1023
0
            std::shared_lock rlock(tablet->get_header_lock());
1024
0
            tablet->tablet_meta()->mutable_tablet_schema()->set_skip_write_index_on_load(
1025
0
                    tablet_meta_info.skip_write_index_on_load);
1026
0
            for (auto& [_, rowset_meta] : tablet->tablet_meta()->all_mutable_rs_metas()) {
1027
0
                rowset_meta->tablet_schema()->set_skip_write_index_on_load(
1028
0
                        tablet_meta_info.skip_write_index_on_load);
1029
0
            }
1030
0
            tablet->tablet_schema_unlocked()->set_skip_write_index_on_load(
1031
0
                    tablet_meta_info.skip_write_index_on_load);
1032
0
            need_to_save = true;
1033
0
        }
1034
0
        if (need_to_save) {
1035
0
            std::shared_lock rlock(tablet->get_header_lock());
1036
0
            tablet->save_meta();
1037
0
        }
1038
0
    }
1039
1040
0
    LOG(INFO) << "finish update tablet meta task. signature=" << req.signature;
1041
0
    if (req.signature != -1) {
1042
0
        TFinishTaskRequest finish_task_request;
1043
0
        finish_task_request.__set_task_status(status.to_thrift());
1044
0
        finish_task_request.__set_backend(BackendOptions::get_local_backend());
1045
0
        finish_task_request.__set_task_type(req.task_type);
1046
0
        finish_task_request.__set_signature(req.signature);
1047
0
        finish_task(finish_task_request);
1048
0
        remove_task_info(req.task_type, req.signature);
1049
0
    }
1050
0
}
1051
1052
0
void check_consistency_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1053
0
    uint32_t checksum = 0;
1054
0
    const auto& check_consistency_req = req.check_consistency_req;
1055
0
    EngineChecksumTask engine_task(engine, check_consistency_req.tablet_id,
1056
0
                                   check_consistency_req.schema_hash, check_consistency_req.version,
1057
0
                                   &checksum);
1058
0
    SCOPED_ATTACH_TASK(engine_task.mem_tracker());
1059
0
    Status status = engine_task.execute();
1060
0
    if (!status.ok()) {
1061
0
        LOG_WARNING("failed to check consistency")
1062
0
                .tag("signature", req.signature)
1063
0
                .tag("tablet_id", check_consistency_req.tablet_id)
1064
0
                .error(status);
1065
0
    } else {
1066
0
        LOG_INFO("successfully check consistency")
1067
0
                .tag("signature", req.signature)
1068
0
                .tag("tablet_id", check_consistency_req.tablet_id)
1069
0
                .tag("checksum", checksum);
1070
0
    }
1071
1072
0
    TFinishTaskRequest finish_task_request;
1073
0
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1074
0
    finish_task_request.__set_task_type(req.task_type);
1075
0
    finish_task_request.__set_signature(req.signature);
1076
0
    finish_task_request.__set_task_status(status.to_thrift());
1077
0
    finish_task_request.__set_tablet_checksum(static_cast<int64_t>(checksum));
1078
0
    finish_task_request.__set_request_version(check_consistency_req.version);
1079
1080
0
    finish_task(finish_task_request);
1081
0
    remove_task_info(req.task_type, req.signature);
1082
0
}
1083
1084
1.02k
void report_task_callback(const ClusterInfo* cluster_info) {
1085
1.02k
    TReportRequest request;
1086
1.02k
    if (config::report_random_wait) {
1087
1.02k
        random_sleep(5);
1088
1.02k
    }
1089
1.02k
    request.__isset.tasks = true;
1090
1.02k
    {
1091
1.02k
        std::lock_guard lock(s_task_signatures_mtx);
1092
1.02k
        auto& tasks = request.tasks;
1093
6.98k
        for (auto&& [task_type, signatures] : s_task_signatures) {
1094
6.98k
            auto& set = tasks[task_type];
1095
3.15M
            for (auto&& signature : signatures) {
1096
3.15M
                set.insert(signature);
1097
3.15M
            }
1098
6.98k
        }
1099
1.02k
    }
1100
1.02k
    request.__set_backend(BackendOptions::get_local_backend());
1101
1.02k
    request.__set_running_tasks(ExecEnv::GetInstance()->fragment_mgr()->running_query_num());
1102
1.02k
    bool succ = handle_report(request, cluster_info, "task");
1103
1.02k
    report_task_total << 1;
1104
1.02k
    if (!succ) [[unlikely]] {
1105
0
        report_task_failed << 1;
1106
0
    }
1107
1.02k
}
1108
1109
356
void report_disk_callback(StorageEngine& engine, const ClusterInfo* cluster_info) {
1110
356
    TReportRequest request;
1111
356
    request.__set_backend(BackendOptions::get_local_backend());
1112
356
    request.__isset.disks = true;
1113
1114
356
    std::vector<DataDirInfo> data_dir_infos;
1115
356
    static_cast<void>(engine.get_all_data_dir_info(&data_dir_infos, true /* update */));
1116
1117
385
    for (auto& root_path_info : data_dir_infos) {
1118
385
        TDisk disk;
1119
385
        disk.__set_root_path(root_path_info.path);
1120
385
        disk.__set_path_hash(root_path_info.path_hash);
1121
385
        disk.__set_storage_medium(root_path_info.storage_medium);
1122
385
        disk.__set_disk_total_capacity(root_path_info.disk_capacity);
1123
385
        disk.__set_data_used_capacity(root_path_info.local_used_capacity);
1124
385
        disk.__set_remote_used_capacity(root_path_info.remote_used_capacity);
1125
385
        disk.__set_disk_available_capacity(root_path_info.available);
1126
385
        disk.__set_trash_used_capacity(root_path_info.trash_used_capacity);
1127
385
        disk.__set_used(root_path_info.is_used);
1128
385
        request.disks[root_path_info.path] = disk;
1129
385
    }
1130
356
    request.__set_num_cores(CpuInfo::num_cores());
1131
356
    request.__set_pipeline_executor_size(config::pipeline_executor_size > 0
1132
356
                                                 ? config::pipeline_executor_size
1133
356
                                                 : CpuInfo::num_cores());
1134
356
    bool succ = handle_report(request, cluster_info, "disk");
1135
356
    report_disk_total << 1;
1136
356
    if (!succ) [[unlikely]] {
1137
0
        report_disk_failed << 1;
1138
0
    }
1139
356
}
1140
1141
80
void report_disk_callback(CloudStorageEngine& engine, const ClusterInfo* cluster_info) {
1142
    // Random sleep 1~5 seconds before doing report.
1143
    // In order to avoid the problem that the FE receives many report requests at the same time
1144
    // and can not be processed.
1145
80
    if (config::report_random_wait) {
1146
80
        random_sleep(5);
1147
80
    }
1148
80
    (void)engine; // To be used in the future
1149
1150
80
    TReportRequest request;
1151
80
    request.__set_backend(BackendOptions::get_local_backend());
1152
80
    request.__isset.disks = true;
1153
1154
    // TODO(deardeng): report disk info in cloud mode. And make it more clear
1155
    //                 that report CPU by using a separte report procedure
1156
    //                 or abstracting disk report as "host info report"
1157
80
    request.__set_num_cores(CpuInfo::num_cores());
1158
80
    request.__set_pipeline_executor_size(config::pipeline_executor_size > 0
1159
80
                                                 ? config::pipeline_executor_size
1160
80
                                                 : CpuInfo::num_cores());
1161
80
    bool succ = handle_report(request, cluster_info, "disk");
1162
80
    report_disk_total << 1;
1163
80
    report_disk_failed << !succ;
1164
80
}
1165
1166
170
void report_tablet_callback(StorageEngine& engine, const ClusterInfo* cluster_info) {
1167
170
    if (config::report_random_wait) {
1168
170
        random_sleep(5);
1169
170
    }
1170
1171
170
    TReportRequest request;
1172
170
    request.__set_backend(BackendOptions::get_local_backend());
1173
170
    request.__isset.tablets = true;
1174
1175
170
    increase_report_version();
1176
170
    uint64_t report_version;
1177
170
    for (int i = 0; i < 5; i++) {
1178
170
        request.tablets.clear();
1179
170
        report_version = s_report_version;
1180
170
        engine.tablet_manager()->build_all_report_tablets_info(&request.tablets);
1181
170
        if (report_version == s_report_version) {
1182
170
            break;
1183
170
        }
1184
170
    }
1185
1186
170
    if (report_version < s_report_version) {
1187
        // TODO llj This can only reduce the possibility for report error, but can't avoid it.
1188
        // If FE create a tablet in FE meta and send CREATE task to this BE, the tablet may not be included in this
1189
        // report, and the report version has a small probability that it has not been updated in time. When FE
1190
        // receives this report, it is possible to delete the new tablet.
1191
0
        LOG(WARNING) << "report version " << report_version << " change to " << s_report_version;
1192
0
        DorisMetrics::instance()->report_all_tablets_requests_skip->increment(1);
1193
0
        return;
1194
0
    }
1195
1196
170
    std::map<int64_t, int64_t> partitions_version;
1197
170
    engine.tablet_manager()->get_partitions_visible_version(&partitions_version);
1198
170
    request.__set_partitions_version(std::move(partitions_version));
1199
1200
170
    int64_t max_compaction_score =
1201
170
            std::max(DorisMetrics::instance()->tablet_cumulative_max_compaction_score->value(),
1202
170
                     DorisMetrics::instance()->tablet_base_max_compaction_score->value());
1203
170
    request.__set_tablet_max_compaction_score(max_compaction_score);
1204
170
    request.__set_report_version(report_version);
1205
1206
    // report storage policy and resource
1207
170
    auto& storage_policy_list = request.storage_policy;
1208
170
    for (auto [id, version] : get_storage_policy_ids()) {
1209
84
        auto& storage_policy = storage_policy_list.emplace_back();
1210
84
        storage_policy.__set_id(id);
1211
84
        storage_policy.__set_version(version);
1212
84
    }
1213
170
    request.__isset.storage_policy = true;
1214
170
    auto& resource_list = request.resource;
1215
215
    for (auto [id_str, version] : get_storage_resource_ids()) {
1216
215
        auto& resource = resource_list.emplace_back();
1217
215
        int64_t id = -1;
1218
215
        if (auto [_, ec] = std::from_chars(id_str.data(), id_str.data() + id_str.size(), id);
1219
215
            ec != std::errc {}) [[unlikely]] {
1220
0
            LOG(ERROR) << "invalid resource id format: " << id_str;
1221
215
        } else {
1222
215
            resource.__set_id(id);
1223
215
            resource.__set_version(version);
1224
215
        }
1225
215
    }
1226
170
    request.__isset.resource = true;
1227
1228
170
    bool succ = handle_report(request, cluster_info, "tablet");
1229
170
    report_tablet_total << 1;
1230
170
    if (!succ) [[unlikely]] {
1231
0
        report_tablet_failed << 1;
1232
0
    }
1233
170
}
1234
1235
43
void report_tablet_callback(CloudStorageEngine& engine, const ClusterInfo* cluster_info) {
1236
    // Random sleep 1~5 seconds before doing report.
1237
    // In order to avoid the problem that the FE receives many report requests at the same time
1238
    // and can not be processed.
1239
43
    if (config::report_random_wait) {
1240
43
        random_sleep(5);
1241
43
    }
1242
1243
43
    TReportRequest request;
1244
43
    request.__set_backend(BackendOptions::get_local_backend());
1245
43
    request.__isset.tablets = true;
1246
1247
43
    increase_report_version();
1248
43
    uint64_t report_version;
1249
43
    uint64_t total_num_tablets = 0;
1250
55
    for (int i = 0; i < 5; i++) {
1251
53
        request.tablets.clear();
1252
53
        report_version = s_report_version;
1253
53
        engine.tablet_mgr().build_all_report_tablets_info(&request.tablets, &total_num_tablets);
1254
53
        if (report_version == s_report_version) {
1255
41
            break;
1256
41
        }
1257
53
    }
1258
1259
43
    if (report_version < s_report_version) {
1260
2
        LOG(WARNING) << "report version " << report_version << " change to " << s_report_version;
1261
2
        DorisMetrics::instance()->report_all_tablets_requests_skip->increment(1);
1262
2
        return;
1263
2
    }
1264
1265
41
    request.__set_report_version(report_version);
1266
41
    request.__set_num_tablets(total_num_tablets);
1267
1268
41
    bool succ = handle_report(request, cluster_info, "tablet");
1269
41
    report_tablet_total << 1;
1270
41
    if (!succ) [[unlikely]] {
1271
0
        report_tablet_failed << 1;
1272
0
    }
1273
41
}
1274
1275
16
void upload_callback(StorageEngine& engine, ExecEnv* env, const TAgentTaskRequest& req) {
1276
16
    const auto& upload_request = req.upload_req;
1277
1278
16
    LOG(INFO) << "get upload task. signature=" << req.signature
1279
16
              << ", job_id=" << upload_request.job_id;
1280
1281
16
    std::map<int64_t, std::vector<std::string>> tablet_files;
1282
16
    std::unique_ptr<SnapshotLoader> loader = std::make_unique<SnapshotLoader>(
1283
16
            engine, env, upload_request.job_id, req.signature, upload_request.broker_addr,
1284
16
            upload_request.broker_prop);
1285
16
    SCOPED_ATTACH_TASK(loader->resource_ctx());
1286
16
    Status status =
1287
16
            loader->init(upload_request.__isset.storage_backend ? upload_request.storage_backend
1288
16
                                                                : TStorageBackendType::type::BROKER,
1289
16
                         upload_request.__isset.location ? upload_request.location : "");
1290
16
    if (status.ok()) {
1291
16
        status = loader->upload(upload_request.src_dest_map, &tablet_files);
1292
16
    }
1293
1294
16
    if (!status.ok()) {
1295
0
        LOG_WARNING("failed to upload")
1296
0
                .tag("signature", req.signature)
1297
0
                .tag("job_id", upload_request.job_id)
1298
0
                .error(status);
1299
16
    } else {
1300
16
        LOG_INFO("successfully upload")
1301
16
                .tag("signature", req.signature)
1302
16
                .tag("job_id", upload_request.job_id);
1303
16
    }
1304
1305
16
    TFinishTaskRequest finish_task_request;
1306
16
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1307
16
    finish_task_request.__set_task_type(req.task_type);
1308
16
    finish_task_request.__set_signature(req.signature);
1309
16
    finish_task_request.__set_task_status(status.to_thrift());
1310
16
    finish_task_request.__set_tablet_files(tablet_files);
1311
1312
16
    finish_task(finish_task_request);
1313
16
    remove_task_info(req.task_type, req.signature);
1314
16
}
1315
1316
22
void download_callback(StorageEngine& engine, ExecEnv* env, const TAgentTaskRequest& req) {
1317
22
    const auto& download_request = req.download_req;
1318
22
    LOG(INFO) << "get download task. signature=" << req.signature
1319
22
              << ", job_id=" << download_request.job_id
1320
22
              << ", task detail: " << apache::thrift::ThriftDebugString(download_request);
1321
1322
    // TODO: download
1323
22
    std::vector<int64_t> downloaded_tablet_ids;
1324
1325
22
    auto status = Status::OK();
1326
22
    if (download_request.__isset.remote_tablet_snapshots) {
1327
0
        std::unique_ptr<SnapshotLoader> loader = std::make_unique<SnapshotLoader>(
1328
0
                engine, env, download_request.job_id, req.signature);
1329
0
        SCOPED_ATTACH_TASK(loader->resource_ctx());
1330
0
        status = loader->remote_http_download(download_request.remote_tablet_snapshots,
1331
0
                                              &downloaded_tablet_ids);
1332
22
    } else {
1333
22
        std::unique_ptr<SnapshotLoader> loader = std::make_unique<SnapshotLoader>(
1334
22
                engine, env, download_request.job_id, req.signature, download_request.broker_addr,
1335
22
                download_request.broker_prop);
1336
22
        SCOPED_ATTACH_TASK(loader->resource_ctx());
1337
22
        status = loader->init(download_request.__isset.storage_backend
1338
22
                                      ? download_request.storage_backend
1339
22
                                      : TStorageBackendType::type::BROKER,
1340
22
                              download_request.__isset.location ? download_request.location : "");
1341
22
        if (status.ok()) {
1342
22
            status = loader->download(download_request.src_dest_map, &downloaded_tablet_ids);
1343
22
        }
1344
22
    }
1345
1346
22
    if (!status.ok()) {
1347
0
        LOG_WARNING("failed to download")
1348
0
                .tag("signature", req.signature)
1349
0
                .tag("job_id", download_request.job_id)
1350
0
                .error(status);
1351
22
    } else {
1352
22
        LOG_INFO("successfully download")
1353
22
                .tag("signature", req.signature)
1354
22
                .tag("job_id", download_request.job_id);
1355
22
    }
1356
1357
22
    TFinishTaskRequest finish_task_request;
1358
22
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1359
22
    finish_task_request.__set_task_type(req.task_type);
1360
22
    finish_task_request.__set_signature(req.signature);
1361
22
    finish_task_request.__set_task_status(status.to_thrift());
1362
22
    finish_task_request.__set_downloaded_tablet_ids(downloaded_tablet_ids);
1363
1364
22
    finish_task(finish_task_request);
1365
22
    remove_task_info(req.task_type, req.signature);
1366
22
}
1367
1368
0
void download_callback(CloudStorageEngine& engine, ExecEnv* env, const TAgentTaskRequest& req) {
1369
0
    const auto& download_request = req.download_req;
1370
0
    LOG(INFO) << "get download task. signature=" << req.signature
1371
0
              << ", job_id=" << download_request.job_id
1372
0
              << ", task detail: " << apache::thrift::ThriftDebugString(download_request);
1373
1374
0
    std::vector<int64_t> transferred_tablet_ids;
1375
1376
0
    auto status = Status::OK();
1377
0
    if (download_request.__isset.remote_tablet_snapshots) {
1378
0
        status = Status::Error<ErrorCode::NOT_IMPLEMENTED_ERROR>(
1379
0
                "remote tablet snapshot is not supported.");
1380
0
    } else {
1381
0
        std::unique_ptr<CloudSnapshotLoader> loader = std::make_unique<CloudSnapshotLoader>(
1382
0
                engine, env, download_request.job_id, req.signature, download_request.broker_addr,
1383
0
                download_request.broker_prop);
1384
0
        SCOPED_ATTACH_TASK(loader->resource_ctx());
1385
0
        status = loader->init(download_request.__isset.storage_backend
1386
0
                                      ? download_request.storage_backend
1387
0
                                      : TStorageBackendType::type::BROKER,
1388
0
                              download_request.__isset.location ? download_request.location : "",
1389
0
                              download_request.vault_id);
1390
0
        if (status.ok()) {
1391
0
            status = loader->download(download_request.src_dest_map, &transferred_tablet_ids);
1392
0
        }
1393
1394
0
        if (!status.ok()) {
1395
0
            LOG_WARNING("failed to download")
1396
0
                    .tag("signature", req.signature)
1397
0
                    .tag("job_id", download_request.job_id)
1398
0
                    .error(status);
1399
0
        } else {
1400
0
            LOG_INFO("successfully download")
1401
0
                    .tag("signature", req.signature)
1402
0
                    .tag("job_id", download_request.job_id);
1403
0
        }
1404
1405
0
        TFinishTaskRequest finish_task_request;
1406
0
        finish_task_request.__set_backend(BackendOptions::get_local_backend());
1407
0
        finish_task_request.__set_task_type(req.task_type);
1408
0
        finish_task_request.__set_signature(req.signature);
1409
0
        finish_task_request.__set_task_status(status.to_thrift());
1410
0
        finish_task_request.__set_downloaded_tablet_ids(transferred_tablet_ids);
1411
1412
0
        finish_task(finish_task_request);
1413
0
        remove_task_info(req.task_type, req.signature);
1414
0
    }
1415
0
}
1416
1417
320
void make_snapshot_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1418
320
    const auto& snapshot_request = req.snapshot_req;
1419
1420
320
    LOG(INFO) << "get snapshot task. signature=" << req.signature;
1421
1422
320
    std::string snapshot_path;
1423
320
    bool allow_incremental_clone = false; // not used
1424
320
    std::vector<std::string> snapshot_files;
1425
320
    Status status = engine.snapshot_mgr()->make_snapshot(snapshot_request, &snapshot_path,
1426
320
                                                         &allow_incremental_clone);
1427
320
    if (status.ok() && snapshot_request.__isset.list_files) {
1428
        // list and save all snapshot files
1429
        // snapshot_path like: data/snapshot/20180417205230.1.86400
1430
        // we need to add subdir: tablet_id/schema_hash/
1431
320
        std::vector<io::FileInfo> files;
1432
320
        bool exists = true;
1433
320
        io::Path path = fmt::format("{}/{}/{}/", snapshot_path, snapshot_request.tablet_id,
1434
320
                                    snapshot_request.schema_hash);
1435
320
        status = io::global_local_filesystem()->list(path, true, &files, &exists);
1436
320
        if (status.ok()) {
1437
338
            for (auto& file : files) {
1438
338
                snapshot_files.push_back(file.file_name);
1439
338
            }
1440
316
        }
1441
320
    }
1442
320
    if (!status.ok()) {
1443
0
        LOG_WARNING("failed to make snapshot")
1444
0
                .tag("signature", req.signature)
1445
0
                .tag("tablet_id", snapshot_request.tablet_id)
1446
0
                .tag("version", snapshot_request.version)
1447
0
                .error(status);
1448
320
    } else {
1449
320
        LOG_INFO("successfully make snapshot")
1450
320
                .tag("signature", req.signature)
1451
320
                .tag("tablet_id", snapshot_request.tablet_id)
1452
320
                .tag("version", snapshot_request.version)
1453
320
                .tag("snapshot_path", snapshot_path);
1454
320
    }
1455
1456
320
    TFinishTaskRequest finish_task_request;
1457
320
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1458
320
    finish_task_request.__set_task_type(req.task_type);
1459
320
    finish_task_request.__set_signature(req.signature);
1460
320
    finish_task_request.__set_snapshot_path(snapshot_path);
1461
320
    finish_task_request.__set_snapshot_files(snapshot_files);
1462
320
    finish_task_request.__set_task_status(status.to_thrift());
1463
1464
320
    finish_task(finish_task_request);
1465
320
    remove_task_info(req.task_type, req.signature);
1466
320
}
1467
1468
320
void release_snapshot_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1469
320
    const auto& release_snapshot_request = req.release_snapshot_req;
1470
1471
320
    LOG(INFO) << "get release snapshot task. signature=" << req.signature;
1472
1473
320
    const std::string& snapshot_path = release_snapshot_request.snapshot_path;
1474
320
    Status status = engine.snapshot_mgr()->release_snapshot(snapshot_path);
1475
320
    if (!status.ok()) {
1476
0
        LOG_WARNING("failed to release snapshot")
1477
0
                .tag("signature", req.signature)
1478
0
                .tag("snapshot_path", snapshot_path)
1479
0
                .error(status);
1480
320
    } else {
1481
320
        LOG_INFO("successfully release snapshot")
1482
320
                .tag("signature", req.signature)
1483
320
                .tag("snapshot_path", snapshot_path);
1484
320
    }
1485
1486
320
    TFinishTaskRequest finish_task_request;
1487
320
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1488
320
    finish_task_request.__set_task_type(req.task_type);
1489
320
    finish_task_request.__set_signature(req.signature);
1490
320
    finish_task_request.__set_task_status(status.to_thrift());
1491
1492
320
    finish_task(finish_task_request);
1493
320
    remove_task_info(req.task_type, req.signature);
1494
320
}
1495
1496
0
void release_snapshot_callback(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
1497
0
    const auto& release_snapshot_request = req.release_snapshot_req;
1498
1499
0
    LOG(INFO) << "get release snapshot task. signature=" << req.signature;
1500
1501
0
    Status status = engine.cloud_snapshot_mgr().release_snapshot(
1502
0
            release_snapshot_request.tablet_id, release_snapshot_request.is_job_completed);
1503
1504
0
    if (!status.ok()) {
1505
0
        LOG_WARNING("failed to release snapshot")
1506
0
                .tag("signature", req.signature)
1507
0
                .tag("tablet_id", release_snapshot_request.tablet_id)
1508
0
                .tag("is_job_completed", release_snapshot_request.is_job_completed)
1509
0
                .error(status);
1510
0
    } else {
1511
0
        LOG_INFO("successfully release snapshot")
1512
0
                .tag("signature", req.signature)
1513
0
                .tag("tablet_id", release_snapshot_request.tablet_id)
1514
0
                .tag("is_job_completed", release_snapshot_request.is_job_completed);
1515
0
    }
1516
1517
0
    TFinishTaskRequest finish_task_request;
1518
0
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1519
0
    finish_task_request.__set_task_type(req.task_type);
1520
0
    finish_task_request.__set_signature(req.signature);
1521
0
    finish_task_request.__set_task_status(status.to_thrift());
1522
1523
0
    finish_task(finish_task_request);
1524
0
    remove_task_info(req.task_type, req.signature);
1525
0
}
1526
1527
172
void move_dir_callback(StorageEngine& engine, ExecEnv* env, const TAgentTaskRequest& req) {
1528
172
    const auto& move_dir_req = req.move_dir_req;
1529
1530
172
    LOG(INFO) << "get move dir task. signature=" << req.signature
1531
172
              << ", job_id=" << move_dir_req.job_id;
1532
172
    Status status;
1533
172
    auto tablet = engine.tablet_manager()->get_tablet(move_dir_req.tablet_id);
1534
172
    if (tablet == nullptr) {
1535
0
        status = Status::InvalidArgument("Could not find tablet");
1536
172
    } else {
1537
172
        SnapshotLoader loader(engine, env, move_dir_req.job_id, move_dir_req.tablet_id);
1538
172
        SCOPED_ATTACH_TASK(loader.resource_ctx());
1539
172
        status = loader.move(move_dir_req.src, tablet, true);
1540
172
    }
1541
1542
172
    if (!status.ok()) {
1543
0
        LOG_WARNING("failed to move dir")
1544
0
                .tag("signature", req.signature)
1545
0
                .tag("job_id", move_dir_req.job_id)
1546
0
                .tag("tablet_id", move_dir_req.tablet_id)
1547
0
                .tag("src", move_dir_req.src)
1548
0
                .error(status);
1549
172
    } else {
1550
172
        LOG_INFO("successfully move dir")
1551
172
                .tag("signature", req.signature)
1552
172
                .tag("job_id", move_dir_req.job_id)
1553
172
                .tag("tablet_id", move_dir_req.tablet_id)
1554
172
                .tag("src", move_dir_req.src);
1555
172
    }
1556
1557
172
    TFinishTaskRequest finish_task_request;
1558
172
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1559
172
    finish_task_request.__set_task_type(req.task_type);
1560
172
    finish_task_request.__set_signature(req.signature);
1561
172
    finish_task_request.__set_task_status(status.to_thrift());
1562
1563
172
    finish_task(finish_task_request);
1564
172
    remove_task_info(req.task_type, req.signature);
1565
172
}
1566
1567
0
void move_dir_callback(CloudStorageEngine& engine, ExecEnv* env, const TAgentTaskRequest& req) {
1568
0
    const auto& move_dir_req = req.move_dir_req;
1569
1570
0
    LOG(INFO) << "get move dir task. signature=" << req.signature
1571
0
              << ", job_id=" << move_dir_req.job_id;
1572
1573
0
    Status status = engine.cloud_snapshot_mgr().commit_snapshot(move_dir_req.tablet_id);
1574
0
    if (!status.ok()) {
1575
0
        LOG_WARNING("failed to move dir")
1576
0
                .tag("signature", req.signature)
1577
0
                .tag("job_id", move_dir_req.job_id)
1578
0
                .tag("tablet_id", move_dir_req.tablet_id)
1579
0
                .error(status);
1580
0
    } else {
1581
0
        LOG_INFO("successfully move dir")
1582
0
                .tag("signature", req.signature)
1583
0
                .tag("job_id", move_dir_req.job_id)
1584
0
                .tag("tablet_id", move_dir_req.tablet_id);
1585
0
    }
1586
1587
0
    TFinishTaskRequest finish_task_request;
1588
0
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1589
0
    finish_task_request.__set_task_type(req.task_type);
1590
0
    finish_task_request.__set_signature(req.signature);
1591
0
    finish_task_request.__set_task_status(status.to_thrift());
1592
1593
0
    finish_task(finish_task_request);
1594
0
    remove_task_info(req.task_type, req.signature);
1595
0
}
1596
1597
0
void submit_table_compaction_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1598
0
    const auto& compaction_req = req.compaction_req;
1599
1600
0
    LOG(INFO) << "get compaction task. signature=" << req.signature
1601
0
              << ", compaction_type=" << compaction_req.type
1602
0
              << ", tablet_id=" << compaction_req.tablet_id;
1603
1604
0
    CompactionType compaction_type;
1605
0
    if (compaction_req.type == "base") {
1606
0
        compaction_type = CompactionType::BASE_COMPACTION;
1607
0
    } else if (compaction_req.type == "cumulative") {
1608
0
        compaction_type = CompactionType::CUMULATIVE_COMPACTION;
1609
0
    } else if (compaction_req.type == "full") {
1610
0
        compaction_type = CompactionType::FULL_COMPACTION;
1611
0
    } else {
1612
0
        LOG(WARNING) << "unknown compaction type: " << compaction_req.type
1613
0
                     << ", tablet_id=" << compaction_req.tablet_id;
1614
0
        return;
1615
0
    }
1616
1617
0
    auto tablet_ptr = engine.tablet_manager()->get_tablet(compaction_req.tablet_id);
1618
0
    if (tablet_ptr == nullptr) {
1619
0
        LOG(WARNING) << "tablet not found. tablet_id=" << compaction_req.tablet_id;
1620
0
        return;
1621
0
    }
1622
1623
0
    if (compaction_type == CompactionType::FULL_COMPACTION) {
1624
        // Full compaction goes through the dedicated threadpool path (align with
1625
        // compaction_action.cpp _handle_run_compaction). `force=false` keeps the
1626
        // admission under permit limiter, matching the HTTP API default.
1627
0
        tablet_ptr->set_last_full_compaction_schedule_time(UnixMillis());
1628
0
        Status status = engine.submit_compaction_task(tablet_ptr, CompactionType::FULL_COMPACTION,
1629
0
                                                      /*force=*/false, /*eager=*/true,
1630
0
                                                      /*trigger_method=*/1);
1631
0
        if (!status.ok()) {
1632
0
            LOG(WARNING) << "failed to submit full compaction task. tablet_id="
1633
0
                         << tablet_ptr->tablet_id() << ", error=" << status;
1634
0
        }
1635
0
        return;
1636
0
    }
1637
1638
    // base / cumulative
1639
0
    auto* data_dir = tablet_ptr->data_dir();
1640
0
    if (!tablet_ptr->can_do_compaction(data_dir->path_hash(), compaction_type)) {
1641
0
        LOG(WARNING) << "could not do compaction. tablet_id=" << tablet_ptr->tablet_id()
1642
0
                     << ", compaction_type=" << compaction_type;
1643
0
        return;
1644
0
    }
1645
1646
0
    Status status = engine.submit_compaction_task(tablet_ptr, compaction_type, false);
1647
0
    if (!status.ok()) {
1648
0
        LOG(WARNING) << "failed to submit table compaction task. error=" << status;
1649
0
    }
1650
0
}
1651
1652
void cloud_submit_table_compaction_callback(CloudStorageEngine& engine,
1653
3
                                            const TAgentTaskRequest& req) {
1654
3
    const auto& compaction_req = req.compaction_req;
1655
1656
3
    LOG(INFO) << "get cloud compaction task. signature=" << req.signature
1657
3
              << ", compaction_type=" << compaction_req.type
1658
3
              << ", tablet_id=" << compaction_req.tablet_id;
1659
1660
3
    CompactionType compaction_type;
1661
3
    if (compaction_req.type == "base") {
1662
1
        compaction_type = CompactionType::BASE_COMPACTION;
1663
2
    } else if (compaction_req.type == "cumulative") {
1664
1
        compaction_type = CompactionType::CUMULATIVE_COMPACTION;
1665
1
    } else if (compaction_req.type == "full") {
1666
1
        compaction_type = CompactionType::FULL_COMPACTION;
1667
1
    } else {
1668
0
        LOG(WARNING) << "unknown cloud compaction type: " << compaction_req.type
1669
0
                     << ", tablet_id=" << compaction_req.tablet_id;
1670
0
        return;
1671
0
    }
1672
1673
    // Mirror cloud_compaction_action::_handle_run_compaction: base/cumu needs the
1674
    // delete bitmap synced eagerly, full does not (FullCompaction re-syncs itself).
1675
3
    bool sync_delete_bitmap = compaction_type != CompactionType::FULL_COMPACTION;
1676
3
    auto tablet_res = engine.tablet_mgr().get_tablet(compaction_req.tablet_id,
1677
3
                                                     /*warmup_data=*/false, sync_delete_bitmap);
1678
3
    if (!tablet_res.has_value()) {
1679
0
        LOG(WARNING) << "failed to get cloud tablet. tablet_id=" << compaction_req.tablet_id
1680
0
                     << ", error=" << tablet_res.error();
1681
0
        return;
1682
0
    }
1683
3
    CloudTabletSPtr tablet = std::move(tablet_res).value();
1684
3
    if (tablet == nullptr) {
1685
0
        LOG(WARNING) << "cloud tablet not found. tablet_id=" << compaction_req.tablet_id;
1686
0
        return;
1687
0
    }
1688
1689
3
    switch (compaction_type) {
1690
1
    case CompactionType::BASE_COMPACTION:
1691
1
        tablet->set_last_base_compaction_schedule_time(UnixMillis());
1692
1
        break;
1693
1
    case CompactionType::CUMULATIVE_COMPACTION:
1694
1
        tablet->set_last_cumu_compaction_schedule_time(UnixMillis());
1695
1
        break;
1696
1
    case CompactionType::FULL_COMPACTION:
1697
1
        tablet->set_last_full_compaction_schedule_time(UnixMillis());
1698
1
        break;
1699
0
    default:
1700
0
        break;
1701
3
    }
1702
1703
3
    Status status = engine.submit_compaction_task(tablet, compaction_type,
1704
3
                                                  /*trigger_method=*/1);
1705
3
    if (!status.ok()) {
1706
1
        LOG(WARNING) << "failed to submit cloud compaction task. tablet_id=" << tablet->tablet_id()
1707
1
                     << ", type=" << compaction_req.type << ", error=" << status;
1708
1
    }
1709
3
}
1710
1711
namespace {
1712
1713
33
void update_s3_resource(const TStorageResource& param, io::RemoteFileSystemSPtr existed_fs) {
1714
33
    Status st;
1715
33
    io::RemoteFileSystemSPtr fs;
1716
1717
33
    if (!existed_fs) {
1718
        // No such FS instance on BE
1719
33
        auto res = io::S3FileSystem::create(S3Conf::get_s3_conf(param.s3_storage_param),
1720
33
                                            std::to_string(param.id));
1721
33
        if (!res.has_value()) {
1722
9
            st = std::move(res).error();
1723
24
        } else {
1724
24
            fs = std::move(res).value();
1725
24
        }
1726
33
    } else {
1727
0
        DCHECK_EQ(existed_fs->type(), io::FileSystemType::S3) << param.id << ' ' << param.name;
1728
0
        auto client = static_cast<io::S3FileSystem*>(existed_fs.get())->client_holder();
1729
0
        auto new_s3_conf = S3Conf::get_s3_conf(param.s3_storage_param);
1730
0
        S3ClientConf conf = std::move(new_s3_conf.client_conf);
1731
0
        st = client->reset(conf);
1732
0
        fs = std::move(existed_fs);
1733
0
    }
1734
1735
33
    if (!st.ok()) {
1736
9
        LOG(WARNING) << "update s3 resource failed: " << st;
1737
24
    } else {
1738
24
        LOG_INFO("successfully update s3 resource")
1739
24
                .tag("resource_id", param.id)
1740
24
                .tag("resource_name", param.name);
1741
24
        put_storage_resource(param.id, {std::move(fs)}, param.version);
1742
24
    }
1743
33
}
1744
1745
38
void update_hdfs_resource(const TStorageResource& param, io::RemoteFileSystemSPtr existed_fs) {
1746
38
    Status st;
1747
38
    io::RemoteFileSystemSPtr fs;
1748
38
    std::string root_path =
1749
38
            param.hdfs_storage_param.__isset.root_path ? param.hdfs_storage_param.root_path : "";
1750
1751
38
    if (!existed_fs) {
1752
        // No such FS instance on BE
1753
38
        auto res = io::HdfsFileSystem::create(
1754
38
                param.hdfs_storage_param, param.hdfs_storage_param.fs_name,
1755
38
                std::to_string(param.id), nullptr, std::move(root_path));
1756
38
        if (!res.has_value()) {
1757
18
            st = std::move(res).error();
1758
20
        } else {
1759
20
            fs = std::move(res).value();
1760
20
        }
1761
1762
38
    } else {
1763
0
        DCHECK_EQ(existed_fs->type(), io::FileSystemType::HDFS) << param.id << ' ' << param.name;
1764
        // TODO(plat1ko): update hdfs conf
1765
0
        fs = std::move(existed_fs);
1766
0
    }
1767
1768
38
    if (!st.ok()) {
1769
18
        LOG(WARNING) << "update hdfs resource failed: " << st;
1770
20
    } else {
1771
20
        LOG_INFO("successfully update hdfs resource")
1772
20
                .tag("resource_id", param.id)
1773
20
                .tag("resource_name", param.name)
1774
20
                .tag("root_path", fs->root_path().string());
1775
20
        put_storage_resource(param.id, {std::move(fs)}, param.version);
1776
20
    }
1777
38
}
1778
1779
} // namespace
1780
1781
11
void push_storage_policy_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1782
11
    const auto& push_storage_policy_req = req.push_storage_policy_req;
1783
    // refresh resource
1784
71
    for (auto&& param : push_storage_policy_req.resource) {
1785
71
        io::RemoteFileSystemSPtr fs;
1786
71
        if (auto existed_resource = get_storage_resource(param.id); existed_resource) {
1787
0
            if (existed_resource->second >= param.version) {
1788
                // Stale request, ignore
1789
0
                continue;
1790
0
            }
1791
1792
0
            fs = std::move(existed_resource->first.fs);
1793
0
        }
1794
1795
71
        if (param.__isset.s3_storage_param) {
1796
33
            update_s3_resource(param, std::move(fs));
1797
38
        } else if (param.__isset.hdfs_storage_param) {
1798
38
            update_hdfs_resource(param, std::move(fs));
1799
38
        } else {
1800
0
            LOG(WARNING) << "unknown resource=" << param;
1801
0
        }
1802
71
    }
1803
    // drop storage policy
1804
11
    for (auto policy_id : push_storage_policy_req.dropped_storage_policy) {
1805
0
        delete_storage_policy(policy_id);
1806
0
    }
1807
    // refresh storage policy
1808
24
    for (auto&& storage_policy : push_storage_policy_req.storage_policy) {
1809
24
        auto existed_storage_policy = get_storage_policy(storage_policy.id);
1810
24
        if (existed_storage_policy == nullptr ||
1811
24
            existed_storage_policy->version < storage_policy.version) {
1812
24
            auto storage_policy1 = std::make_shared<StoragePolicy>();
1813
24
            storage_policy1->name = storage_policy.name;
1814
24
            storage_policy1->version = storage_policy.version;
1815
24
            storage_policy1->cooldown_datetime = storage_policy.cooldown_datetime;
1816
24
            storage_policy1->cooldown_ttl = storage_policy.cooldown_ttl;
1817
24
            storage_policy1->resource_id = storage_policy.resource_id;
1818
24
            LOG_INFO("successfully update storage policy")
1819
24
                    .tag("storage_policy_id", storage_policy.id)
1820
24
                    .tag("storage_policy", storage_policy1->to_string());
1821
24
            put_storage_policy(storage_policy.id, std::move(storage_policy1));
1822
24
        }
1823
24
    }
1824
11
}
1825
1826
16
void push_index_policy_callback(const TAgentTaskRequest& req) {
1827
16
    const auto& request = req.push_index_policy_req;
1828
16
    doris::ExecEnv::GetInstance()->index_policy_mgr()->apply_policy_changes(
1829
16
            request.index_policys, request.dropped_index_policys);
1830
16
}
1831
1832
2
void push_cooldown_conf_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1833
2
    const auto& push_cooldown_conf_req = req.push_cooldown_conf;
1834
326
    for (const auto& cooldown_conf : push_cooldown_conf_req.cooldown_confs) {
1835
326
        int64_t tablet_id = cooldown_conf.tablet_id;
1836
326
        TabletSharedPtr tablet = engine.tablet_manager()->get_tablet(tablet_id);
1837
326
        if (tablet == nullptr) {
1838
0
            LOG(WARNING) << "failed to get tablet. tablet_id=" << tablet_id;
1839
0
            continue;
1840
0
        }
1841
326
        if (tablet->update_cooldown_conf(cooldown_conf.cooldown_term,
1842
326
                                         cooldown_conf.cooldown_replica_id) &&
1843
326
            cooldown_conf.cooldown_replica_id == tablet->replica_id() &&
1844
326
            tablet->tablet_meta()->cooldown_meta_id().initialized()) {
1845
2
            Tablet::async_write_cooldown_meta(tablet);
1846
2
        }
1847
326
    }
1848
2
}
1849
1850
8.12k
void create_tablet_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1851
8.12k
    const auto& create_tablet_req = req.create_tablet_req;
1852
8.12k
    RuntimeProfile runtime_profile("CreateTablet");
1853
8.12k
    RuntimeProfile* profile = &runtime_profile;
1854
8.12k
    MonotonicStopWatch watch;
1855
8.12k
    watch.start();
1856
8.12k
    Defer defer = [&] {
1857
8.12k
        auto elapsed_time = static_cast<double>(watch.elapsed_time());
1858
8.12k
        if (elapsed_time / 1e9 > config::agent_task_trace_threshold_sec) {
1859
0
#include "common/compile_check_avoid_begin.h"
1860
0
            COUNTER_UPDATE(profile->total_time_counter(), elapsed_time);
1861
0
#include "common/compile_check_avoid_end.h"
1862
0
            std::stringstream ss;
1863
0
            profile->pretty_print(&ss);
1864
0
            LOG(WARNING) << "create tablet cost(s) " << elapsed_time / 1e9 << std::endl << ss.str();
1865
0
        }
1866
8.12k
    };
1867
8.12k
    DorisMetrics::instance()->create_tablet_requests_total->increment(1);
1868
8.12k
    VLOG_NOTICE << "start to create tablet " << create_tablet_req.tablet_id;
1869
1870
8.12k
    std::vector<TTabletInfo> finish_tablet_infos;
1871
8.12k
    VLOG_NOTICE << "create tablet: " << create_tablet_req;
1872
8.12k
    Status status = engine.create_tablet(create_tablet_req, profile);
1873
8.12k
    if (!status.ok()) {
1874
0
        DorisMetrics::instance()->create_tablet_requests_failed->increment(1);
1875
0
        LOG_WARNING("failed to create tablet, reason={}", status.to_string())
1876
0
                .tag("signature", req.signature)
1877
0
                .tag("tablet_id", create_tablet_req.tablet_id)
1878
0
                .error(status);
1879
8.12k
    } else {
1880
8.12k
        increase_report_version();
1881
        // get path hash of the created tablet
1882
8.12k
        TabletSharedPtr tablet;
1883
8.12k
        {
1884
8.12k
            SCOPED_TIMER(ADD_TIMER(profile, "GetTablet"));
1885
8.12k
            tablet = engine.tablet_manager()->get_tablet(create_tablet_req.tablet_id);
1886
8.12k
        }
1887
8.12k
        DCHECK(tablet != nullptr);
1888
8.12k
        TTabletInfo tablet_info;
1889
8.12k
        tablet_info.tablet_id = tablet->tablet_id();
1890
8.12k
        tablet_info.schema_hash = tablet->schema_hash();
1891
8.12k
        tablet_info.version = create_tablet_req.version;
1892
        // Useless but it is a required field in TTabletInfo
1893
8.12k
        tablet_info.version_hash = 0;
1894
8.12k
        tablet_info.row_count = 0;
1895
8.12k
        tablet_info.data_size = 0;
1896
8.12k
        tablet_info.__set_path_hash(tablet->data_dir()->path_hash());
1897
8.12k
        tablet_info.__set_replica_id(tablet->replica_id());
1898
8.12k
        finish_tablet_infos.push_back(tablet_info);
1899
8.12k
        LOG_INFO("successfully create tablet")
1900
8.12k
                .tag("signature", req.signature)
1901
8.12k
                .tag("tablet_id", create_tablet_req.tablet_id);
1902
8.12k
    }
1903
8.12k
    TFinishTaskRequest finish_task_request;
1904
8.12k
    finish_task_request.__set_finish_tablet_infos(finish_tablet_infos);
1905
8.12k
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1906
8.12k
    finish_task_request.__set_report_version(s_report_version);
1907
8.12k
    finish_task_request.__set_task_type(req.task_type);
1908
8.12k
    finish_task_request.__set_signature(req.signature);
1909
8.12k
    finish_task_request.__set_task_status(status.to_thrift());
1910
8.12k
    finish_task(finish_task_request);
1911
8.12k
    remove_task_info(req.task_type, req.signature);
1912
8.12k
}
1913
1914
5.97k
void drop_tablet_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
1915
5.97k
    const auto& drop_tablet_req = req.drop_tablet_req;
1916
5.97k
    Status status;
1917
5.97k
    auto dropped_tablet = engine.tablet_manager()->get_tablet(drop_tablet_req.tablet_id, false);
1918
5.97k
    if (dropped_tablet != nullptr) {
1919
5.97k
        status = engine.tablet_manager()->drop_tablet(drop_tablet_req.tablet_id,
1920
5.97k
                                                      drop_tablet_req.replica_id,
1921
5.97k
                                                      drop_tablet_req.is_drop_table_or_partition);
1922
5.97k
    } else {
1923
0
        status = Status::NotFound("could not find tablet {}", drop_tablet_req.tablet_id);
1924
0
    }
1925
5.97k
    if (status.ok()) {
1926
        // if tablet is dropped by fe, then the related txn should also be removed
1927
5.97k
        engine.txn_manager()->force_rollback_tablet_related_txns(
1928
5.97k
                dropped_tablet->data_dir()->get_meta(), drop_tablet_req.tablet_id,
1929
5.97k
                dropped_tablet->tablet_uid());
1930
5.97k
        LOG_INFO("successfully drop tablet")
1931
5.97k
                .tag("signature", req.signature)
1932
5.97k
                .tag("tablet_id", drop_tablet_req.tablet_id)
1933
5.97k
                .tag("replica_id", drop_tablet_req.replica_id);
1934
5.97k
    } else {
1935
0
        LOG_WARNING("failed to drop tablet")
1936
0
                .tag("signature", req.signature)
1937
0
                .tag("tablet_id", drop_tablet_req.tablet_id)
1938
0
                .tag("replica_id", drop_tablet_req.replica_id)
1939
0
                .error(status);
1940
0
    }
1941
1942
5.97k
    TFinishTaskRequest finish_task_request;
1943
5.97k
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
1944
5.97k
    finish_task_request.__set_task_type(req.task_type);
1945
5.97k
    finish_task_request.__set_signature(req.signature);
1946
5.97k
    finish_task_request.__set_task_status(status.to_thrift());
1947
1948
5.97k
    TTabletInfo tablet_info;
1949
5.97k
    tablet_info.tablet_id = drop_tablet_req.tablet_id;
1950
5.97k
    tablet_info.schema_hash = drop_tablet_req.schema_hash;
1951
5.97k
    tablet_info.version = 0;
1952
    // Useless but it is a required field in TTabletInfo
1953
5.97k
    tablet_info.version_hash = 0;
1954
5.97k
    tablet_info.row_count = 0;
1955
5.97k
    tablet_info.data_size = 0;
1956
1957
5.97k
    finish_task_request.__set_finish_tablet_infos({tablet_info});
1958
5.97k
    LOG_INFO("successfully drop tablet")
1959
5.97k
            .tag("signature", req.signature)
1960
5.97k
            .tag("tablet_id", drop_tablet_req.tablet_id);
1961
1962
5.97k
    finish_task(finish_task_request);
1963
5.97k
    remove_task_info(req.task_type, req.signature);
1964
5.97k
}
1965
1966
0
void drop_tablet_callback(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
1967
0
    const auto& drop_tablet_req = req.drop_tablet_req;
1968
    // here drop_tablet_req.tablet_id is the signature of the task, see DropReplicaTask in fe
1969
0
    Defer defer = [&] { remove_task_info(req.task_type, req.signature); };
1970
0
    DBUG_EXECUTE_IF("WorkPoolCloudDropTablet.drop_tablet_callback.failed", {
1971
0
        LOG_WARNING("WorkPoolCloudDropTablet.drop_tablet_callback.failed")
1972
0
                .tag("tablet_id", drop_tablet_req.tablet_id);
1973
0
        return;
1974
0
    });
1975
0
    MonotonicStopWatch watch;
1976
0
    watch.start();
1977
0
    auto weak_tablets = engine.tablet_mgr().get_weak_tablets();
1978
0
    std::ostringstream rowset_ids_stream;
1979
0
    bool found = false;
1980
0
    for (auto& weak_tablet : weak_tablets) {
1981
0
        auto tablet = weak_tablet.lock();
1982
0
        if (tablet == nullptr) {
1983
0
            continue;
1984
0
        }
1985
0
        if (tablet->tablet_id() != drop_tablet_req.tablet_id) {
1986
0
            continue;
1987
0
        }
1988
0
        found = true;
1989
0
        auto clean_rowsets = tablet->get_snapshot_rowset(true);
1990
        // Get first 10 rowset IDs as comma-separated string, just for log
1991
0
        int count = 0;
1992
0
        for (const auto& rowset : clean_rowsets) {
1993
0
            if (count >= 10) break;
1994
0
            if (count > 0) {
1995
0
                rowset_ids_stream << ",";
1996
0
            }
1997
0
            rowset_ids_stream << rowset->rowset_id().to_string();
1998
0
            count++;
1999
0
        }
2000
2001
0
        CloudTablet::recycle_cached_data(clean_rowsets);
2002
0
        break;
2003
0
    }
2004
2005
0
    if (!found) {
2006
0
        LOG(WARNING) << "tablet not found when dropping tablet_id=" << drop_tablet_req.tablet_id
2007
0
                     << ", cost " << static_cast<double>(watch.elapsed_time()) / 1e9 << "(s)";
2008
0
        return;
2009
0
    }
2010
2011
0
    engine.tablet_mgr().erase_tablet(drop_tablet_req.tablet_id);
2012
0
    LOG(INFO) << "drop cloud tablet_id=" << drop_tablet_req.tablet_id
2013
0
              << " and clean file cache first 10 rowsets {" << rowset_ids_stream.str() << "}, cost "
2014
0
              << static_cast<double>(watch.elapsed_time()) / 1e9 << "(s)";
2015
0
}
2016
2017
22
void push_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2018
22
    const auto& push_req = req.push_req;
2019
2020
22
    LOG(INFO) << "get push task. signature=" << req.signature
2021
22
              << " push_type=" << push_req.push_type;
2022
22
    std::vector<TTabletInfo> tablet_infos;
2023
2024
    // exist a path task_worker_pool <- agent_server <- backend_service <- BackendService
2025
    // use the arg BackendService_submit_tasks_args.tasks is not const
2026
    // and push_req will be modify, so modify is ok
2027
22
    EngineBatchLoadTask engine_task(engine, const_cast<TPushReq&>(push_req), &tablet_infos);
2028
22
    SCOPED_ATTACH_TASK(engine_task.mem_tracker());
2029
22
    auto status = engine_task.execute();
2030
2031
    // Return result to fe
2032
22
    TFinishTaskRequest finish_task_request;
2033
22
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2034
22
    finish_task_request.__set_task_type(req.task_type);
2035
22
    finish_task_request.__set_signature(req.signature);
2036
22
    if (push_req.push_type == TPushType::DELETE) {
2037
22
        finish_task_request.__set_request_version(push_req.version);
2038
22
    }
2039
2040
22
    if (status.ok()) {
2041
22
        LOG_INFO("successfully execute push task")
2042
22
                .tag("signature", req.signature)
2043
22
                .tag("tablet_id", push_req.tablet_id)
2044
22
                .tag("push_type", push_req.push_type);
2045
22
        increase_report_version();
2046
22
        finish_task_request.__set_finish_tablet_infos(tablet_infos);
2047
22
    } else {
2048
0
        LOG_WARNING("failed to execute push task")
2049
0
                .tag("signature", req.signature)
2050
0
                .tag("tablet_id", push_req.tablet_id)
2051
0
                .tag("push_type", push_req.push_type)
2052
0
                .error(status);
2053
0
    }
2054
22
    finish_task_request.__set_task_status(status.to_thrift());
2055
22
    finish_task_request.__set_report_version(s_report_version);
2056
2057
22
    finish_task(finish_task_request);
2058
22
    remove_task_info(req.task_type, req.signature);
2059
22
}
2060
2061
3.18k
void cloud_push_callback(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
2062
3.18k
    const auto& push_req = req.push_req;
2063
2064
3.18k
    LOG(INFO) << "get push task. signature=" << req.signature
2065
3.18k
              << " push_type=" << push_req.push_type;
2066
2067
    // Return result to fe
2068
3.18k
    TFinishTaskRequest finish_task_request;
2069
3.18k
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2070
3.18k
    finish_task_request.__set_task_type(req.task_type);
2071
3.18k
    finish_task_request.__set_signature(req.signature);
2072
2073
    // Only support DELETE in cloud mode now
2074
3.18k
    if (push_req.push_type != TPushType::DELETE) {
2075
0
        finish_task_request.__set_task_status(
2076
0
                Status::NotSupported("push_type {} not is supported",
2077
0
                                     std::to_string(push_req.push_type))
2078
0
                        .to_thrift());
2079
0
        return;
2080
0
    }
2081
2082
3.18k
    finish_task_request.__set_request_version(push_req.version);
2083
2084
3.18k
    DorisMetrics::instance()->delete_requests_total->increment(1);
2085
3.18k
    auto st = CloudDeleteTask::execute(engine, req.push_req);
2086
3.18k
    if (st.ok()) {
2087
3.17k
        LOG_INFO("successfully execute push task")
2088
3.17k
                .tag("signature", req.signature)
2089
3.17k
                .tag("tablet_id", push_req.tablet_id)
2090
3.17k
                .tag("push_type", push_req.push_type);
2091
3.17k
        increase_report_version();
2092
3.17k
        auto& tablet_info = finish_task_request.finish_tablet_infos.emplace_back();
2093
        // Just need tablet_id
2094
3.17k
        tablet_info.tablet_id = push_req.tablet_id;
2095
3.17k
        finish_task_request.__isset.finish_tablet_infos = true;
2096
3.17k
    } else {
2097
18
        DorisMetrics::instance()->delete_requests_failed->increment(1);
2098
18
        LOG_WARNING("failed to execute push task")
2099
18
                .tag("signature", req.signature)
2100
18
                .tag("tablet_id", push_req.tablet_id)
2101
18
                .tag("push_type", push_req.push_type)
2102
18
                .error(st);
2103
18
    }
2104
2105
3.18k
    finish_task_request.__set_task_status(st.to_thrift());
2106
3.18k
    finish_task_request.__set_report_version(s_report_version);
2107
2108
3.18k
    finish_task(finish_task_request);
2109
3.18k
    remove_task_info(req.task_type, req.signature);
2110
3.18k
}
2111
2112
PublishVersionWorkerPool::PublishVersionWorkerPool(StorageEngine& engine)
2113
5
        : TaskWorkerPool("PUBLISH_VERSION", config::publish_version_worker_count,
2114
6.12k
                         [this](const TAgentTaskRequest& task) { publish_version_callback(task); }),
2115
5
          _engine(engine) {}
2116
2117
PublishVersionWorkerPool::~PublishVersionWorkerPool() = default;
2118
2119
6.13k
void PublishVersionWorkerPool::publish_version_callback(const TAgentTaskRequest& req) {
2120
6.13k
    const auto& publish_version_req = req.publish_version_req;
2121
6.13k
    DorisMetrics::instance()->publish_task_request_total->increment(1);
2122
6.13k
    VLOG_NOTICE << "get publish version task. signature=" << req.signature;
2123
2124
6.13k
    std::set<TTabletId> error_tablet_ids;
2125
6.13k
    std::map<TTabletId, TVersion> succ_tablets;
2126
    // partition_id, tablet_id, publish_version, commit_tso
2127
6.13k
    std::vector<DiscontinuousVersionTablet> discontinuous_version_tablets;
2128
6.13k
    std::map<TTableId, std::map<TTabletId, int64_t>> table_id_to_tablet_id_to_num_delta_rows;
2129
6.13k
    uint32_t retry_time = 0;
2130
6.13k
    Status status;
2131
6.13k
    constexpr uint32_t PUBLISH_VERSION_MAX_RETRY = 3;
2132
6.13k
    while (retry_time < PUBLISH_VERSION_MAX_RETRY) {
2133
6.13k
        succ_tablets.clear();
2134
6.13k
        error_tablet_ids.clear();
2135
6.13k
        table_id_to_tablet_id_to_num_delta_rows.clear();
2136
6.13k
        EnginePublishVersionTask engine_task(_engine, publish_version_req, &error_tablet_ids,
2137
6.13k
                                             &succ_tablets, &discontinuous_version_tablets,
2138
6.13k
                                             &table_id_to_tablet_id_to_num_delta_rows);
2139
6.13k
        SCOPED_ATTACH_TASK(engine_task.mem_tracker());
2140
6.13k
        status = engine_task.execute();
2141
6.13k
        if (status.ok()) {
2142
6.12k
            break;
2143
6.12k
        }
2144
2145
12
        if (status.is<PUBLISH_VERSION_NOT_CONTINUOUS>()) {
2146
            // there are too many missing versions, it has been be added to async
2147
            // publish task, so no need to retry here.
2148
12
            if (discontinuous_version_tablets.empty()) {
2149
0
                break;
2150
0
            }
2151
12
            LOG_EVERY_SECOND(INFO) << "wait for previous publish version task to be done, "
2152
6
                                   << "transaction_id: " << publish_version_req.transaction_id;
2153
2154
12
            int64_t time_elapsed = time(nullptr) - req.recv_time;
2155
12
            if (time_elapsed > config::publish_version_task_timeout_s) {
2156
0
                LOG(INFO) << "task elapsed " << time_elapsed
2157
0
                          << " seconds since it is inserted to queue, it is timeout";
2158
0
                break;
2159
0
            }
2160
2161
            // Version not continuous, put to queue and wait pre version publish task execute
2162
12
            PUBLISH_VERSION_count << 1;
2163
12
            auto st = _thread_pool->submit_func([this, req] {
2164
12
                this->publish_version_callback(req);
2165
12
                PUBLISH_VERSION_count << -1;
2166
12
            });
2167
12
            if (!st.ok()) [[unlikely]] {
2168
0
                PUBLISH_VERSION_count << -1;
2169
0
                status = std::move(st);
2170
12
            } else {
2171
12
                return;
2172
12
            }
2173
12
        }
2174
2175
0
        LOG_WARNING("failed to publish version")
2176
0
                .tag("transaction_id", publish_version_req.transaction_id)
2177
0
                .tag("error_tablets_num", error_tablet_ids.size())
2178
0
                .tag("retry_time", retry_time)
2179
0
                .error(status);
2180
0
        ++retry_time;
2181
0
    }
2182
2183
6.12k
    for (auto& item : discontinuous_version_tablets) {
2184
0
        _engine.add_async_publish_task(item.partition_id, item.tablet_id, item.publish_version,
2185
0
                                       publish_version_req.transaction_id, false, item.commit_tso);
2186
0
    }
2187
6.12k
    TFinishTaskRequest finish_task_request;
2188
6.12k
    if (!status.ok()) [[unlikely]] {
2189
0
        DorisMetrics::instance()->publish_task_failed_total->increment(1);
2190
        // if publish failed, return failed, FE will ignore this error and
2191
        // check error tablet ids and FE will also republish this task
2192
0
        LOG_WARNING("failed to publish version")
2193
0
                .tag("signature", req.signature)
2194
0
                .tag("transaction_id", publish_version_req.transaction_id)
2195
0
                .tag("error_tablets_num", error_tablet_ids.size())
2196
0
                .error(status);
2197
6.12k
    } else {
2198
6.12k
        if (!config::disable_auto_compaction &&
2199
6.12k
            (!config::enable_compaction_pause_on_high_memory ||
2200
6.12k
             !GlobalMemoryArbitrator::is_exceed_soft_mem_limit(GB_EXCHANGE_BYTE))) {
2201
47.1k
            for (auto [tablet_id, _] : succ_tablets) {
2202
47.1k
                TabletSharedPtr tablet = _engine.tablet_manager()->get_tablet(tablet_id);
2203
47.1k
                if (tablet != nullptr) {
2204
47.1k
                    if (!tablet->tablet_meta()->tablet_schema()->disable_auto_compaction()) {
2205
47.1k
                        tablet->published_count.fetch_add(1);
2206
47.1k
                        int64_t published_count = tablet->published_count.load();
2207
47.1k
                        int32_t max_version_config = tablet->max_version_config();
2208
47.1k
                        if (tablet->exceed_version_limit(
2209
47.1k
                                    max_version_config *
2210
47.1k
                                    config::load_trigger_compaction_version_percent / 100) &&
2211
47.1k
                            published_count % 20 == 0) {
2212
0
                            auto st = _engine.submit_compaction_task(
2213
0
                                    tablet, CompactionType::CUMULATIVE_COMPACTION, true, false);
2214
0
                            if (!st.ok()) [[unlikely]] {
2215
0
                                LOG(WARNING) << "trigger compaction failed, tablet_id=" << tablet_id
2216
0
                                             << ", published=" << published_count << " : " << st;
2217
0
                            } else {
2218
0
                                LOG(INFO) << "trigger compaction succ, tablet_id:" << tablet_id
2219
0
                                          << ", published:" << published_count;
2220
0
                            }
2221
0
                        }
2222
47.1k
                    }
2223
47.1k
                } else {
2224
0
                    LOG(WARNING) << "trigger compaction failed, tablet_id:" << tablet_id;
2225
0
                }
2226
47.1k
            }
2227
6.12k
        }
2228
6.12k
        int64_t cost_second = time(nullptr) - req.recv_time;
2229
6.12k
        g_publish_version_latency << cost_second;
2230
6.12k
        LOG_INFO("successfully publish version")
2231
6.12k
                .tag("signature", req.signature)
2232
6.12k
                .tag("transaction_id", publish_version_req.transaction_id)
2233
6.12k
                .tag("tablets_num", succ_tablets.size())
2234
6.12k
                .tag("cost(s)", cost_second);
2235
6.12k
    }
2236
2237
6.12k
    status.to_thrift(&finish_task_request.task_status);
2238
6.12k
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2239
6.12k
    finish_task_request.__set_task_type(req.task_type);
2240
6.12k
    finish_task_request.__set_signature(req.signature);
2241
6.12k
    finish_task_request.__set_report_version(s_report_version);
2242
6.12k
    finish_task_request.__set_succ_tablets(succ_tablets);
2243
6.12k
    finish_task_request.__set_error_tablet_ids(
2244
6.12k
            std::vector<TTabletId>(error_tablet_ids.begin(), error_tablet_ids.end()));
2245
6.12k
    finish_task_request.__set_table_id_to_tablet_id_to_delta_num_rows(
2246
6.12k
            table_id_to_tablet_id_to_num_delta_rows);
2247
6.12k
    finish_task(finish_task_request);
2248
6.12k
    remove_task_info(req.task_type, req.signature);
2249
6.12k
}
2250
2251
22
void clear_transaction_task_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2252
22
    const auto& clear_transaction_task_req = req.clear_transaction_task_req;
2253
22
    LOG(INFO) << "get clear transaction task. signature=" << req.signature
2254
22
              << ", transaction_id=" << clear_transaction_task_req.transaction_id
2255
22
              << ", partition_id_size=" << clear_transaction_task_req.partition_id.size();
2256
2257
22
    Status status;
2258
2259
22
    if (clear_transaction_task_req.transaction_id > 0) {
2260
        // transaction_id should be greater than zero.
2261
        // If it is not greater than zero, no need to execute
2262
        // the following clear_transaction_task() function.
2263
22
        if (!clear_transaction_task_req.partition_id.empty()) {
2264
4
            engine.clear_transaction_task(clear_transaction_task_req.transaction_id,
2265
4
                                          clear_transaction_task_req.partition_id);
2266
18
        } else {
2267
18
            engine.clear_transaction_task(clear_transaction_task_req.transaction_id);
2268
18
        }
2269
22
        LOG(INFO) << "finish to clear transaction task. signature=" << req.signature
2270
22
                  << ", transaction_id=" << clear_transaction_task_req.transaction_id;
2271
22
    } else {
2272
0
        LOG(WARNING) << "invalid transaction id " << clear_transaction_task_req.transaction_id
2273
0
                     << ". signature= " << req.signature;
2274
0
    }
2275
2276
22
    TFinishTaskRequest finish_task_request;
2277
22
    finish_task_request.__set_task_status(status.to_thrift());
2278
22
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2279
22
    finish_task_request.__set_task_type(req.task_type);
2280
22
    finish_task_request.__set_signature(req.signature);
2281
2282
22
    finish_task(finish_task_request);
2283
22
    remove_task_info(req.task_type, req.signature);
2284
22
}
2285
2286
20
void alter_tablet_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2287
20
    int64_t signature = req.signature;
2288
20
    LOG(INFO) << "get alter table task, signature: " << signature;
2289
20
    bool is_task_timeout = false;
2290
20
    if (req.__isset.recv_time) {
2291
20
        int64_t time_elapsed = time(nullptr) - req.recv_time;
2292
20
        if (time_elapsed > config::report_task_interval_seconds * 20) {
2293
0
            LOG(INFO) << "task elapsed " << time_elapsed
2294
0
                      << " seconds since it is inserted to queue, it is timeout";
2295
0
            is_task_timeout = true;
2296
0
        }
2297
20
    }
2298
20
    if (!is_task_timeout) {
2299
20
        TFinishTaskRequest finish_task_request;
2300
20
        TTaskType::type task_type = req.task_type;
2301
20
        alter_tablet(engine, req, signature, task_type, &finish_task_request);
2302
20
        finish_task(finish_task_request);
2303
20
    }
2304
20
    doris::g_fragment_executing_count << -1;
2305
20
    int64_t now = duration_cast<std::chrono::milliseconds>(
2306
20
                          std::chrono::system_clock::now().time_since_epoch())
2307
20
                          .count();
2308
20
    g_fragment_last_active_time.set_value(now);
2309
20
    remove_task_info(req.task_type, req.signature);
2310
20
}
2311
2312
9.47k
void alter_cloud_tablet_callback(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
2313
9.47k
    int64_t signature = req.signature;
2314
9.47k
    LOG(INFO) << "get alter table task, signature: " << signature;
2315
9.47k
    bool is_task_timeout = false;
2316
9.47k
    if (req.__isset.recv_time) {
2317
9.47k
        int64_t time_elapsed = time(nullptr) - req.recv_time;
2318
9.47k
        if (time_elapsed > config::report_task_interval_seconds * 20) {
2319
0
            LOG(INFO) << "task elapsed " << time_elapsed
2320
0
                      << " seconds since it is inserted to queue, it is timeout";
2321
0
            is_task_timeout = true;
2322
0
        }
2323
9.47k
    }
2324
9.47k
    if (!is_task_timeout) {
2325
9.47k
        TFinishTaskRequest finish_task_request;
2326
9.47k
        TTaskType::type task_type = req.task_type;
2327
9.47k
        alter_cloud_tablet(engine, req, signature, task_type, &finish_task_request);
2328
9.47k
        finish_task(finish_task_request);
2329
9.47k
    }
2330
9.47k
    doris::g_fragment_executing_count << -1;
2331
9.47k
    int64_t now = duration_cast<std::chrono::milliseconds>(
2332
9.47k
                          std::chrono::system_clock::now().time_since_epoch())
2333
9.47k
                          .count();
2334
9.47k
    g_fragment_last_active_time.set_value(now);
2335
2336
    // Clean up alter_version before remove_task_info to avoid race:
2337
    // remove_task_info allows same-signature re-submit, whose pre_submit_callback
2338
    // would set alter_version, then this cleanup would wipe it.
2339
9.47k
    if (req.__isset.alter_tablet_req_v2) {
2340
9.47k
        const auto& alter_req = req.alter_tablet_req_v2;
2341
9.47k
        auto new_tablet = engine.tablet_mgr().get_tablet(alter_req.new_tablet_id);
2342
9.47k
        auto base_tablet = engine.tablet_mgr().get_tablet(alter_req.base_tablet_id);
2343
9.47k
        if (new_tablet.has_value()) {
2344
9.46k
            new_tablet.value()->set_alter_version(-1);
2345
9.46k
        }
2346
9.47k
        if (base_tablet.has_value()) {
2347
9.46k
            base_tablet.value()->set_alter_version(-1);
2348
9.46k
        }
2349
9.47k
    }
2350
2351
9.47k
    remove_task_info(req.task_type, req.signature);
2352
9.47k
}
2353
2354
9.47k
void set_alter_version_before_enqueue(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
2355
9.47k
    if (!req.__isset.alter_tablet_req_v2) {
2356
0
        return;
2357
0
    }
2358
9.47k
    const auto& alter_req = req.alter_tablet_req_v2;
2359
9.47k
    if (alter_req.alter_version <= 1) {
2360
4.60k
        return;
2361
4.60k
    }
2362
4.86k
    auto new_tablet = engine.tablet_mgr().get_tablet(alter_req.new_tablet_id);
2363
4.86k
    if (!new_tablet.has_value() || new_tablet.value()->tablet_state() == TABLET_RUNNING) {
2364
14
        return;
2365
14
    }
2366
4.85k
    auto base_tablet = engine.tablet_mgr().get_tablet(alter_req.base_tablet_id);
2367
4.85k
    if (!base_tablet.has_value()) {
2368
0
        return;
2369
0
    }
2370
4.85k
    new_tablet.value()->set_alter_version(alter_req.alter_version);
2371
4.85k
    base_tablet.value()->set_alter_version(alter_req.alter_version);
2372
4.85k
    LOG(INFO) << "set alter_version=" << alter_req.alter_version
2373
4.85k
              << " before enqueue, base_tablet=" << alter_req.base_tablet_id
2374
4.85k
              << ", new_tablet=" << alter_req.new_tablet_id;
2375
4.85k
}
2376
2377
0
void gc_binlog_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2378
0
    std::unordered_map<int64_t, int64_t> gc_tablet_infos;
2379
0
    if (!req.__isset.gc_binlog_req) {
2380
0
        LOG(WARNING) << "gc binlog task is not valid";
2381
0
        return;
2382
0
    }
2383
0
    if (!req.gc_binlog_req.__isset.tablet_gc_binlog_infos) {
2384
0
        LOG(WARNING) << "gc binlog task tablet_gc_binlog_infos is not valid";
2385
0
        return;
2386
0
    }
2387
2388
0
    const auto& tablet_gc_binlog_infos = req.gc_binlog_req.tablet_gc_binlog_infos;
2389
0
    for (auto&& tablet_info : tablet_gc_binlog_infos) {
2390
        // gc_tablet_infos.emplace(tablet_info.tablet_id, tablet_info.schema_hash);
2391
0
        gc_tablet_infos.emplace(tablet_info.tablet_id, tablet_info.version);
2392
0
    }
2393
2394
0
    engine.gc_binlogs(gc_tablet_infos);
2395
0
}
2396
2397
5.93k
void visible_version_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2398
5.93k
    const TVisibleVersionReq& visible_version_req = req.visible_version_req;
2399
5.93k
    engine.tablet_manager()->update_partitions_visible_version(
2400
5.93k
            visible_version_req.partition_version);
2401
5.93k
}
2402
2403
void clone_callback(StorageEngine& engine, const ClusterInfo* cluster_info,
2404
0
                    const TAgentTaskRequest& req) {
2405
0
    const auto& clone_req = req.clone_req;
2406
2407
0
    DorisMetrics::instance()->clone_requests_total->increment(1);
2408
0
    LOG(INFO) << "get clone task. signature=" << req.signature;
2409
2410
0
    std::vector<TTabletInfo> tablet_infos;
2411
0
    EngineCloneTask engine_task(engine, clone_req, cluster_info, req.signature, &tablet_infos);
2412
0
    SCOPED_ATTACH_TASK(engine_task.mem_tracker());
2413
0
    auto status = engine_task.execute();
2414
    // Return result to fe
2415
0
    TFinishTaskRequest finish_task_request;
2416
0
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2417
0
    finish_task_request.__set_task_type(req.task_type);
2418
0
    finish_task_request.__set_signature(req.signature);
2419
0
    finish_task_request.__set_task_status(status.to_thrift());
2420
2421
0
    if (!status.ok()) {
2422
0
        DorisMetrics::instance()->clone_requests_failed->increment(1);
2423
0
        LOG_WARNING("failed to clone tablet")
2424
0
                .tag("signature", req.signature)
2425
0
                .tag("tablet_id", clone_req.tablet_id)
2426
0
                .error(status);
2427
0
    } else {
2428
0
        LOG_INFO("successfully clone tablet")
2429
0
                .tag("signature", req.signature)
2430
0
                .tag("tablet_id", clone_req.tablet_id)
2431
0
                .tag("copy_size", engine_task.get_copy_size())
2432
0
                .tag("copy_time_ms", engine_task.get_copy_time_ms());
2433
2434
0
        if (engine_task.is_new_tablet()) {
2435
0
            increase_report_version();
2436
0
            finish_task_request.__set_report_version(s_report_version);
2437
0
        }
2438
0
        finish_task_request.__set_finish_tablet_infos(tablet_infos);
2439
0
        finish_task_request.__set_copy_size(engine_task.get_copy_size());
2440
0
        finish_task_request.__set_copy_time_ms(engine_task.get_copy_time_ms());
2441
0
    }
2442
2443
0
    finish_task(finish_task_request);
2444
0
    remove_task_info(req.task_type, req.signature);
2445
0
}
2446
2447
0
void storage_medium_migrate_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2448
0
    const auto& storage_medium_migrate_req = req.storage_medium_migrate_req;
2449
2450
    // check request and get info
2451
0
    TabletSharedPtr tablet;
2452
0
    DataDir* dest_store = nullptr;
2453
2454
0
    auto status = check_migrate_request(engine, storage_medium_migrate_req, tablet, &dest_store);
2455
0
    if (status.ok()) {
2456
0
        EngineStorageMigrationTask engine_task(engine, tablet, dest_store);
2457
0
        SCOPED_ATTACH_TASK(engine_task.mem_tracker());
2458
0
        status = engine_task.execute();
2459
0
    }
2460
    // fe should ignore this err
2461
0
    if (status.is<FILE_ALREADY_EXIST>()) {
2462
0
        status = Status::OK();
2463
0
    }
2464
0
    if (!status.ok()) {
2465
0
        LOG_WARNING("failed to migrate storage medium")
2466
0
                .tag("signature", req.signature)
2467
0
                .tag("tablet_id", storage_medium_migrate_req.tablet_id)
2468
0
                .error(status);
2469
0
    } else {
2470
0
        LOG_INFO("successfully migrate storage medium")
2471
0
                .tag("signature", req.signature)
2472
0
                .tag("tablet_id", storage_medium_migrate_req.tablet_id);
2473
0
    }
2474
2475
0
    TFinishTaskRequest finish_task_request;
2476
0
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2477
0
    finish_task_request.__set_task_type(req.task_type);
2478
0
    finish_task_request.__set_signature(req.signature);
2479
0
    finish_task_request.__set_task_status(status.to_thrift());
2480
2481
0
    finish_task(finish_task_request);
2482
0
    remove_task_info(req.task_type, req.signature);
2483
0
}
2484
2485
8.96k
void calc_delete_bitmap_callback(CloudStorageEngine& engine, const TAgentTaskRequest& req) {
2486
8.96k
    std::vector<TTabletId> error_tablet_ids;
2487
8.96k
    std::vector<TTabletId> succ_tablet_ids;
2488
8.96k
    Status status;
2489
8.96k
    error_tablet_ids.clear();
2490
8.96k
    const auto& calc_delete_bitmap_req = req.calc_delete_bitmap_req;
2491
8.96k
    CloudEngineCalcDeleteBitmapTask engine_task(engine, calc_delete_bitmap_req, &error_tablet_ids,
2492
8.96k
                                                &succ_tablet_ids);
2493
8.96k
    SCOPED_ATTACH_TASK(engine_task.mem_tracker());
2494
8.96k
    if (req.signature != calc_delete_bitmap_req.transaction_id) {
2495
        // transaction_id may not be the same as req.signature, so add a log here
2496
0
        LOG_INFO("begin to execute calc delete bitmap task")
2497
0
                .tag("signature", req.signature)
2498
0
                .tag("transaction_id", calc_delete_bitmap_req.transaction_id);
2499
0
    }
2500
8.96k
    status = engine_task.execute();
2501
2502
8.96k
    TFinishTaskRequest finish_task_request;
2503
8.96k
    if (!status) {
2504
1
        DorisMetrics::instance()->publish_task_failed_total->increment(1);
2505
1
        LOG_WARNING("failed to calculate delete bitmap")
2506
1
                .tag("signature", req.signature)
2507
1
                .tag("transaction_id", calc_delete_bitmap_req.transaction_id)
2508
1
                .tag("error_tablets_num", error_tablet_ids.size())
2509
1
                .error(status);
2510
1
    }
2511
2512
8.96k
    status.to_thrift(&finish_task_request.task_status);
2513
8.96k
    finish_task_request.__set_backend(BackendOptions::get_local_backend());
2514
8.96k
    finish_task_request.__set_task_type(req.task_type);
2515
8.96k
    finish_task_request.__set_signature(req.signature);
2516
8.96k
    finish_task_request.__set_report_version(s_report_version);
2517
8.96k
    finish_task_request.__set_error_tablet_ids(error_tablet_ids);
2518
8.96k
    finish_task_request.__set_resp_partitions(calc_delete_bitmap_req.partitions);
2519
2520
8.96k
    finish_task(finish_task_request);
2521
8.96k
    remove_task_info(req.task_type, req.signature);
2522
8.96k
}
2523
2524
void make_cloud_committed_rs_visible_callback(CloudStorageEngine& engine,
2525
27.4k
                                              const TAgentTaskRequest& req) {
2526
27.4k
    if (!config::enable_cloud_make_rs_visible_on_be) {
2527
0
        return;
2528
0
    }
2529
27.4k
    LOG(INFO) << "begin to make cloud tmp rs visible, txn_id="
2530
27.4k
              << req.make_cloud_tmp_rs_visible_req.txn_id
2531
27.4k
              << ", tablet_count=" << req.make_cloud_tmp_rs_visible_req.tablet_ids.size();
2532
2533
27.4k
    const auto& make_visible_req = req.make_cloud_tmp_rs_visible_req;
2534
27.4k
    auto& tablet_mgr = engine.tablet_mgr();
2535
2536
27.4k
    int64_t txn_id = make_visible_req.txn_id;
2537
27.4k
    int64_t version_update_time_ms = make_visible_req.__isset.version_update_time_ms
2538
27.4k
                                             ? make_visible_req.version_update_time_ms
2539
27.4k
                                             : 0;
2540
2541
    // Process each tablet involved in this transaction on this BE
2542
174k
    for (int64_t tablet_id : make_visible_req.tablet_ids) {
2543
174k
        auto tablet_result =
2544
174k
                tablet_mgr.get_tablet(tablet_id, /* warmup_data */ false,
2545
174k
                                      /* sync_delete_bitmap */ false,
2546
174k
                                      /* sync_stats */ nullptr, /* force_use_only_cached */ true,
2547
174k
                                      /* cache_on_miss */ false);
2548
174k
        if (!tablet_result.has_value()) {
2549
0
            continue;
2550
0
        }
2551
174k
        auto cloud_tablet = tablet_result.value();
2552
2553
174k
        int64_t partition_id = cloud_tablet->partition_id();
2554
174k
        auto version_iter = make_visible_req.partition_version_map.find(partition_id);
2555
174k
        if (version_iter == make_visible_req.partition_version_map.end()) {
2556
65
            continue;
2557
65
        }
2558
174k
        int64_t visible_version = version_iter->second;
2559
174k
        DBUG_EXECUTE_IF("make_cloud_committed_rs_visible_callback.block", {
2560
174k
            auto target_tablet_id = dp->param<int64_t>("tablet_id", -1);
2561
174k
            auto target_table_id = dp->param<int64_t>("table_id", -1);
2562
174k
            auto version = dp->param<int64_t>("version", -1);
2563
174k
            if ((target_tablet_id == tablet_id || target_table_id == cloud_tablet->table_id()) &&
2564
174k
                version == visible_version) {
2565
174k
                DBUG_BLOCK
2566
174k
            }
2567
174k
        });
2568
174k
        cloud_tablet->try_make_committed_rs_visible(txn_id, visible_version,
2569
174k
                                                    version_update_time_ms);
2570
174k
    }
2571
27.4k
    LOG(INFO) << "make cloud tmp rs visible finished, txn_id=" << txn_id
2572
27.4k
              << ", processed_tablets=" << make_visible_req.tablet_ids.size();
2573
27.4k
}
2574
2575
0
void clean_trash_callback(StorageEngine& engine, const TAgentTaskRequest& req) {
2576
0
    LOG(INFO) << "clean trash start";
2577
0
    DBUG_EXECUTE_IF("clean_trash_callback_sleep", { sleep(100); })
2578
0
    static_cast<void>(engine.start_trash_sweep(nullptr, true));
2579
0
    static_cast<void>(engine.notify_listener("REPORT_DISK_STATE"));
2580
0
    LOG(INFO) << "clean trash finish";
2581
0
}
2582
2583
4
void clean_udf_cache_callback(const TAgentTaskRequest& req) {
2584
4
    const auto& clean_req = req.clean_udf_cache_req;
2585
2586
4
    if (doris::config::enable_java_support) {
2587
4
        static_cast<void>(Jni::Util::clean_udf_class_load_cache(clean_req.function_signature));
2588
4
    }
2589
2590
4
    if (clean_req.__isset.function_id && clean_req.function_id > 0) {
2591
0
        UserFunctionCache::instance()->drop_function_cache(clean_req.function_id);
2592
0
        PythonServerManager::instance().clear_udaf_state_cache(clean_req.function_id);
2593
0
    }
2594
2595
4
    LOG(INFO) << "clean udf cache finish: function_signature=" << clean_req.function_signature;
2596
4
}
2597
2598
1.32k
void report_index_policy_callback(const ClusterInfo* cluster_info) {
2599
1.32k
    TReportRequest request;
2600
1.32k
    auto& index_policy_list = request.index_policy;
2601
1.32k
    const auto& policys = doris::ExecEnv::GetInstance()->index_policy_mgr()->get_index_policys();
2602
17.0k
    for (const auto& policy : policys) {
2603
17.0k
        index_policy_list.emplace_back(policy.second);
2604
17.0k
    }
2605
1.32k
    request.__isset.index_policy = true;
2606
1.32k
    request.__set_backend(BackendOptions::get_local_backend());
2607
1.32k
    bool succ = handle_report(request, cluster_info, "index_policy");
2608
1.32k
    report_index_policy_total << 1;
2609
1.32k
    if (!succ) [[unlikely]] {
2610
0
        report_index_policy_failed << 1;
2611
0
    }
2612
1.32k
}
2613
2614
} // namespace doris