Coverage Report

Created: 2026-07-24 22:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/load/group_commit/group_commit_mgr.h
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
#pragma once
19
20
#include <gen_cpp/PaloInternalService_types.h>
21
22
#include <atomic>
23
#include <condition_variable>
24
#include <cstdint>
25
#include <future>
26
#include <memory>
27
#include <mutex>
28
#include <set>
29
#include <shared_mutex>
30
#include <thread>
31
#include <unordered_map>
32
#include <utility>
33
34
#include "common/status.h"
35
#include "core/block/block.h"
36
#include "exec/sink/writer/vwal_writer.h"
37
#include "load/group_commit/wal/wal_manager.h"
38
#include "runtime/exec_env.h"
39
#include "util/threadpool.h"
40
41
namespace doris {
42
class ExecEnv;
43
class GroupCommitMgr;
44
class TUniqueId;
45
class RuntimeState;
46
47
class Dependency;
48
49
struct BlockData {
50
0
    BlockData(const std::shared_ptr<Block>& block) : block(block), block_bytes(block->bytes()) {};
51
    std::shared_ptr<Block> block;
52
    size_t block_bytes;
53
};
54
55
class LoadBlockQueue {
56
public:
57
    LoadBlockQueue(const UniqueId& load_instance_id, std::string& label, int64_t txn_id,
58
                   int64_t schema_version, int64_t index_size,
59
                   std::shared_ptr<std::atomic_size_t> all_block_queues_bytes,
60
                   bool wait_internal_group_commit_finish, int64_t group_commit_interval_ms,
61
                   int64_t group_commit_data_bytes)
62
0
            : load_instance_id(load_instance_id),
63
0
              label(label),
64
0
              txn_id(txn_id),
65
0
              schema_version(schema_version),
66
0
              index_size(index_size),
67
0
              wait_internal_group_commit_finish(wait_internal_group_commit_finish),
68
0
              _group_commit_interval_ms(group_commit_interval_ms),
69
0
              _start_time(std::chrono::steady_clock::now()),
70
0
              _last_print_time(_start_time),
71
0
              _group_commit_data_bytes(group_commit_data_bytes),
72
0
              _all_block_queues_bytes(all_block_queues_bytes) {};
73
74
    Status add_block(RuntimeState* runtime_state, std::shared_ptr<Block> block, bool write_wal,
75
                     UniqueId& load_id);
76
    Status get_block(RuntimeState* runtime_state, Block* block, bool* find_block, bool* eos,
77
                     std::shared_ptr<Dependency> get_block_dep);
78
    bool contain_load_id(const UniqueId& load_id);
79
    Status add_load_id(const UniqueId& load_id, const std::shared_ptr<Dependency> put_block_dep);
80
    Status remove_load_id(const UniqueId& load_id);
81
    void cancel(const Status& st);
82
0
    bool need_commit() const { return _need_commit.load(); }
83
84
    Status create_wal(int64_t db_id, int64_t tb_id, int64_t wal_id, const std::string& import_label,
85
                      WalManager* wal_manager, std::vector<TSlotDescriptor>& slot_desc,
86
                      int be_exe_version);
87
    Status close_wal();
88
    bool has_enough_wal_disk_space(size_t estimated_wal_bytes);
89
    void append_dependency(std::shared_ptr<Dependency> finish_dep);
90
    void append_read_dependency(std::shared_ptr<Dependency> read_dep);
91
0
    int64_t get_group_commit_interval_ms() { return _group_commit_interval_ms; };
92
93
0
    std::string debug_string() const {
94
0
        fmt::memory_buffer debug_string_buffer;
95
0
        fmt::format_to(
96
0
                debug_string_buffer,
97
0
                "load_instance_id={}, label={}, txn_id={}, "
98
0
                "wait_internal_group_commit_finish={}, data_size_condition={}, "
99
0
                "group_commit_load_count={}, process_finish={}, _need_commit={}, schema_version={}",
100
0
                load_instance_id.to_string(), label, txn_id, wait_internal_group_commit_finish,
101
0
                data_size_condition, group_commit_load_count, process_finish.load(),
102
0
                _need_commit.load(), schema_version);
103
0
        return fmt::to_string(debug_string_buffer);
104
0
    }
105
106
    UniqueId load_instance_id;
107
    std::string label;
108
    int64_t txn_id;
109
    int64_t schema_version;
110
    int64_t index_size;
111
    bool wait_internal_group_commit_finish = false;
112
    bool data_size_condition = false;
113
114
    // counts of load in one group commit
115
    std::atomic_size_t group_commit_load_count = 0;
116
117
    // only used by fault injection (debug point) to reproduce that multiple loads
118
    // reuse one group commit plan and share a load_id
119
    std::atomic<int> _debug_add_block_seq = 0;
120
121
    // the execute status of this internal group commit
122
    std::mutex mutex;
123
    std::atomic<bool> process_finish = false;
124
    Status status = Status::OK();
125
    std::vector<std::shared_ptr<Dependency>> dependencies;
126
127
private:
128
    void _cancel_without_lock(const Status& st);
129
    std::string _get_load_ids();
130
131
    // the set of load ids of all blocks in this queue
132
    std::map<UniqueId, std::shared_ptr<Dependency>> _load_ids_to_write_dep;
133
    std::vector<std::shared_ptr<Dependency>> _read_deps;
134
    std::list<BlockData> _block_queue;
135
136
    // wal
137
    std::string _wal_base_path;
138
    std::shared_ptr<VWalWriter> _v_wal_writer;
139
140
    // commit
141
    std::atomic<bool> _need_commit = false;
142
    // commit by time interval, can be changed by 'ALTER TABLE my_table SET ("group_commit_interval_ms"="1000");'
143
    int64_t _group_commit_interval_ms;
144
    std::chrono::steady_clock::time_point _start_time;
145
    std::chrono::steady_clock::time_point _last_print_time;
146
    // commit by data size
147
    int64_t _group_commit_data_bytes;
148
    int64_t _data_bytes = 0;
149
150
    // memory back pressure, memory consumption of all tables' load block queues
151
    std::shared_ptr<std::atomic_size_t> _all_block_queues_bytes;
152
    std::condition_variable _get_cond;
153
};
154
155
class GroupCommitTable {
156
public:
157
    GroupCommitTable(ExecEnv* exec_env, doris::ThreadPool* thread_pool, int64_t db_id,
158
                     int64_t table_id, std::shared_ptr<std::atomic_size_t> all_block_queue_bytes,
159
                     GroupCommitMgr* group_commit_mgr)
160
0
            : _exec_env(exec_env),
161
0
              _thread_pool(thread_pool),
162
0
              _all_block_queues_bytes(all_block_queue_bytes),
163
0
              _db_id(db_id),
164
0
              _table_id(table_id),
165
0
              _group_commit_mgr(group_commit_mgr) {};
166
    Status get_first_block_load_queue(int64_t table_id, int64_t base_schema_version,
167
                                      int64_t index_size, const UniqueId& load_id,
168
                                      std::shared_ptr<LoadBlockQueue>& load_block_queue,
169
                                      int be_exe_version, TGroupCommitMode::type group_commit_mode,
170
                                      std::shared_ptr<Dependency> create_plan_dep,
171
                                      std::shared_ptr<Dependency> put_block_dep);
172
    Status get_load_block_queue(const TUniqueId& instance_id,
173
                                std::shared_ptr<LoadBlockQueue>& load_block_queue,
174
                                std::shared_ptr<Dependency> get_block_dep);
175
    void remove_load_id(const UniqueId& load_id);
176
    Status submit_create_group_commit_load();
177
178
private:
179
    Status _submit_create_group_commit_load();
180
    Status _check_wal_backlog(TGroupCommitMode::type group_commit_mode);
181
    Status _create_group_commit_load(int be_exe_version,
182
                                     const std::shared_ptr<MemTrackerLimiter>& mem_tracker,
183
                                     std::shared_ptr<LoadBlockQueue>& created_load_block_queue);
184
    Status _exec_plan_fragment(int64_t db_id, int64_t table_id, const std::string& label,
185
                               int64_t txn_id, const TPipelineFragmentParams& pipeline_params);
186
    Status _finish_group_commit_load(int64_t db_id, int64_t table_id, const std::string& label,
187
                                     int64_t txn_id, const TUniqueId& instance_id, Status& status,
188
                                     RuntimeState* state);
189
190
    ExecEnv* _exec_env = nullptr;
191
    ThreadPool* _thread_pool = nullptr;
192
    // memory consumption of all tables' load block queues, used for memory back pressure.
193
    std::shared_ptr<std::atomic_size_t> _all_block_queues_bytes;
194
195
    int64_t _db_id;
196
    int64_t _table_id;
197
    GroupCommitMgr* _group_commit_mgr = nullptr;
198
199
    std::mutex _lock;
200
    // fragment_instance_id to load_block_queue
201
    std::unordered_map<UniqueId, std::shared_ptr<LoadBlockQueue>> _load_block_queues;
202
    bool _is_creating_plan_fragment = false;
203
    // user_load_id -> <create_plan_dep, put_block_dep, base_schema_version, index_size>
204
    std::unordered_map<UniqueId, std::tuple<std::shared_ptr<Dependency>,
205
                                            std::shared_ptr<Dependency>, int64_t, int64_t>>
206
            _create_plan_deps;
207
    std::string _create_plan_failed_reason;
208
    int _create_plan_be_exe_version = 0;
209
    int64_t _create_plan_start_time_ms = 0;
210
};
211
212
class GroupCommitMgr {
213
public:
214
    GroupCommitMgr(ExecEnv* exec_env);
215
    virtual ~GroupCommitMgr();
216
217
    void stop();
218
219
    // used when init group_commit_scan_node
220
    Status get_load_block_queue(int64_t table_id, const TUniqueId& instance_id,
221
                                std::shared_ptr<LoadBlockQueue>& load_block_queue,
222
                                std::shared_ptr<Dependency> get_block_dep);
223
    Status get_first_block_load_queue(int64_t db_id, int64_t table_id, int64_t base_schema_version,
224
                                      int64_t index_size, const UniqueId& load_id,
225
                                      std::shared_ptr<LoadBlockQueue>& load_block_queue,
226
                                      int be_exe_version, TGroupCommitMode::type group_commit_mode,
227
                                      std::shared_ptr<Dependency> create_plan_dep,
228
                                      std::shared_ptr<Dependency> put_block_dep);
229
    void remove_load_id(int64_t table_id, const UniqueId& load_id);
230
    std::promise<Status> debug_promise;
231
    std::future<Status> debug_future = debug_promise.get_future();
232
    void add_need_create_plan_table(int64_t table_id);
233
0
    std::shared_ptr<MemTrackerLimiter> group_commit_mem_tracker() {
234
0
        return _group_commit_mem_tracker;
235
0
    }
236
237
private:
238
    void _create_plan_worker();
239
240
    ExecEnv* _exec_env = nullptr;
241
    std::unique_ptr<doris::ThreadPool> _thread_pool;
242
    // memory consumption of all tables' load block queues, used for memory back pressure.
243
    std::shared_ptr<std::atomic_size_t> _all_block_queues_bytes;
244
245
    std::mutex _lock;
246
    // TODO remove table when unused
247
    std::unordered_map<int64_t, std::shared_ptr<GroupCommitTable>> _table_map;
248
    std::mutex _need_create_plan_lock;
249
    std::condition_variable _need_create_plan_cv;
250
    std::set<int64_t> _need_create_plan_tables;
251
    bool _stopped = false;
252
    std::thread _create_plan_thread;
253
    std::shared_ptr<MemTrackerLimiter> _group_commit_mem_tracker;
254
};
255
256
} // namespace doris