Coverage Report

Created: 2025-07-23 16:39

/root/doris/be/src/runtime/fragment_mgr.h
Line
Count
Source (jump to first uncovered line)
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/FrontendService_types.h>
21
#include <gen_cpp/QueryPlanExtra_types.h>
22
#include <gen_cpp/Types_types.h>
23
#include <gen_cpp/types.pb.h>
24
25
#include <cstdint>
26
#include <functional>
27
#include <iosfwd>
28
#include <memory>
29
#include <mutex>
30
#include <string>
31
#include <unordered_map>
32
#include <vector>
33
34
#include "common/status.h"
35
#include "gutil/ref_counted.h"
36
#include "http/rest_monitor_iface.h"
37
#include "runtime/query_context.h"
38
#include "runtime_filter_mgr.h"
39
#include "util/countdown_latch.h"
40
#include "util/hash_util.hpp" // IWYU pragma: keep
41
#include "util/metrics.h"
42
43
namespace butil {
44
class IOBufAsZeroCopyInputStream;
45
}
46
47
namespace doris {
48
extern bvar::Adder<uint64_t> g_fragment_executing_count;
49
extern bvar::Status<uint64_t> g_fragment_last_active_time;
50
51
namespace pipeline {
52
class PipelineFragmentContext;
53
} // namespace pipeline
54
class QueryContext;
55
class ExecEnv;
56
class ThreadPool;
57
class TExecPlanFragmentParams;
58
class PExecPlanFragmentStartRequest;
59
class PMergeFilterRequest;
60
class PPublishFilterRequest;
61
class RuntimeProfile;
62
class RuntimeState;
63
class TPipelineFragmentParams;
64
class TPipelineInstanceParams;
65
class TScanColumnDesc;
66
class TScanOpenParams;
67
class Thread;
68
class WorkloadQueryInfo;
69
70
std::string to_load_error_http_path(const std::string& file_name);
71
72
template <typename Key, typename Value, typename ValueType>
73
class ConcurrentContextMap {
74
public:
75
    using ApplyFunction = std::function<Status(phmap::flat_hash_map<Key, Value>&)>;
76
    ConcurrentContextMap();
77
    Value find(const Key& query_id);
78
    void insert(const Key& query_id, std::shared_ptr<ValueType>);
79
    void clear();
80
    void erase(const Key& query_id);
81
4
    size_t num_items() const {
82
4
        size_t n = 0;
83
512
        for (auto& pair : _internal_map) {
  Branch (83:25): [True: 512, False: 4]
  Branch (83:25): [True: 0, False: 0]
84
512
            std::shared_lock lock(*pair.first);
85
512
            auto& map = pair.second;
86
512
            n += map.size();
87
512
        }
88
4
        return n;
89
4
    }
_ZNK5doris20ConcurrentContextMapINS_9TUniqueIdESt8weak_ptrINS_12QueryContextEES3_E9num_itemsEv
Line
Count
Source
81
4
    size_t num_items() const {
82
4
        size_t n = 0;
83
512
        for (auto& pair : _internal_map) {
  Branch (83:25): [True: 512, False: 4]
84
512
            std::shared_lock lock(*pair.first);
85
512
            auto& map = pair.second;
86
512
            n += map.size();
87
512
        }
88
4
        return n;
89
4
    }
Unexecuted instantiation: _ZNK5doris20ConcurrentContextMapISt4pairINS_9TUniqueIdEiESt10shared_ptrINS_8pipeline23PipelineFragmentContextEES6_E9num_itemsEv
90
12
    void apply(ApplyFunction&& function) {
91
1.53k
        for (auto& pair : _internal_map) {
  Branch (91:25): [True: 512, False: 4]
  Branch (91:25): [True: 1.02k, False: 8]
92
            // TODO: Now only the cancel worker do the GC the _query_ctx_map. each query must
93
            // do erase the finish query unless in _query_ctx_map. Rethink the logic is ok
94
1.53k
            std::unique_lock lock(*pair.first);
95
1.53k
            static_cast<void>(function(pair.second));
96
1.53k
        }
97
12
    }
_ZN5doris20ConcurrentContextMapISt4pairINS_9TUniqueIdEiESt10shared_ptrINS_8pipeline23PipelineFragmentContextEES6_E5applyEOSt8functionIFNS_6StatusERN5phmap13flat_hash_mapIS3_S7_NSB_4HashIS3_EENSB_7EqualToIS3_EESaIS1_IKS3_S7_EEEEEE
Line
Count
Source
90
4
    void apply(ApplyFunction&& function) {
91
512
        for (auto& pair : _internal_map) {
  Branch (91:25): [True: 512, False: 4]
92
            // TODO: Now only the cancel worker do the GC the _query_ctx_map. each query must
93
            // do erase the finish query unless in _query_ctx_map. Rethink the logic is ok
94
512
            std::unique_lock lock(*pair.first);
95
512
            static_cast<void>(function(pair.second));
96
512
        }
97
4
    }
_ZN5doris20ConcurrentContextMapINS_9TUniqueIdESt8weak_ptrINS_12QueryContextEES3_E5applyEOSt8functionIFNS_6StatusERN5phmap13flat_hash_mapIS1_S4_NS8_4HashIS1_EENS8_7EqualToIS1_EESaISt4pairIKS1_S4_EEEEEE
Line
Count
Source
90
8
    void apply(ApplyFunction&& function) {
91
1.02k
        for (auto& pair : _internal_map) {
  Branch (91:25): [True: 1.02k, False: 8]
92
            // TODO: Now only the cancel worker do the GC the _query_ctx_map. each query must
93
            // do erase the finish query unless in _query_ctx_map. Rethink the logic is ok
94
1.02k
            std::unique_lock lock(*pair.first);
95
1.02k
            static_cast<void>(function(pair.second));
96
1.02k
        }
97
8
    }
98
99
    Status apply_if_not_exists(const Key& query_id, std::shared_ptr<ValueType>& query_ctx,
100
                               ApplyFunction&& function);
101
102
private:
103
    // The lock should only be used to protect the structures in fragment manager. Has to be
104
    // used in a very small scope because it may dead lock. For example, if the _lock is used
105
    // in prepare stage, the call path is  prepare --> expr prepare --> may call allocator
106
    // when allocate failed, allocator may call query_is_cancelled, query is callced will also
107
    // call _lock, so that there is dead lock.
108
    std::vector<std::pair<std::unique_ptr<std::shared_mutex>, phmap::flat_hash_map<Key, Value>>>
109
            _internal_map;
110
};
111
112
// This class used to manage all the fragment execute in this instance
113
class FragmentMgr : public RestMonitorIface {
114
public:
115
    using FinishCallback = std::function<void(RuntimeState*, Status*)>;
116
117
    FragmentMgr(ExecEnv* exec_env);
118
    ~FragmentMgr() override;
119
120
    void stop();
121
122
    // execute one plan fragment
123
    Status exec_plan_fragment(const TExecPlanFragmentParams& params, const QuerySource query_type);
124
125
    Status exec_plan_fragment(const TPipelineFragmentParams& params, const QuerySource query_type);
126
127
    void remove_pipeline_context(
128
            std::shared_ptr<pipeline::PipelineFragmentContext> pipeline_context);
129
130
    // TODO(zc): report this is over
131
    Status exec_plan_fragment(const TExecPlanFragmentParams& params, const QuerySource query_type,
132
                              const FinishCallback& cb);
133
134
    Status exec_plan_fragment(const TPipelineFragmentParams& params, const QuerySource query_type,
135
                              const FinishCallback& cb);
136
137
    Status start_query_execution(const PExecPlanFragmentStartRequest* request);
138
139
    Status trigger_pipeline_context_report(const ReportStatusRequest,
140
                                           std::shared_ptr<pipeline::PipelineFragmentContext>&&);
141
142
    // Can be used in both version.
143
    void cancel_query(const TUniqueId query_id, const Status reason);
144
145
    void cancel_worker();
146
147
    void debug(std::stringstream& ss) override;
148
149
    // input: TQueryPlanInfo fragment_instance_id
150
    // output: selected_columns
151
    // execute external query, all query info are packed in TScanOpenParams
152
    Status exec_external_plan_fragment(const TScanOpenParams& params,
153
                                       const TQueryPlanInfo& t_query_plan_info,
154
                                       const TUniqueId& query_id,
155
                                       const TUniqueId& fragment_instance_id,
156
                                       std::vector<TScanColumnDesc>* selected_columns);
157
158
    Status apply_filterv2(const PPublishFilterRequestV2* request,
159
                          butil::IOBufAsZeroCopyInputStream* attach_data);
160
161
    Status merge_filter(const PMergeFilterRequest* request,
162
                        butil::IOBufAsZeroCopyInputStream* attach_data);
163
164
    Status send_filter_size(const PSendFilterSizeRequest* request);
165
166
    Status sync_filter_size(const PSyncFilterSizeRequest* request);
167
168
    std::string to_http_path(const std::string& file_name);
169
170
    void coordinator_callback(const ReportStatusRequest& req);
171
172
0
    ThreadPool* get_thread_pool() { return _thread_pool.get(); }
173
174
0
    int32_t running_query_num() { return _query_ctx_map.num_items(); }
175
176
    std::string dump_pipeline_tasks(int64_t duration = 0);
177
    std::string dump_pipeline_tasks(TUniqueId& query_id);
178
179
    void get_runtime_query_info(std::vector<WorkloadQueryInfo>* _query_info_list);
180
181
    Status get_realtime_exec_status(const TUniqueId& query_id,
182
                                    TReportExecStatusParams* exec_status);
183
184
    std::shared_ptr<QueryContext> get_query_ctx(const TUniqueId& query_id);
185
186
private:
187
    std::shared_ptr<QueryContext> _get_or_erase_query_ctx(const TUniqueId& query_id);
188
189
    struct BrpcItem {
190
        TNetworkAddress network_address;
191
        std::vector<std::weak_ptr<QueryContext>> queries;
192
    };
193
194
    template <typename Param>
195
    void _set_scan_concurrency(const Param& params, QueryContext* query_ctx);
196
197
    Status _get_or_create_query_ctx(const TPipelineFragmentParams& params, TUniqueId query_id,
198
                                    bool pipeline, QuerySource query_type,
199
                                    std::shared_ptr<QueryContext>& query_ctx);
200
201
    // This is input params
202
    ExecEnv* _exec_env = nullptr;
203
204
    // (QueryID, FragmentID) -> PipelineFragmentContext
205
    ConcurrentContextMap<std::pair<TUniqueId, int>,
206
                         std::shared_ptr<pipeline::PipelineFragmentContext>,
207
                         pipeline::PipelineFragmentContext>
208
            _pipeline_map;
209
210
    // query id -> QueryContext
211
    ConcurrentContextMap<TUniqueId, std::weak_ptr<QueryContext>, QueryContext> _query_ctx_map;
212
    std::unordered_map<TUniqueId, std::unordered_map<int, int64_t>> _bf_size_map;
213
214
    CountDownLatch _stop_background_threads_latch;
215
    scoped_refptr<Thread> _cancel_thread;
216
    // every job is a pool
217
    std::unique_ptr<ThreadPool> _thread_pool;
218
219
    std::shared_ptr<MetricEntity> _entity;
220
    UIntGauge* timeout_canceled_fragment_count = nullptr;
221
222
    RuntimeFilterMergeController _runtimefilter_controller;
223
};
224
225
uint64_t get_fragment_executing_count();
226
uint64_t get_fragment_last_active_time();
227
228
} // namespace doris