Coverage Report

Created: 2024-11-20 12:30

/root/doris/be/src/runtime/exec_env.cpp
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
#include "runtime/exec_env.h"
19
20
#include <gen_cpp/HeartbeatService_types.h>
21
#include <glog/logging.h>
22
23
#include <mutex>
24
#include <utility>
25
26
#include "common/config.h"
27
#include "common/logging.h"
28
#include "olap/olap_define.h"
29
#include "olap/storage_engine.h"
30
#include "olap/tablet_manager.h"
31
#include "runtime/fragment_mgr.h"
32
#include "runtime/frontend_info.h"
33
#include "runtime/load_stream_mgr.h"
34
#include "util/debug_util.h"
35
#include "util/time.h"
36
#include "vec/sink/delta_writer_v2_pool.h"
37
#include "vec/sink/load_stream_map_pool.h"
38
39
namespace doris {
40
41
6
ExecEnv::ExecEnv() = default;
42
43
6
ExecEnv::~ExecEnv() {
44
6
    destroy();
45
6
}
46
47
// TODO(plat1ko): template <class Engine>
48
#ifdef BE_TEST
49
1
void ExecEnv::set_write_cooldown_meta_executors() {
50
1
    _write_cooldown_meta_executors = std::make_unique<WriteCooldownMetaExecutors>();
51
1
}
52
#endif // BE_TEST
53
54
25
Result<BaseTabletSPtr> ExecEnv::get_tablet(int64_t tablet_id) {
55
25
    BaseTabletSPtr tablet;
56
25
    std::string err;
57
25
    tablet = StorageEngine::instance()->tablet_manager()->get_tablet(tablet_id, true, &err);
58
25
    if (tablet == nullptr) {
59
1
        return unexpected(
60
1
                Status::InternalError("failed to get tablet: {}, reason: {}", tablet_id, err));
61
1
    }
62
24
    return tablet;
63
25
}
64
65
0
const std::string& ExecEnv::token() const {
66
0
    return _master_info->token;
67
0
}
68
69
0
std::map<TNetworkAddress, FrontendInfo> ExecEnv::get_frontends() {
70
0
    std::lock_guard<std::mutex> lg(_frontends_lock);
71
0
    return _frontends;
72
0
}
73
74
0
void ExecEnv::update_frontends(const std::vector<TFrontendInfo>& new_fe_infos) {
75
0
    std::lock_guard<std::mutex> lg(_frontends_lock);
76
77
0
    std::set<TNetworkAddress> dropped_fes;
78
79
0
    for (const auto& cur_fe : _frontends) {
80
0
        dropped_fes.insert(cur_fe.first);
81
0
    }
82
83
0
    for (const auto& coming_fe_info : new_fe_infos) {
84
0
        auto itr = _frontends.find(coming_fe_info.coordinator_address);
85
86
0
        if (itr == _frontends.end()) {
87
0
            LOG(INFO) << "A completely new frontend, " << PrintFrontendInfo(coming_fe_info);
88
89
0
            _frontends.insert(std::pair<TNetworkAddress, FrontendInfo>(
90
0
                    coming_fe_info.coordinator_address,
91
0
                    FrontendInfo {coming_fe_info, GetCurrentTimeMicros() / 1000, /*first time*/
92
0
                                  GetCurrentTimeMicros() / 1000 /*last time*/}));
93
94
0
            continue;
95
0
        }
96
97
0
        dropped_fes.erase(coming_fe_info.coordinator_address);
98
99
0
        if (coming_fe_info.process_uuid == 0) {
100
0
            LOG(WARNING) << "Frontend " << PrintFrontendInfo(coming_fe_info)
101
0
                         << " is in an unknown state.";
102
0
        }
103
104
0
        if (coming_fe_info.process_uuid == itr->second.info.process_uuid) {
105
0
            itr->second.last_reveiving_time_ms = GetCurrentTimeMicros() / 1000;
106
0
            continue;
107
0
        }
108
109
        // If we get here, means this frontend has already restarted.
110
0
        itr->second.info.process_uuid = coming_fe_info.process_uuid;
111
0
        itr->second.first_receiving_time_ms = GetCurrentTimeMicros() / 1000;
112
0
        itr->second.last_reveiving_time_ms = GetCurrentTimeMicros() / 1000;
113
0
        LOG(INFO) << "Update frontend " << PrintFrontendInfo(coming_fe_info);
114
0
    }
115
116
0
    for (const auto& dropped_fe : dropped_fes) {
117
0
        LOG(INFO) << "Frontend " << PrintThriftNetworkAddress(dropped_fe)
118
0
                  << " has already been dropped, remove it";
119
0
        _frontends.erase(dropped_fe);
120
0
    }
121
0
}
122
123
4
std::map<TNetworkAddress, FrontendInfo> ExecEnv::get_running_frontends() {
124
4
    std::lock_guard<std::mutex> lg(_frontends_lock);
125
4
    std::map<TNetworkAddress, FrontendInfo> res;
126
4
    const int expired_duration = config::fe_expire_duration_seconds * 1000;
127
4
    const auto now = GetCurrentTimeMicros() / 1000;
128
129
4
    for (const auto& pair : _frontends) {
130
0
        auto& brpc_addr = pair.first;
131
0
        auto& fe_info = pair.second;
132
133
0
        if (fe_info.info.process_uuid == 0) {
134
            // FE is in an unknown state, regart it as alive. conservative
135
0
            res[brpc_addr] = fe_info;
136
0
        } else {
137
0
            if (now - fe_info.last_reveiving_time_ms < expired_duration) {
138
                // If fe info has just been update in last expired_duration, regard it as running.
139
0
                res[brpc_addr] = fe_info;
140
0
            } else {
141
                // Fe info has not been udpate for more than expired_duration, regard it as an abnormal.
142
                // Abnormal means this fe can not connect to master, and it is not dropped from cluster.
143
                // or fe do not have master yet.
144
0
                LOG_EVERY_N(WARNING, 50) << fmt::format(
145
0
                        "Frontend {}:{} has not update its hb for more than {} secs, regard it as "
146
0
                        "abnormal",
147
0
                        brpc_addr.hostname, brpc_addr.port, config::fe_expire_duration_seconds);
148
0
            }
149
0
        }
150
0
    }
151
152
4
    return res;
153
4
}
154
155
0
void ExecEnv::wait_for_all_tasks_done() {
156
    // For graceful shutdown, need to wait for all running queries to stop
157
0
    int32_t wait_seconds_passed = 0;
158
0
    while (true) {
159
0
        int num_queries = _fragment_mgr->running_query_num();
160
0
        if (num_queries < 1) {
161
0
            break;
162
0
        }
163
0
        if (wait_seconds_passed > doris::config::grace_shutdown_wait_seconds) {
164
0
            LOG(INFO) << "There are still " << num_queries << " queries running, but "
165
0
                      << wait_seconds_passed << " seconds passed, has to exist now";
166
0
            break;
167
0
        }
168
0
        LOG(INFO) << "There are still " << num_queries << " queries running, waiting...";
169
0
        sleep(1);
170
0
        ++wait_seconds_passed;
171
0
    }
172
0
}
173
174
} // namespace doris