* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
#include "DataBaseManager.h"
#include "BaselineManager.h"
#include "TraceTime.h"
#include "MemoryParse.h"
#include "QueryMemoryViewHandler.h"
namespace Dic {
namespace Module {
namespace Memory {
using namespace Dic::Server;
bool QueryMemoryViewHandler::HandleRequest(std::unique_ptr<Protocol::Request> requestPtr) {
MemoryViewRequest &request = dynamic_cast<MemoryViewRequest &>(*requestPtr.get());
std::unique_ptr<MemoryViewResponse> responsePtr = std::make_unique<MemoryViewResponse>();
MemoryViewResponse &response = *responsePtr.get();
SetBaseResponse(request, response);
std::string errorMsg;
if (!request.params.CommonCheck(errorMsg)) {
SetMemoryError(ErrorCode::PARAMS_ERROR);
SendResponse(std::move(responsePtr), false);
return false;
}
double start = NumberUtil::StringToDouble(request.params.start);
double end = NumberUtil::StringToDouble(request.params.end);
response.rankOffsetNs = Timeline::TraceTime::Instance().GetOffsetByFileIdUsingMinTimestamp(request.params.rankId);
if (MemoryParse::Instance().Exist(request.params.GetRequestKey())) {
CurveView curve = MemoryParse::Instance().ComputeCurve(start, end, request.params.GetRequestKey());
responsePtr->data.title = curve.title;
responsePtr->data.legends = curve.legends;
responsePtr->data.lines = curve.dataLines;
SendResponse(std::move(responsePtr), true);
return true;
}
bool success = QueryCurveData(response, errorMsg, request, responsePtr);
if (!success) {
return false;
}
CurveView curve;
curve.tempData = std::move(responsePtr->data.tempData);
curve.legends = responsePtr->data.legends;
curve.title = responsePtr->data.title;
MemoryParse::Instance().PutCurve(request.params.GetRequestKey(), curve);
curve = MemoryParse::Instance().ComputeCurve(0, 0, request.params.GetRequestKey());
responsePtr->data.lines = curve.dataLines;
SendResponse(std::move(responsePtr), true);
return true;
}
bool QueryMemoryViewHandler::QueryCurveData(MemoryViewResponse &response, std::string &errorMsg,
MemoryViewRequest &request, std::unique_ptr<MemoryViewResponse> &responsePtr) {
auto database = Timeline::DataBaseManager::Instance().GetMemoryDatabaseByRankId(request.params.rankId);
if (!database) {
SetMemoryError(ErrorCode::CONNECT_DATABASE_FAILED);
SendResponse(std::move(responsePtr), false);
return false;
}
std::string deviceId = Timeline::DataBaseManager::Instance().GetDeviceIdFromRankId(request.params.rankId);
if (deviceId.empty()) {
SetMemoryError(ErrorCode::GET_DEVICE_ID_FAILED);
SendResponse(std::move(responsePtr), false);
return false;
}
request.params.deviceId = deviceId;
if (!request.params.isCompare) {
uint64_t offsetTime = Timeline::TraceTime::Instance().GetOffsetByFileIdUsingMinTimestamp(request.params.rankId);
if (!database || !database->QueryMemoryView(request.params, response.data, offsetTime)) {
SetMemoryError(ErrorCode::QUERY_MEMORY_VIEW_DATA_FAILED);
SendResponse(std::move(responsePtr), false);
return false;
}
} else {
MemoryViewData compareData;
MemoryViewData baselineData;
if (!GetRespectiveData(database, compareData, baselineData, request, errorMsg)) {
SendResponse(std::move(responsePtr), false);
return false;
}
ExecuteComparisonAlgorithm(compareData, baselineData, response);
}
return true;
}
bool QueryMemoryViewHandler::GetRespectiveData(std::shared_ptr<VirtualMemoryDataBase> database,
Dic::Protocol::MemoryViewData &compareData, Dic::Protocol::MemoryViewData &baselineData,
Dic::Protocol::MemoryViewRequest &request, std::string &errorMsg) {
std::string baselineId = Global::BaselineManager::Instance().GetBaselineId();
if (baselineId == "") {
errorMsg = "Failed to get baseline id.";
SetMemoryError(ErrorCode::GET_BASELINE_ID_FAILED);
return false;
}
auto databaseBaseline = Timeline::DataBaseManager::Instance().GetMemoryDatabaseByRankId(baselineId);
if (!databaseBaseline) {
errorMsg = "Failed to connect to database of baseline.";
SetMemoryError(ErrorCode::CONNECT_DATABASE_FAILED);
return false;
}
uint64_t offsetTimeCompare =
Timeline::TraceTime::Instance().GetOffsetByFileIdUsingMinTimestamp(request.params.rankId);
if (!database->QueryMemoryView(request.params, compareData, offsetTimeCompare)) {
errorMsg = "Failed to query memory view compare data.";
SetMemoryError(ErrorCode::QUERY_MEMORY_VIEW_DATA_COMPARE_FAILED);
return false;
}
request.params.deviceId = FullDb::DataBaseManager::Instance().GetDeviceIdFromRankId(baselineId);
uint64_t offsetTimeBaseline = Timeline::TraceTime::Instance().GetOffsetByFileIdUsingMinTimestamp(baselineId);
if (!databaseBaseline->QueryMemoryView(request.params, baselineData, offsetTimeBaseline)) {
errorMsg = "Failed to query memory view baseline data.";
SetMemoryError(ErrorCode::QUERY_MEMORY_VIEW_DATA_BASELINE_FAILED);
return false;
}
return true;
}
void QueryMemoryViewHandler::ExecuteComparisonAlgorithm(const Protocol::MemoryViewData &compareData,
const Protocol::MemoryViewData &baselineData, Protocol::MemoryViewResponse &response) {
GetCompareGraphLegends(compareData, baselineData, response.data);
GetCompareGraphLines(compareData, baselineData, response.data);
}
void QueryMemoryViewHandler::GetCompareGraphLegends(const Protocol::MemoryViewData &compareData,
const Protocol::MemoryViewData &baselineData, Protocol::MemoryViewData &resultData) {
resultData.title = "";
resultData.legends = compareData.legends;
for (size_t i = 1; i < compareData.legends.size(); ++i) {
resultData.legends[i] += " of Compare";
}
if (baselineData.legends.size() > 0) {
resultData.legends.insert(
resultData.legends.end(), baselineData.legends.begin() + 1, baselineData.legends.end());
}
for (size_t i = compareData.legends.size(); i < resultData.legends.size(); ++i) {
resultData.legends[i] += " of Baseline";
}
}
void QueryMemoryViewHandler::GetCompareGraphLines(const Protocol::MemoryViewData &compareData,
const Protocol::MemoryViewData &baselineData, Protocol::MemoryViewData &resultData) {
size_t indexCompare = 0;
size_t indexBaseline = 0;
uint64_t compareSize = compareData.legends.empty() ? 0 : compareData.tempData.size() / compareData.legends.size();
uint64_t baselineSize =
baselineData.legends.empty() ? 0 : baselineData.tempData.size() / baselineData.legends.size();
while ((indexCompare < compareSize) || (indexBaseline < baselineSize)) {
if (indexBaseline >= baselineSize ||
(indexCompare < compareSize &&
compareData.tempData[indexCompare * compareData.legends.size()] <
baselineData.tempData[indexBaseline * baselineData.legends.size()])) {
for (size_t i = 0; i < compareData.legends.size(); ++i) {
resultData.tempData.emplace_back(compareData.tempData[indexCompare * compareData.legends.size() + i]);
}
if (!baselineData.legends.empty()) {
resultData.tempData.insert(resultData.tempData.end(), baselineData.legends.size() - 1,
std::numeric_limits<double>::quiet_NaN());
}
++indexCompare;
continue;
}
if (indexCompare >= compareSize ||
(indexBaseline < baselineSize &&
compareData.tempData[indexCompare * compareData.legends.size()] >
baselineData.tempData[indexBaseline * baselineData.legends.size()])) {
resultData.tempData.emplace_back(baselineData.tempData[indexBaseline * baselineData.legends.size()]);
if (!compareData.legends.empty()) {
resultData.tempData.insert(resultData.tempData.end(), compareData.legends.size() - 1,
std::numeric_limits<double>::quiet_NaN());
}
if ((indexBaseline + 1) * baselineData.legends.size() <= baselineData.tempData.size()) {
AddBaseLineData(baselineData, resultData, indexBaseline);
}
++indexBaseline;
continue;
}
for (size_t i = 0; i < compareData.legends.size(); ++i) {
resultData.tempData.emplace_back(compareData.tempData[indexCompare * compareData.legends.size() + i]);
}
if (!baselineData.legends.empty()) {
AddBaseLineData(baselineData, resultData, indexBaseline);
}
++indexCompare;
++indexBaseline;
}
}
void QueryMemoryViewHandler::AddBaseLineData(
const MemoryViewData &baselineData, MemoryViewData &resultData, size_t indexBaseline) const {
for (size_t i = 1; i < baselineData.legends.size(); ++i) {
resultData.tempData.emplace_back(baselineData.tempData[indexBaseline * baselineData.legends.size() + i]);
}
}
}
}
}