@@ -48,12 +48,19 @@ namespace doris::pipeline {
4848
4949PipelineTask::PipelineTask (
5050 PipelinePtr& pipeline, uint32_t task_id, RuntimeState* state,
51- PipelineFragmentContext* fragment_context, RuntimeProfile* parent_profile,
51+ std::shared_ptr< PipelineFragmentContext> fragment_context, RuntimeProfile* parent_profile,
5252 std::map<int ,
5353 std::pair<std::shared_ptr<LocalExchangeSharedState>, std::shared_ptr<Dependency>>>
5454 le_state_map,
5555 int task_idx)
56- : _index(task_id),
56+ :
57+ #ifdef BE_TEST
58+ _query_id (fragment_context ? fragment_context->get_query_id () : TUniqueId()),
59+ #else
60+ _query_id (fragment_context->get_query_id ()),
61+ #endif
62+ _pip_id (pipeline->id ()),
63+ _index(task_id),
5764 _pipeline(pipeline),
5865 _opened(false ),
5966 _state(state),
@@ -64,7 +71,9 @@ PipelineTask::PipelineTask(
6471 _root(_operators.back().get()),
6572 _sink(pipeline->sink_shared_pointer ()),
6673 _le_state_map(std::move(le_state_map)),
67- _task_idx(task_idx) {
74+ _task_idx(task_idx),
75+ _execution_dep(state->get_query_ctx ()->get_execution_dependency()),
76+ _pipeline_name(_pipeline->name ()) {
6877 _pipeline_task_watcher.start ();
6978 _execution_dependencies.push_back (state->get_query_ctx ()->get_execution_dependency ());
7079 auto shared_state = _sink->create_shared_state ();
@@ -117,8 +126,12 @@ Status PipelineTask::prepare(const TPipelineInstanceParams& local_params, const
117126 std::copy (deps.begin (), deps.end (),
118127 std::inserter (_execution_dependencies, _execution_dependencies.end ()));
119128 }
120- if (query_context ()->is_cancelled ()) {
121- clear_blocking_state ();
129+ if (auto fragment = _fragment_context.lock ()) {
130+ if (fragment->get_query_ctx ()->is_cancelled ()) {
131+ clear_blocking_state ();
132+ }
133+ } else {
134+ return Status::InternalError (" Fragment already finished! Query: {}" , print_id (_query_id));
122135 }
123136 return Status::OK ();
124137}
@@ -231,7 +244,7 @@ bool PipelineTask::_wait_to_start() {
231244 // 2. Runtime filter dependencies are ready
232245 // 3. All tablets are loaded into local storage
233246 for (auto * op_dep : _execution_dependencies) {
234- _blocked_dep = op_dep->is_blocked_by (this );
247+ _blocked_dep = op_dep->is_blocked_by (shared_from_this () );
235248 if (_blocked_dep != nullptr ) {
236249 _blocked_dep->start_watcher ();
237250 return true ;
@@ -252,7 +265,7 @@ bool PipelineTask::_is_blocked() {
252265 for (int i = _read_dependencies.size () - 1 ; i >= 0 ; i--) {
253266 // `_read_dependencies` is organized according to operators. For each operator, running condition is met iff all dependencies are ready.
254267 for (auto * dep : _read_dependencies[i]) {
255- _blocked_dep = dep->is_blocked_by (this );
268+ _blocked_dep = dep->is_blocked_by (shared_from_this () );
256269 if (_blocked_dep != nullptr ) {
257270 _blocked_dep->start_watcher ();
258271 return true ;
@@ -271,7 +284,7 @@ bool PipelineTask::_is_blocked() {
271284 }
272285
273286 for (auto * op_dep : _write_dependencies) {
274- _blocked_dep = op_dep->is_blocked_by (this );
287+ _blocked_dep = op_dep->is_blocked_by (shared_from_this () );
275288 if (_blocked_dep != nullptr ) {
276289 _blocked_dep->start_watcher ();
277290 return true ;
@@ -281,6 +294,10 @@ bool PipelineTask::_is_blocked() {
281294}
282295
283296Status PipelineTask::execute (bool * eos) {
297+ auto fragment_context = _fragment_context.lock ();
298+ if (!fragment_context) {
299+ return Status::InternalError (" Fragment already finished! Query: {}" , print_id (_query_id));
300+ }
284301 if (_eos) {
285302 *eos = true ;
286303 return Status::OK ();
@@ -303,11 +320,11 @@ Status PipelineTask::execute(bool* eos) {
303320 }
304321 int64_t delta_cpu_time = cpu_time_stop_watch.elapsed_time ();
305322 _task_cpu_timer->update (delta_cpu_time);
306- auto cpu_qs = query_context ()->get_cpu_statistics ();
323+ auto cpu_qs = fragment_context-> get_query_ctx ()->get_cpu_statistics ();
307324 if (cpu_qs) {
308325 cpu_qs->add_cpu_nanos (delta_cpu_time);
309326 }
310- query_context ()->update_cpu_time (delta_cpu_time);
327+ fragment_context-> get_query_ctx ()->update_cpu_time (delta_cpu_time);
311328 }};
312329 if (!_wake_up_early) {
313330 RETURN_IF_ERROR (_prepare ());
@@ -318,7 +335,7 @@ Status PipelineTask::execute(bool* eos) {
318335 RETURN_IF_ERROR (_prepare ());
319336
320337 // The status must be runnable
321- if (!_opened && !_fragment_context ->is_canceled ()) {
338+ if (!_opened && !fragment_context ->is_canceled ()) {
322339 DBUG_EXECUTE_IF (" PipelineTask::execute.open_sleep" , {
323340 auto required_pipeline_id =
324341 DebugPoints::instance ()->get_debug_param_or_default <int32_t >(
@@ -350,7 +367,7 @@ Status PipelineTask::execute(bool* eos) {
350367
351368 _task_profile->add_info_string (" TaskState" , " Runnable" );
352369 _task_profile->add_info_string (" BlockedByDependency" , " " );
353- while (!_fragment_context ->is_canceled ()) {
370+ while (!fragment_context ->is_canceled ()) {
354371 SCOPED_RAW_TIMER (&time_spent);
355372 if (_is_blocked ()) {
356373 return Status::OK ();
@@ -359,7 +376,7 @@ Status PipelineTask::execute(bool* eos) {
359376 // / When a task is cancelled,
360377 // / its blocking state will be cleared and it will transition to a ready state (though it is not truly ready).
361378 // / Here, checking whether it is cancelled to prevent tasks in a blocking state from being re-executed.
362- if (_fragment_context ->is_canceled ()) {
379+ if (fragment_context ->is_canceled ()) {
363380 break ;
364381 }
365382
@@ -428,7 +445,7 @@ Status PipelineTask::execute(bool* eos) {
428445 }
429446 }
430447
431- RETURN_IF_ERROR (get_task_queue ()->push_back (this ));
448+ RETURN_IF_ERROR (get_task_queue ()->push_back (shared_from_this () ));
432449 return Status::OK ();
433450}
434451
@@ -489,12 +506,34 @@ bool PipelineTask::should_revoke_memory(RuntimeState* state, int64_t revocable_m
489506 }
490507}
491508
509+ void PipelineTask::stop_if_finished () {
510+ auto fragment = _fragment_context.lock ();
511+ if (!fragment) {
512+ return ;
513+ }
514+ SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER (fragment->get_query_ctx ()->query_mem_tracker );
515+ if (auto sink = _sink) {
516+ if (sink->is_finished (_state)) {
517+ clear_blocking_state ();
518+ }
519+ }
520+ }
521+
492522void PipelineTask::finalize () {
523+ auto fragment = _fragment_context.lock ();
524+ if (!fragment) {
525+ return ;
526+ }
527+ SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER (fragment->get_query_ctx ()->query_mem_tracker );
493528 std::unique_lock<std::mutex> lc (_dependency_lock);
494529 _finalized = true ;
495530 _sink_shared_state.reset ();
496531 _op_shared_states.clear ();
497532 _le_state_map.clear ();
533+ _block.reset ();
534+ _operators.clear ();
535+ _sink.reset ();
536+ _pipeline.reset ();
498537}
499538
500539Status PipelineTask::close (Status exec_status, bool close_sink) {
@@ -529,31 +568,37 @@ Status PipelineTask::close(Status exec_status, bool close_sink) {
529568}
530569
531570std::string PipelineTask::debug_string () {
532- std::unique_lock<std::mutex> lc (_dependency_lock);
533571 fmt::memory_buffer debug_string_buffer;
534572
535- fmt::format_to (debug_string_buffer, " QueryId: {}\n " , print_id (query_context ()-> query_id () ));
573+ fmt::format_to (debug_string_buffer, " QueryId: {}\n " , print_id (_query_id ));
536574 fmt::format_to (debug_string_buffer, " InstanceId: {}\n " ,
537575 print_id (_state->fragment_instance_id ()));
538576
577+ fmt::format_to (
578+ debug_string_buffer,
579+ " PipelineTask[this = {}, id = {}, open = {}, eos = {}, finalized = {}, dry run = "
580+ " {}, _wake_up_early = {}, is running = {}]" ,
581+ (void *)this , _index, _opened, _eos, _finalized, _dry_run, _wake_up_early.load (),
582+ is_running ());
583+ std::unique_lock<std::mutex> lc (_dependency_lock);
539584 auto * cur_blocked_dep = _blocked_dep;
540- auto elapsed = _fragment_context->elapsed_time () / 1000000000.0 ;
585+ auto fragment = _fragment_context.lock ();
586+ if (is_finalized () || !fragment) {
587+ fmt::format_to (debug_string_buffer, " pipeline name = {}" , _pipeline_name);
588+ return fmt::to_string (debug_string_buffer);
589+ }
590+ auto elapsed = fragment->elapsed_time () / NANOS_PER_SEC;
541591 fmt::format_to (debug_string_buffer,
542- " PipelineTask[this = {}, id = {}, open = {}, eos = {}, finish = {}, dry run = "
543- " {}, elapse time = {}s, _wake_up_early = {}], block dependency = {}, is "
544- " running = {}\n operators: " ,
545- (void *)this , _index, _opened, _eos, _finalized, _dry_run, elapsed,
546- _wake_up_early.load (),
547- cur_blocked_dep && !_finalized ? cur_blocked_dep->debug_string () : " NULL" ,
548- is_running ());
592+ " elapse time = {}s, block dependency = [{}]\n operators: " , elapsed,
593+ cur_blocked_dep && !is_finalized () ? cur_blocked_dep->debug_string () : " NULL" );
549594 for (size_t i = 0 ; i < _operators.size (); i++) {
550595 fmt::format_to (debug_string_buffer, " \n {}" ,
551596 _opened && !_finalized ? _operators[i]->debug_string (_state, i)
552597 : _operators[i]->debug_string (i));
553598 }
554599 fmt::format_to (debug_string_buffer, " \n {}\n " ,
555- _opened && !_finalized ? _sink->debug_string (_state, _operators.size ())
556- : _sink->debug_string (_operators.size ()));
600+ _opened && !is_finalized () ? _sink->debug_string (_state, _operators.size ())
601+ : _sink->debug_string (_operators.size ()));
557602 if (_finalized) {
558603 return fmt::to_string (debug_string_buffer);
559604 }
@@ -588,10 +633,7 @@ std::string PipelineTask::debug_string() {
588633
589634void PipelineTask::wake_up () {
590635 // call by dependency
591- static_cast <void >(get_task_queue ()->push_back (this ));
636+ static_cast <void >(get_task_queue ()->push_back (shared_from_this () ));
592637}
593638
594- QueryContext* PipelineTask::query_context () {
595- return _fragment_context->get_query_ctx ();
596- }
597639} // namespace doris::pipeline
0 commit comments