|
| 1 | +// Copyright 2021-present StarRocks, Inc. All rights reserved. |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +#pragma once |
| 16 | + |
| 17 | +#include <atomic> |
| 18 | +#include <functional> |
| 19 | +#include <map> |
| 20 | +#include <memory> |
| 21 | +#include <memory_resource> |
| 22 | +#include <unordered_map> |
| 23 | +#include <utility> |
| 24 | +#include <vector> |
| 25 | + |
| 26 | +#include "base/hash/hash_std.hpp" |
| 27 | +#include "base/uid_util.h" |
| 28 | +#include "compute_env/pipeline/driver_limiter.h" |
| 29 | +#include "compute_env/pipeline/pipeline_timer_context.h" |
| 30 | +#include "compute_env/query/fragment_runtime_state.h" |
| 31 | +#include "compute_env/query_cache/cache_param.h" |
| 32 | +#include "compute_env/workgroup/work_group_fwd.h" |
| 33 | +#include "exec/runtime/adaptive/adaptive_dop_param.h" |
| 34 | +#include "exec/runtime/group_execution/execution_group_fwd.h" |
| 35 | +#include "exec_primitive/exec_node.h" |
| 36 | +#include "exec_primitive/pipeline/pipeline_fwd.h" |
| 37 | +#include "exec_primitive/pipeline/primitives/execution_group_lifecycle.h" |
| 38 | +#include "exec_primitive/pipeline/primitives/fragment_lifecycle.h" |
| 39 | +#include "exec_primitive/pipeline/runtime_filter_hub.h" |
| 40 | +#include "exec_primitive/pipeline/scan/morsel_queue_factory_base.h" |
| 41 | +#include "gen_cpp/FrontendService.h" |
| 42 | +#include "gen_cpp/HeartbeatService.h" |
| 43 | +#include "gen_cpp/InternalService_types.h" |
| 44 | +#include "gen_cpp/PlanNodes_types.h" |
| 45 | +#include "gen_cpp/QueryPlanExtra_types.h" |
| 46 | +#include "gen_cpp/Types_types.h" |
| 47 | +#include "runtime/runtime_state.h" |
| 48 | +#include "storage_primitive/predicate_tree_params.h" |
| 49 | + |
| 50 | +namespace starrocks { |
| 51 | + |
| 52 | +class FragmentAttachment; |
| 53 | +class FragmentDictState; |
| 54 | +class RuntimeFilterPort; |
| 55 | + |
| 56 | +namespace pipeline { |
| 57 | + |
| 58 | +class PassThroughChunkBufferGuard; |
| 59 | + |
| 60 | +using RuntimeFilterPort = starrocks::RuntimeFilterPort; |
| 61 | +using PerDriverScanRangesMap = std::map<int32_t, std::vector<TScanRangeParams>>; |
| 62 | + |
| 63 | +class FragmentContext : public ExecutionGroupLifecycle { |
| 64 | + friend class FragmentContextManager; |
| 65 | + |
| 66 | +public: |
| 67 | + FragmentContext(); |
| 68 | + ~FragmentContext(); |
| 69 | + |
| 70 | + // Fragment-level shared MemPool — delegates to RuntimeState which owns it. |
| 71 | + MemPool* fragment_mem_pool() { return _runtime_state ? _runtime_state->fragment_mem_pool() : nullptr; } |
| 72 | + |
| 73 | + // PMR memory resource — delegates to RuntimeState which owns it. |
| 74 | + std::pmr::memory_resource* mem_resource() { return _runtime_state ? _runtime_state->mem_resource() : nullptr; } |
| 75 | + |
| 76 | + const TUniqueId& query_id() const { return _query_id; } |
| 77 | + void set_query_id(const TUniqueId& query_id) { _query_id = query_id; } |
| 78 | + const TUniqueId& fragment_instance_id() const { return _fragment_runtime_state.fragment_instance_id(); } |
| 79 | + void set_fragment_instance_id(const TUniqueId& fragment_instance_id) { |
| 80 | + _fragment_runtime_state.set_fragment_instance_id(fragment_instance_id); |
| 81 | + } |
| 82 | + FragmentRuntimeState& fragment_runtime_state() { return _fragment_runtime_state; } |
| 83 | + const FragmentRuntimeState& fragment_runtime_state() const { return _fragment_runtime_state; } |
| 84 | + void set_fe_addr(const TNetworkAddress& fe_addr) { _fragment_runtime_state.set_fe_addr(fe_addr); } |
| 85 | + const TNetworkAddress& fe_addr() const { return _fragment_runtime_state.fe_addr(); } |
| 86 | + FragmentFuture finish_future() { return _finish_promise.get_future(); } |
| 87 | + RuntimeState* runtime_state() const { return _runtime_state.get(); } |
| 88 | + std::shared_ptr<RuntimeState> runtime_state_ptr() { return _runtime_state; } |
| 89 | + void set_runtime_state(std::shared_ptr<RuntimeState>&& runtime_state) { _runtime_state = std::move(runtime_state); } |
| 90 | + void attach_to_runtime_state(RuntimeState* state); |
| 91 | + FragmentDictState* dict_state() const { return _fragment_dict_state.get(); } |
| 92 | + ExecNode*& plan() { return _plan; } |
| 93 | + |
| 94 | + void move_tplan(TPlan& tplan); |
| 95 | + const TPlan& tplan() const { return _tplan; } |
| 96 | + void set_data_sink(std::unique_ptr<DataSink> data_sink); |
| 97 | + |
| 98 | + size_t total_dop() const; |
| 99 | + |
| 100 | + bool all_execution_groups_finished() const { return _num_finished_execution_groups == _execution_groups.size(); } |
| 101 | + void count_down_execution_group(size_t val = 1); |
| 102 | + void on_execution_group_finished() override { count_down_execution_group(); } |
| 103 | + void set_fragment_lifecycle(FragmentLifecycleWeakPtr lifecycle) { _fragment_lifecycle = std::move(lifecycle); } |
| 104 | + |
| 105 | + bool need_report_exec_state(); |
| 106 | + void report_exec_state_if_necessary(); |
| 107 | + |
| 108 | + void set_final_status(const Status& status); |
| 109 | + |
| 110 | + Status final_status() const { return _fragment_runtime_state.final_status(); } |
| 111 | + |
| 112 | + void cancel(const Status& status); |
| 113 | + |
| 114 | + void finish() { cancel(Status::OK()); } |
| 115 | + |
| 116 | + MorselQueueFactoryMap& morsel_queue_factories() { return _morsel_queue_factories; } |
| 117 | + |
| 118 | + void set_pipelines(ExecutionGroups&& exec_groups, Pipelines&& pipelines); |
| 119 | + |
| 120 | + Status prepare_all_pipelines(); |
| 121 | + |
| 122 | + void iterate_drivers(const std::function<void(const DriverPtr&)>& call); |
| 123 | + |
| 124 | + void clear_all_drivers(); |
| 125 | + void close_all_execution_groups(); |
| 126 | + |
| 127 | + RuntimeFilterHub* runtime_filter_hub() { return _fragment_runtime_state.runtime_filter_hub(); } |
| 128 | + const RuntimeFilterHub* runtime_filter_hub() const { return _fragment_runtime_state.runtime_filter_hub(); } |
| 129 | + |
| 130 | + RuntimeFilterPort* runtime_filter_port() { return _runtime_state->runtime_filter_port(); } |
| 131 | + |
| 132 | + void prepare_pass_through_chunk_buffer(); |
| 133 | + void destroy_pass_through_chunk_buffer(); |
| 134 | + |
| 135 | + void set_driver_token(DriverLimiter::TokenPtr driver_token) { _driver_token = std::move(driver_token); } |
| 136 | + Status set_pipeline_timer(PipelineTimer* pipeline_timer, std::shared_ptr<PipelineTimerTask> timeout_task); |
| 137 | + void clear_pipeline_timer(); |
| 138 | + PipelineTimerContextPtr pipeline_timer_context() const { return _pipeline_timer_context; } |
| 139 | + |
| 140 | + query_cache::CacheParam& cache_param() { return _cache_param; } |
| 141 | + |
| 142 | + void set_enable_cache(bool flag) { _fragment_runtime_state.set_enable_cache(flag); } |
| 143 | + |
| 144 | + bool enable_cache() const { return _fragment_runtime_state.enable_cache(); } |
| 145 | + |
| 146 | + void set_fragment_attachments(std::vector<std::unique_ptr<FragmentAttachment>>&& attachments); |
| 147 | + |
| 148 | + void set_enable_adaptive_dop(bool val) { _fragment_runtime_state.set_enable_adaptive_dop(val); } |
| 149 | + bool enable_adaptive_dop() const { return _fragment_runtime_state.enable_adaptive_dop(); } |
| 150 | + AdaptiveDopParam& adaptive_dop_param() { return _adaptive_dop_param; } |
| 151 | + |
| 152 | + const PredicateTreeParams& pred_tree_params() const { return _fragment_runtime_state.pred_tree_params(); } |
| 153 | + void set_pred_tree_params(const PredicateTreeParams& params) { |
| 154 | + _fragment_runtime_state.set_pred_tree_params(params); |
| 155 | + } |
| 156 | + |
| 157 | + size_t next_driver_id() { return _next_driver_id++; } |
| 158 | + |
| 159 | + void set_workgroup(workgroup::WorkGroupPtr wg) { _fragment_runtime_state.set_workgroup(std::move(wg)); } |
| 160 | + const workgroup::WorkGroupPtr& workgroup() const { return _fragment_runtime_state.workgroup(); } |
| 161 | + bool enable_resource_group() const { return workgroup() != nullptr; } |
| 162 | + TQueryType::type query_type() const; |
| 163 | + |
| 164 | + size_t expired_log_count() const { return _expired_log_count; } |
| 165 | + |
| 166 | + void set_expired_log_count(size_t val) { _expired_log_count = val; } |
| 167 | + |
| 168 | + void iterate_pipeline(const std::function<void(Pipeline*)>& call); |
| 169 | + Status iterate_pipeline(const std::function<Status(Pipeline*)>& call); |
| 170 | + |
| 171 | + Status prepare_active_drivers(); |
| 172 | + Status submit_active_drivers(DriverExecutor* executor); |
| 173 | + |
| 174 | + bool enable_group_execution() const { return _enable_group_execution; } |
| 175 | + void set_enable_group_execution(bool enable_group_execution) { _enable_group_execution = enable_group_execution; } |
| 176 | + |
| 177 | + void set_report_when_finish(bool report) { _report_when_finish = report; } |
| 178 | + |
| 179 | + // acquire runtime filter from cache |
| 180 | + void acquire_runtime_filters(); |
| 181 | + |
| 182 | + bool enable_event_scheduler() const { return event_scheduler() != nullptr; } |
| 183 | + EventScheduler* event_scheduler() const { return _event_scheduler.get(); } |
| 184 | + void init_event_scheduler(); |
| 185 | + |
| 186 | +private: |
| 187 | + void _close_fragment_attachments(); |
| 188 | + |
| 189 | + bool _enable_group_execution = false; |
| 190 | + // Id of this query |
| 191 | + TUniqueId _query_id; |
| 192 | + // Id of this instance |
| 193 | + FragmentRuntimeState _fragment_runtime_state; |
| 194 | + |
| 195 | + // Hold tplan data datasink from delivery request to create driver lazily |
| 196 | + // after delivery request has been finished. |
| 197 | + TPlan _tplan; |
| 198 | + std::unique_ptr<DataSink> _data_sink; |
| 199 | + |
| 200 | + // promise used to determine whether fragment finished its execution |
| 201 | + FragmentPromise _finish_promise; |
| 202 | + |
| 203 | + // never adjust the order of _runtime_state, _plan, _pipelines and _drivers, since |
| 204 | + // _plan depends on _runtime_state and _drivers depends on _runtime_state. |
| 205 | + std::shared_ptr<RuntimeState> _runtime_state = nullptr; |
| 206 | + std::unique_ptr<FragmentDictState> _fragment_dict_state; |
| 207 | + ExecNode* _plan = nullptr; // lives in _runtime_state->obj_pool() |
| 208 | + size_t _next_driver_id = 0; |
| 209 | + // MorselQueueFactory must outlive the pipelines/operators declared below: a |
| 210 | + // scan operator's ConnectorChunkSource::close() is invoked from ~ScanOperator |
| 211 | + // during _pipelines teardown and calls back into the MorselQueueFactory via |
| 212 | + // ScanOperatorFactory::morsel_queue_factory(). Declaring _morsel_queue_factories |
| 213 | + // before _pipelines makes it destroyed after them, avoiding a use-after-free on |
| 214 | + // non-EOF (cancel/error/limit) teardown paths. |
| 215 | + MorselQueueFactoryMap _morsel_queue_factories; |
| 216 | + // Must outlive PipelineDriver observers owned by _pipelines. |
| 217 | + std::unique_ptr<EventScheduler> _event_scheduler; |
| 218 | + Pipelines _pipelines; |
| 219 | + ExecutionGroups _execution_groups; |
| 220 | + std::atomic<size_t> _num_finished_execution_groups = 0; |
| 221 | + FragmentLifecycleWeakPtr _fragment_lifecycle; |
| 222 | + |
| 223 | + PipelineTimerContextPtr _pipeline_timer_context = nullptr; |
| 224 | + std::shared_ptr<PipelineTimerTask> _timeout_task = nullptr; |
| 225 | + std::shared_ptr<PipelineTimerTask> _report_state_task = nullptr; |
| 226 | + |
| 227 | + DriverLimiter::TokenPtr _driver_token = nullptr; |
| 228 | + |
| 229 | + std::unique_ptr<PassThroughChunkBufferGuard> _pass_through_chunk_buffer_guard; |
| 230 | + |
| 231 | + query_cache::CacheParam _cache_param; |
| 232 | + std::vector<std::unique_ptr<FragmentAttachment>> _fragment_attachments; |
| 233 | + |
| 234 | + AdaptiveDopParam _adaptive_dop_param; |
| 235 | + |
| 236 | + size_t _expired_log_count = 0; |
| 237 | + |
| 238 | + bool _report_when_finish{}; |
| 239 | +}; |
| 240 | +} // namespace pipeline |
| 241 | +} // namespace starrocks |
0 commit comments