* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2026 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 "TextTraceDatabase.h"
namespace Dic::Module::Timeline {
using namespace Dic::Server;
using namespace Dic::Protocol;
bool TextTraceDatabase::CreateFtraceTable() {
if (!isOpen) {
ServerLog::Error("Failed to create ftrace table. Database is not open.");
return false;
}
std::string sql = R"(
CREATE TABLE IF NOT EXISTS ftrace_analysis (
track_id INTEGER NOT NULL,
data_type INTEGER NOT NULL,
args TEXT,
PRIMARY KEY (track_id, data_type)
);
)";
std::unique_lock<std::recursive_mutex> lock(mutex);
return ExecSql(sql);
}
bool TextTraceDatabase::InsertFtraceStat(const FtraceStatisticsData &event) {
ftraceStatCache.emplace_back(event);
if (ftraceStatCache.size() == CACHE_SIZE) {
InsertFtraceStatList(ftraceStatCache);
ftraceStatCache.clear();
}
return true;
}
std::unique_ptr<SqlitePreparedStatement> TextTraceDatabase::GetFtraceStmt(uint64_t paramLen) {
std::string valuePlaceholders;
for (uint64_t i = 0; i < paramLen; ++i) {
if (i > 0) {
valuePlaceholders += ", ";
}
valuePlaceholders += "(?, ?, ?)";
}
std::string sql = "INSERT INTO ftrace_analysis (track_id, data_type, args) VALUES " + valuePlaceholders;
return CreatPreparedStatement(sql);
}
bool TextTraceDatabase::InsertFtraceStatList(const std::vector<FtraceStatisticsData> &dataList) {
std::unique_ptr<SqlitePreparedStatement> stmt = nullptr;
std::unique_ptr<SqlitePreparedStatement> &refStmt = dataList.size() == CACHE_SIZE ? insertFtraceStatStmt : stmt;
if (refStmt == nullptr) {
refStmt = GetFtraceStmt(dataList.size());
} else {
refStmt->Reset();
}
int bindIndex = bindStartIndex;
for (const auto &data : dataList) {
sqlite3_bind_int64(refStmt->stmt, bindIndex++, static_cast<int64_t>(data.trackId));
sqlite3_bind_int64(refStmt->stmt, bindIndex++, static_cast<int8_t>(data.dataType));
sqlite3_bind_text(refStmt->stmt, bindIndex++, data.GetArgs().c_str(), -1, SQLITE_TRANSIENT);
}
std::unique_lock<std::recursive_mutex> lock(mutex);
if (!refStmt->Execute()) {
ServerLog::Error("Insert ftrace stat data fail. ", refStmt->GetErrorMessage());
return false;
}
return true;
}
FtraceStatistics TextTraceDatabase::QueryFtraceStatistics(FtraceDataType dataType, uint64_t offset, uint64_t limit) {
FtraceStatistics result;
if (!isOpen) {
ServerLog::Error("Failed to query ftrace statistics. Database is not open.");
return result;
}
std::unique_lock<std::recursive_mutex> lock(mutex);
std::string sql = "SELECT track_id, data_type, args, COUNT(*) OVER () AS total_count FROM "
"ftrace_analysis WHERE data_type = ? LIMIT ? OFFSET ?";
sqlite3_stmt *stmt = nullptr;
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
ServerLog::Error("Failed to prepare statement: ", sqlite3_errmsg(db));
return result;
}
int bindIndex = bindStartIndex;
sqlite3_bind_int64(stmt, bindIndex++, static_cast<int64_t>(dataType));
sqlite3_bind_int64(stmt, bindIndex++, static_cast<int64_t>(limit));
sqlite3_bind_int64(stmt, bindIndex++, static_cast<int64_t>(offset));
while (sqlite3_step(stmt) == SQLITE_ROW) {
FtraceStatisticsData data;
data.trackId = sqlite3_column_int64(stmt, 0);
data.dataType = static_cast<FtraceDataType>(sqlite3_column_int(stmt, 1));
std::string argsStr = sqlite3_column_string(stmt, 2);
if (!argsStr.empty()) {
data.SetArgs(argsStr);
}
result.totalCount = sqlite3_column_int64(stmt, 3);
result.data.push_back(data);
}
sqlite3_finalize(stmt);
return result;
}
}