106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include "plugin_session_manager.h"
1706f6ba60Sopenharmony_ci
1806f6ba60Sopenharmony_cinamespace {
1906f6ba60Sopenharmony_ciconstexpr uint32_t MAX_BUFFER_PAGES = 512 * 1024 * 1024 / 4096;
2006f6ba60Sopenharmony_ci}
2106f6ba60Sopenharmony_ci
2206f6ba60Sopenharmony_ciPluginSessionManager::PluginSessionManager(const PluginServiceWeakPtr& pluginService) : pluginService_(pluginService) {}
2306f6ba60Sopenharmony_ci
2406f6ba60Sopenharmony_ciPluginSessionManager::~PluginSessionManager() {}
2506f6ba60Sopenharmony_ci
2606f6ba60Sopenharmony_cibool PluginSessionManager::CheckBufferConfig(const ProfilerSessionConfig::BufferConfig& bufferConfig)
2706f6ba60Sopenharmony_ci{
2806f6ba60Sopenharmony_ci    const uint32_t pages = bufferConfig.pages();
2906f6ba60Sopenharmony_ci    const auto policy = bufferConfig.policy();
3006f6ba60Sopenharmony_ci    return pages > 0 && pages <= MAX_BUFFER_PAGES &&
3106f6ba60Sopenharmony_ci           (policy == ProfilerSessionConfig::BufferConfig::RECYCLE ||
3206f6ba60Sopenharmony_ci            policy == ProfilerSessionConfig::BufferConfig::FLATTEN);
3306f6ba60Sopenharmony_ci}
3406f6ba60Sopenharmony_ci
3506f6ba60Sopenharmony_cibool PluginSessionManager::CheckPluginSha256(const ProfilerPluginConfig& pluginConfig)
3606f6ba60Sopenharmony_ci{
3706f6ba60Sopenharmony_ci    std::string reqSha = pluginConfig.plugin_sha256();
3806f6ba60Sopenharmony_ci    if (reqSha.size() > 0) { // only check when SHA256 provided in request
3906f6ba60Sopenharmony_ci        auto pluginSvc = pluginService_.lock();
4006f6ba60Sopenharmony_ci        CHECK_NOTNULL(pluginSvc, false, "plugin service null!");
4106f6ba60Sopenharmony_ci
4206f6ba60Sopenharmony_ci        PluginInfo info = {};
4306f6ba60Sopenharmony_ci        std::string name = pluginConfig.name();
4406f6ba60Sopenharmony_ci        CHECK_TRUE(pluginSvc->GetPluginInfo(name, info), false, "get plugin info %s failed!", name.c_str());
4506f6ba60Sopenharmony_ci
4606f6ba60Sopenharmony_ci        std::string devSha = info.sha256;
4706f6ba60Sopenharmony_ci        CHECK_TRUE(devSha == reqSha, false, "SHA256 mismatch: %s, %s!", devSha.c_str(), reqSha.c_str());
4806f6ba60Sopenharmony_ci    }
4906f6ba60Sopenharmony_ci    return true;
5006f6ba60Sopenharmony_ci}
5106f6ba60Sopenharmony_ci
5206f6ba60Sopenharmony_ciPluginSessionPtr PluginSessionManager::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
5306f6ba60Sopenharmony_ci                                                           const ProfilerSessionConfig::BufferConfig& bufferConfig,
5406f6ba60Sopenharmony_ci                                                           const ProfilerDataRepeaterPtr& dataRepeater)
5506f6ba60Sopenharmony_ci{
5606f6ba60Sopenharmony_ci    auto name = pluginConfig.name();
5706f6ba60Sopenharmony_ci    CHECK_TRUE(pluginSessions_.count(name) == 0, nullptr, "plugin name %s exists!", name.c_str());
5806f6ba60Sopenharmony_ci    CHECK_TRUE(CheckBufferConfig(bufferConfig), nullptr, "buffer config invalid!");
5906f6ba60Sopenharmony_ci    CHECK_TRUE(CheckPluginSha256(pluginConfig), nullptr, "SHA256 check failed!");
6006f6ba60Sopenharmony_ci
6106f6ba60Sopenharmony_ci    auto session = std::make_shared<PluginSession>(pluginConfig, bufferConfig, pluginService_, dataRepeater);
6206f6ba60Sopenharmony_ci    CHECK_NOTNULL(session, nullptr, "allocate plugin session for %s failed!", name.c_str());
6306f6ba60Sopenharmony_ci    CHECK_TRUE(session->IsAvailable(), nullptr, "config plugin for %s failed!", name.c_str());
6406f6ba60Sopenharmony_ci    return session;
6506f6ba60Sopenharmony_ci}
6606f6ba60Sopenharmony_ci
6706f6ba60Sopenharmony_ciPluginSessionPtr PluginSessionManager::CreatePluginSession(const ProfilerPluginConfig& pluginConfig,
6806f6ba60Sopenharmony_ci                                                           const ProfilerDataRepeaterPtr& dataRepeater)
6906f6ba60Sopenharmony_ci{
7006f6ba60Sopenharmony_ci    auto name = pluginConfig.name();
7106f6ba60Sopenharmony_ci    CHECK_TRUE(pluginSessions_.count(name) == 0, nullptr, "plugin name %s exists!", name.c_str());
7206f6ba60Sopenharmony_ci    CHECK_TRUE(CheckPluginSha256(pluginConfig), nullptr, "SHA256 check failed!");
7306f6ba60Sopenharmony_ci
7406f6ba60Sopenharmony_ci    auto session = std::make_shared<PluginSession>(pluginConfig, pluginService_, dataRepeater);
7506f6ba60Sopenharmony_ci    CHECK_NOTNULL(session, nullptr, "allocate plugin session for %s failed!", name.c_str());
7606f6ba60Sopenharmony_ci    CHECK_TRUE(session->IsAvailable(), nullptr, "config plugin for %s failed!", name.c_str());
7706f6ba60Sopenharmony_ci    return session;
7806f6ba60Sopenharmony_ci}
7906f6ba60Sopenharmony_ci
8006f6ba60Sopenharmony_cibool PluginSessionManager::CreatePluginSessions(const std::vector<ProfilerPluginConfig>& pluginConfigs,
8106f6ba60Sopenharmony_ci                                                const std::vector<ProfilerSessionConfig::BufferConfig>& bufferConfigs,
8206f6ba60Sopenharmony_ci                                                const ProfilerDataRepeaterPtr& dataRepeater)
8306f6ba60Sopenharmony_ci{
8406f6ba60Sopenharmony_ci    CHECK_TRUE(pluginConfigs.size() == bufferConfigs.size(), false, "buffer and config vector size mismatch %zu, %zu",
8506f6ba60Sopenharmony_ci               bufferConfigs.size(), pluginConfigs.size());
8606f6ba60Sopenharmony_ci
8706f6ba60Sopenharmony_ci    std::map<std::string, PluginSessionPtr> tmpPluginSessions;
8806f6ba60Sopenharmony_ci    for (size_t i = 0; i < pluginConfigs.size(); i++) {
8906f6ba60Sopenharmony_ci        auto session = CreatePluginSession(pluginConfigs[i], bufferConfigs[i], dataRepeater);
9006f6ba60Sopenharmony_ci
9106f6ba60Sopenharmony_ci        // tmpPluginSessions will released if some plugin session create failed
9206f6ba60Sopenharmony_ci        CHECK_NOTNULL(session, false, "create plugin-%zu session failed!", i);
9306f6ba60Sopenharmony_ci        tmpPluginSessions[pluginConfigs[i].name()] = session;
9406f6ba60Sopenharmony_ci    }
9506f6ba60Sopenharmony_ci
9606f6ba60Sopenharmony_ci    // insert all plugin session to pluginSessions_ map
9706f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
9806f6ba60Sopenharmony_ci    for (auto& entry : tmpPluginSessions) {
9906f6ba60Sopenharmony_ci        pluginSessions_.insert(entry);
10006f6ba60Sopenharmony_ci    }
10106f6ba60Sopenharmony_ci    return true;
10206f6ba60Sopenharmony_ci}
10306f6ba60Sopenharmony_ci
10406f6ba60Sopenharmony_cibool PluginSessionManager::CreatePluginSessions(const std::vector<ProfilerPluginConfig>& pluginConfigs,
10506f6ba60Sopenharmony_ci                                                const ProfilerDataRepeaterPtr& dataRepeater)
10606f6ba60Sopenharmony_ci{
10706f6ba60Sopenharmony_ci    std::map<std::string, PluginSessionPtr> tmpPluginSessions;
10806f6ba60Sopenharmony_ci    for (size_t i = 0; i < pluginConfigs.size(); i++) {
10906f6ba60Sopenharmony_ci        auto session = CreatePluginSession(pluginConfigs[i], dataRepeater);
11006f6ba60Sopenharmony_ci
11106f6ba60Sopenharmony_ci        // tmpPluginSessions will released if some plugin session create failed
11206f6ba60Sopenharmony_ci        CHECK_NOTNULL(session, false, "create plugin-%zu session without shmem buffer failed!", i);
11306f6ba60Sopenharmony_ci        tmpPluginSessions[pluginConfigs[i].name()] = session;
11406f6ba60Sopenharmony_ci    }
11506f6ba60Sopenharmony_ci
11606f6ba60Sopenharmony_ci    // insert all plugin session to pluginSessions_ map
11706f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
11806f6ba60Sopenharmony_ci    for (auto& entry : tmpPluginSessions) {
11906f6ba60Sopenharmony_ci        pluginSessions_.insert(entry);
12006f6ba60Sopenharmony_ci    }
12106f6ba60Sopenharmony_ci    return true;
12206f6ba60Sopenharmony_ci}
12306f6ba60Sopenharmony_ci
12406f6ba60Sopenharmony_cibool PluginSessionManager::RemovePluginSessions(const std::vector<std::string>& nameList)
12506f6ba60Sopenharmony_ci{
12606f6ba60Sopenharmony_ci    CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
12706f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
12806f6ba60Sopenharmony_ci    for (auto& name : nameList) {
12906f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
13006f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
13106f6ba60Sopenharmony_ci            continue;
13206f6ba60Sopenharmony_ci        }
13306f6ba60Sopenharmony_ci        pluginSessions_.erase(it);
13406f6ba60Sopenharmony_ci    }
13506f6ba60Sopenharmony_ci    return true;
13606f6ba60Sopenharmony_ci}
13706f6ba60Sopenharmony_ci
13806f6ba60Sopenharmony_cibool PluginSessionManager::InvalidatePluginSessions(const std::vector<std::string>& nameList)
13906f6ba60Sopenharmony_ci{
14006f6ba60Sopenharmony_ci    CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
14106f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
14206f6ba60Sopenharmony_ci    for (auto& name : nameList) {
14306f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
14406f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
14506f6ba60Sopenharmony_ci            continue;
14606f6ba60Sopenharmony_ci        }
14706f6ba60Sopenharmony_ci        it->second->Invalidate();
14806f6ba60Sopenharmony_ci    }
14906f6ba60Sopenharmony_ci    return true;
15006f6ba60Sopenharmony_ci}
15106f6ba60Sopenharmony_ci
15206f6ba60Sopenharmony_cibool PluginSessionManager::StartPluginSessions(const std::vector<std::string>& nameList)
15306f6ba60Sopenharmony_ci{
15406f6ba60Sopenharmony_ci    CHECK_TRUE(nameList.size() > 0, false, "nameList empty!");
15506f6ba60Sopenharmony_ci    pluginNameList_ = std::move(nameList);
15606f6ba60Sopenharmony_ci    // start each plugin sessions
15706f6ba60Sopenharmony_ci    size_t failureCount = 0;
15806f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
15906f6ba60Sopenharmony_ci    for (auto& name : nameList) {
16006f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
16106f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
16206f6ba60Sopenharmony_ci            continue;
16306f6ba60Sopenharmony_ci        }
16406f6ba60Sopenharmony_ci        if (!it->second->Start()) {
16506f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "start session %s FAILED!", it->first.c_str());
16606f6ba60Sopenharmony_ci            failureCount++;
16706f6ba60Sopenharmony_ci        }
16806f6ba60Sopenharmony_ci    }
16906f6ba60Sopenharmony_ci    return failureCount == 0;
17006f6ba60Sopenharmony_ci}
17106f6ba60Sopenharmony_ci
17206f6ba60Sopenharmony_cibool PluginSessionManager::StopPluginSessions(const std::vector<std::string>& nameList)
17306f6ba60Sopenharmony_ci{
17406f6ba60Sopenharmony_ci    // stop each plugin sessions
17506f6ba60Sopenharmony_ci    size_t failureCount = 0;
17606f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
17706f6ba60Sopenharmony_ci    for (auto& name : nameList) {
17806f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
17906f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
18006f6ba60Sopenharmony_ci            continue;
18106f6ba60Sopenharmony_ci        }
18206f6ba60Sopenharmony_ci        if (!it->second->Stop()) {
18306f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "stop session %s FAILED!", it->first.c_str());
18406f6ba60Sopenharmony_ci            failureCount++;
18506f6ba60Sopenharmony_ci        }
18606f6ba60Sopenharmony_ci    }
18706f6ba60Sopenharmony_ci    return failureCount == 0;
18806f6ba60Sopenharmony_ci}
18906f6ba60Sopenharmony_ci
19006f6ba60Sopenharmony_cibool PluginSessionManager::RefreshPluginSession()
19106f6ba60Sopenharmony_ci{
19206f6ba60Sopenharmony_ci    size_t failureCount = 0;
19306f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
19406f6ba60Sopenharmony_ci    for (auto& name : pluginNameList_) {
19506f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
19606f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
19706f6ba60Sopenharmony_ci            continue;
19806f6ba60Sopenharmony_ci        }
19906f6ba60Sopenharmony_ci        if (!it->second->Refresh()) {
20006f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "refresh data %s FAILED!", it->first.c_str());
20106f6ba60Sopenharmony_ci            failureCount++;
20206f6ba60Sopenharmony_ci        }
20306f6ba60Sopenharmony_ci    }
20406f6ba60Sopenharmony_ci    return failureCount == 0;
20506f6ba60Sopenharmony_ci}
20606f6ba60Sopenharmony_ci
20706f6ba60Sopenharmony_cibool PluginSessionManager::CheckStatus(const std::vector<std::string>& nameList, PluginSession::State state)
20806f6ba60Sopenharmony_ci{
20906f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
21006f6ba60Sopenharmony_ci    for (auto& name : nameList) {
21106f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
21206f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
21306f6ba60Sopenharmony_ci            continue;
21406f6ba60Sopenharmony_ci        }
21506f6ba60Sopenharmony_ci        auto actualState = it->second->GetState();
21606f6ba60Sopenharmony_ci        if (actualState != state) {
21706f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "plugin %s state is %d not %d!", it->first.c_str(), actualState, state);
21806f6ba60Sopenharmony_ci            return false;
21906f6ba60Sopenharmony_ci        }
22006f6ba60Sopenharmony_ci    }
22106f6ba60Sopenharmony_ci    return true;
22206f6ba60Sopenharmony_ci}
22306f6ba60Sopenharmony_ci
22406f6ba60Sopenharmony_cistd::vector<PluginSession::State> PluginSessionManager::GetStatus(const std::vector<std::string>& nameList)
22506f6ba60Sopenharmony_ci{
22606f6ba60Sopenharmony_ci    std::vector<PluginSession::State> status;
22706f6ba60Sopenharmony_ci    std::unique_lock<std::mutex> lock(mutex_);
22806f6ba60Sopenharmony_ci    for (auto& name : nameList) {
22906f6ba60Sopenharmony_ci        auto it = pluginSessions_.find(name);
23006f6ba60Sopenharmony_ci        if (it == pluginSessions_.end()) {
23106f6ba60Sopenharmony_ci            continue;
23206f6ba60Sopenharmony_ci        }
23306f6ba60Sopenharmony_ci        status.push_back(it->second->GetState());
23406f6ba60Sopenharmony_ci    }
23506f6ba60Sopenharmony_ci    return status;
23606f6ba60Sopenharmony_ci}
237