|
| 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 | +#include "orchestration/orchestration_env.h" |
| 16 | + |
| 17 | +#include <unistd.h> |
| 18 | + |
| 19 | +#include <memory> |
| 20 | +#include <vector> |
| 21 | + |
| 22 | +#include "common/config_exec_env_fwd.h" |
| 23 | +#include "common/logging.h" |
| 24 | +#include "common/process_exit.h" |
| 25 | +#include "common/system/master_info.h" |
| 26 | +#include "compute_env/compute_env.h" |
| 27 | +#include "compute_env/profile_report_worker.h" |
| 28 | +#include "exec/exec_env.h" |
| 29 | +#include "exec/pipeline/pipeline_fragment_reporter.h" |
| 30 | +#include "exec/runtime/query_context_manager.h" |
| 31 | +#include "orchestration/external_scan_context_mgr.h" |
| 32 | +#include "orchestration/external_scan_orchestrator.h" |
| 33 | +#include "orchestration/fragment_mgr.h" |
| 34 | +#include "orchestration/orchestration_metrics.h" |
| 35 | +#include "orchestration/routine_load_task_executor.h" |
| 36 | +#include "orchestration/runtime_filter_worker.h" |
| 37 | +#include "orchestration/stream_load_orchestrator.h" |
| 38 | + |
| 39 | +namespace starrocks::orchestration { |
| 40 | + |
| 41 | +OrchestrationEnv::OrchestrationEnv() = default; |
| 42 | + |
| 43 | +OrchestrationEnv::~OrchestrationEnv() { |
| 44 | + destroy(); |
| 45 | +} |
| 46 | + |
| 47 | +Status OrchestrationEnv::init(ExecEnv* exec_env, MetricRegistry* metrics, StreamLoadExecutor* stream_load_executor) { |
| 48 | + DCHECK(exec_env != nullptr); |
| 49 | + DCHECK(stream_load_executor != nullptr); |
| 50 | + _exec_env = exec_env; |
| 51 | + |
| 52 | + _fragment_mgr = std::make_unique<FragmentMgr>(exec_env, metrics); |
| 53 | + |
| 54 | + ProfileReportWorkerOptions profile_report_worker_options; |
| 55 | + profile_report_worker_options.report_non_pipeline_fragments = |
| 56 | + [this](const std::vector<TUniqueId>& non_pipeline_need_report_fragment_ids) { |
| 57 | + DCHECK(_fragment_mgr != nullptr); |
| 58 | + return _fragment_mgr->report_fragments(non_pipeline_need_report_fragment_ids); |
| 59 | + }; |
| 60 | + profile_report_worker_options.report_pipeline_fragments = |
| 61 | + [exec_env](const std::vector<PipeLineReportTaskKey>& pipeline_need_report_query_fragment_ids) { |
| 62 | + DCHECK(exec_env->query_context_mgr() != nullptr); |
| 63 | + return report_pipeline_fragments(exec_env->query_context_mgr(), |
| 64 | + pipeline_need_report_query_fragment_ids); |
| 65 | + }; |
| 66 | + RETURN_IF_ERROR(exec_env->compute_env()->init_profile_report_worker(std::move(profile_report_worker_options))); |
| 67 | + |
| 68 | + _runtime_filter_worker = |
| 69 | + std::make_unique<RuntimeFilterWorker>(&exec_env->runtime_services(), &exec_env->rpc_services(), |
| 70 | + exec_env->query_pool_mem_tracker(), _fragment_mgr.get()); |
| 71 | + _runtime_filter_worker_started = true; |
| 72 | + exec_env->set_runtime_filter_services(_runtime_filter_worker.get(), _runtime_filter_worker.get()); |
| 73 | + |
| 74 | + _metrics = std::make_unique<OrchestrationMetrics>(); |
| 75 | + _metrics->install( |
| 76 | + metrics, [this] { return _runtime_filter_worker == nullptr ? nullptr : _runtime_filter_worker->metrics(); }, |
| 77 | + [this] { return _runtime_filter_worker == nullptr ? 0 : _runtime_filter_worker->queue_size(); }); |
| 78 | + |
| 79 | + _external_scan_context_mgr = std::make_unique<ExternalScanContextMgr>(exec_env, metrics); |
| 80 | + _external_scan_orchestrator = |
| 81 | + std::make_unique<ExternalScanOrchestrator>(exec_env, _external_scan_context_mgr.get()); |
| 82 | + |
| 83 | + _stream_load_orchestrator = std::make_unique<StreamLoadOrchestrator>(exec_env, _fragment_mgr.get()); |
| 84 | + |
| 85 | + _routine_load_task_executor = |
| 86 | + std::make_unique<RoutineLoadTaskExecutor>(exec_env, _stream_load_orchestrator.get(), stream_load_executor); |
| 87 | + RETURN_IF_ERROR(_routine_load_task_executor->init(metrics)); |
| 88 | + _routine_load_task_executor_started = true; |
| 89 | + |
| 90 | + return Status::OK(); |
| 91 | +} |
| 92 | + |
| 93 | +void OrchestrationEnv::wait_for_finish() { |
| 94 | + if (config::loop_count_wait_fragments_finish < 0) { |
| 95 | + LOG(WARNING) << "'config::loop_count_wait_fragments_finish' is set to a negative integer, ignore it."; |
| 96 | + return; |
| 97 | + } |
| 98 | + |
| 99 | + size_t max_loop_secs = config::loop_count_wait_fragments_finish * 10; |
| 100 | + if (max_loop_secs == 0) { |
| 101 | + return; |
| 102 | + } |
| 103 | + |
| 104 | + size_t running_fragments = _get_running_fragments_count(); |
| 105 | + size_t loop_secs = 0; |
| 106 | + |
| 107 | + // TODO: decouple the heartbeat with the graceful exit |
| 108 | + // only wait for frontend's heartbeat when the node is ever received heartbeats from the frontend |
| 109 | + bool need_wait_frontend_hb = config::graceful_exit_wait_for_frontend_heartbeat && get_backend_id().has_value(); |
| 110 | + |
| 111 | + while ((running_fragments > 0 || (need_wait_frontend_hb && !is_frontend_aware_of_exit())) && |
| 112 | + loop_secs < max_loop_secs) { |
| 113 | + LOG(INFO) << "Frontend is aware of exit: " << is_frontend_aware_of_exit() << ", " << running_fragments |
| 114 | + << " fragment(s) are still running..."; |
| 115 | + sleep(1); |
| 116 | + running_fragments = _get_running_fragments_count(); |
| 117 | + loop_secs++; |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +void OrchestrationEnv::stop() { |
| 122 | + if (_exec_env != nullptr && _exec_env->compute_env() != nullptr && _exec_env->profile_report_worker() != nullptr) { |
| 123 | + _exec_env->compute_env()->stop_profile_report_worker(); |
| 124 | + } |
| 125 | + if (_runtime_filter_worker != nullptr && _runtime_filter_worker_started) { |
| 126 | + _runtime_filter_worker->close(); |
| 127 | + _runtime_filter_worker_started = false; |
| 128 | + } |
| 129 | + if (_routine_load_task_executor != nullptr && _routine_load_task_executor_started) { |
| 130 | + _routine_load_task_executor->stop(); |
| 131 | + _routine_load_task_executor_started = false; |
| 132 | + } |
| 133 | + if (_fragment_mgr != nullptr) { |
| 134 | + _fragment_mgr->close(); |
| 135 | + } |
| 136 | +} |
| 137 | + |
| 138 | +void OrchestrationEnv::destroy() { |
| 139 | + stop(); |
| 140 | + _metrics.reset(); |
| 141 | + _runtime_filter_worker.reset(); |
| 142 | + _routine_load_task_executor.reset(); |
| 143 | + _stream_load_orchestrator.reset(); |
| 144 | + _external_scan_orchestrator.reset(); |
| 145 | + _external_scan_context_mgr.reset(); |
| 146 | + if (_exec_env != nullptr && _exec_env->compute_env() != nullptr) { |
| 147 | + _exec_env->compute_env()->destroy_profile_report_worker(); |
| 148 | + _exec_env->set_runtime_filter_services(nullptr, nullptr); |
| 149 | + _exec_env = nullptr; |
| 150 | + } |
| 151 | + _fragment_mgr.reset(); |
| 152 | +} |
| 153 | + |
| 154 | +size_t OrchestrationEnv::_get_running_fragments_count() const { |
| 155 | + const auto non_pipeline_fragments = _fragment_mgr == nullptr ? 0 : _fragment_mgr->running_fragment_count(); |
| 156 | + const auto pipeline_fragments = (_exec_env == nullptr || _exec_env->query_context_mgr() == nullptr) |
| 157 | + ? 0 |
| 158 | + : _exec_env->query_context_mgr()->size(); |
| 159 | + return non_pipeline_fragments + pipeline_fragments; |
| 160 | +} |
| 161 | + |
| 162 | +} // namespace starrocks::orchestration |
0 commit comments