12498b56bSopenharmony_ci/* 22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 42498b56bSopenharmony_ci * you may not use this file except in compliance with the License. 52498b56bSopenharmony_ci * You may obtain a copy of the License at 62498b56bSopenharmony_ci * 72498b56bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 82498b56bSopenharmony_ci * 92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122498b56bSopenharmony_ci * See the License for the specific language governing permissions and 132498b56bSopenharmony_ci * limitations under the License. 142498b56bSopenharmony_ci */ 152498b56bSopenharmony_ci#include <cstdio> 162498b56bSopenharmony_ci#include <dirent.h> 172498b56bSopenharmony_ci#include <fstream> 182498b56bSopenharmony_ci#include <iostream> 192498b56bSopenharmony_ci#include <securec.h> 202498b56bSopenharmony_ci#include <sstream> 212498b56bSopenharmony_ci#include <sys/stat.h> 222498b56bSopenharmony_ci#include <sys/time.h> 232498b56bSopenharmony_ci#include <unistd.h> 242498b56bSopenharmony_ci 252498b56bSopenharmony_ci#include "log_persister_rotator.h" 262498b56bSopenharmony_ci 272498b56bSopenharmony_ciconstexpr uint8_t MAX_TIME_BUF_SIZE = 32; 282498b56bSopenharmony_ciconstexpr uint8_t MAX_LOG_INDEX_LEN = 4; 292498b56bSopenharmony_ci 302498b56bSopenharmony_cinamespace OHOS { 312498b56bSopenharmony_cinamespace HiviewDFX { 322498b56bSopenharmony_cistd::string GetFileNameIndex(const int index) 332498b56bSopenharmony_ci{ 342498b56bSopenharmony_ci char res[MAX_LOG_INDEX_LEN]; 352498b56bSopenharmony_ci (void)snprintf_s(res, sizeof(res), sizeof(res) - 1, "%03d", index % MAX_LOG_FILE_NUM); 362498b56bSopenharmony_ci std::string fileNameIndex(res); 372498b56bSopenharmony_ci return fileNameIndex; 382498b56bSopenharmony_ci} 392498b56bSopenharmony_ci 402498b56bSopenharmony_cibool LogPersisterRotator::IsOldFile(const std::string& logName, const int index) 412498b56bSopenharmony_ci{ 422498b56bSopenharmony_ci std::string fileNameHead = m_logsPath.substr(strlen(HILOG_FILE_DIR), m_logsPath.size()); 432498b56bSopenharmony_ci fileNameHead = fileNameHead + "." + GetFileNameIndex(index + 1 - m_maxLogFileNum); 442498b56bSopenharmony_ci if (logName.find(fileNameHead) == std::string::npos) { 452498b56bSopenharmony_ci return false; 462498b56bSopenharmony_ci } 472498b56bSopenharmony_ci return true; 482498b56bSopenharmony_ci} 492498b56bSopenharmony_ci 502498b56bSopenharmony_ci 512498b56bSopenharmony_ciLogPersisterRotator::LogPersisterRotator(const std::string& logsPath, uint32_t id, uint32_t maxFiles, 522498b56bSopenharmony_ci const std::string& fileNameSuffix) 532498b56bSopenharmony_ci : m_maxLogFileNum(maxFiles), m_logsPath(logsPath), m_fileNameSuffix(fileNameSuffix), m_id(id) 542498b56bSopenharmony_ci{ 552498b56bSopenharmony_ci} 562498b56bSopenharmony_ci 572498b56bSopenharmony_ciLogPersisterRotator::~LogPersisterRotator() 582498b56bSopenharmony_ci{ 592498b56bSopenharmony_ci m_infoFile.close(); 602498b56bSopenharmony_ci remove(m_infoFilePath.c_str()); 612498b56bSopenharmony_ci} 622498b56bSopenharmony_ci 632498b56bSopenharmony_ciint LogPersisterRotator::Init(const PersistRecoveryInfo& info, bool restore) 642498b56bSopenharmony_ci{ 652498b56bSopenharmony_ci if (!m_infoFile.is_open()) { 662498b56bSopenharmony_ci if (int result = OpenInfoFile(); result != RET_SUCCESS) { 672498b56bSopenharmony_ci return result; 682498b56bSopenharmony_ci } 692498b56bSopenharmony_ci } 702498b56bSopenharmony_ci 712498b56bSopenharmony_ci m_info = info; 722498b56bSopenharmony_ci SetFileIndex(m_info.index, restore); 732498b56bSopenharmony_ci UpdateRotateNumber(); 742498b56bSopenharmony_ci return RET_SUCCESS; 752498b56bSopenharmony_ci} 762498b56bSopenharmony_ci 772498b56bSopenharmony_ciint LogPersisterRotator::OpenInfoFile() 782498b56bSopenharmony_ci{ 792498b56bSopenharmony_ci auto lastSeparatorIdx = m_logsPath.find_last_of('/'); 802498b56bSopenharmony_ci std::string parentDirPath = m_logsPath.substr(0, lastSeparatorIdx); 812498b56bSopenharmony_ci if (access(parentDirPath.c_str(), F_OK) != 0) { 822498b56bSopenharmony_ci if (errno == ENOENT) { 832498b56bSopenharmony_ci mkdir(parentDirPath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO); 842498b56bSopenharmony_ci } 852498b56bSopenharmony_ci } 862498b56bSopenharmony_ci std::string infoFileName = std::string(".") + AUXILLARY_PERSISTER_PREFIX + std::to_string(m_id) + ".info"; 872498b56bSopenharmony_ci m_infoFilePath = parentDirPath + "/" + infoFileName; 882498b56bSopenharmony_ci m_infoFile.open(m_infoFilePath, std::ios::binary | std::ios::out | std::ios::trunc); 892498b56bSopenharmony_ci return m_infoFile.is_open() ? RET_SUCCESS : RET_FAIL; 902498b56bSopenharmony_ci} 912498b56bSopenharmony_ci 922498b56bSopenharmony_ciint LogPersisterRotator::Input(const char *buf, uint32_t length) 932498b56bSopenharmony_ci{ 942498b56bSopenharmony_ci if (length <= 0 || buf == nullptr) { 952498b56bSopenharmony_ci return ERR_LOG_PERSIST_COMPRESS_BUFFER_EXP; 962498b56bSopenharmony_ci } 972498b56bSopenharmony_ci if (m_needRotate) { 982498b56bSopenharmony_ci Rotate(); 992498b56bSopenharmony_ci m_needRotate = false; 1002498b56bSopenharmony_ci } else if ((access(m_currentLogFileName.c_str(), F_OK) != 0) || !m_currentLogOutput.is_open()) { 1012498b56bSopenharmony_ci CreateLogFile(); 1022498b56bSopenharmony_ci } 1032498b56bSopenharmony_ci m_currentLogOutput.write(buf, length); 1042498b56bSopenharmony_ci m_currentLogOutput.flush(); 1052498b56bSopenharmony_ci return 0; 1062498b56bSopenharmony_ci} 1072498b56bSopenharmony_ci 1082498b56bSopenharmony_civoid LogPersisterRotator::RemoveOldFile() 1092498b56bSopenharmony_ci{ 1102498b56bSopenharmony_ci DIR *dir = nullptr; 1112498b56bSopenharmony_ci struct dirent *ent = nullptr; 1122498b56bSopenharmony_ci if ((dir = opendir(HILOG_FILE_DIR)) != nullptr) { 1132498b56bSopenharmony_ci while ((ent = readdir(dir)) != nullptr) { 1142498b56bSopenharmony_ci size_t length = strlen(ent->d_name); 1152498b56bSopenharmony_ci std::string pPath(ent->d_name, length); 1162498b56bSopenharmony_ci if (IsOldFile(pPath, m_currentLogFileIdx)) { 1172498b56bSopenharmony_ci remove((HILOG_FILE_DIR + pPath).c_str()); 1182498b56bSopenharmony_ci break; 1192498b56bSopenharmony_ci } 1202498b56bSopenharmony_ci } 1212498b56bSopenharmony_ci } 1222498b56bSopenharmony_ci if (dir != nullptr) { 1232498b56bSopenharmony_ci closedir(dir); 1242498b56bSopenharmony_ci } 1252498b56bSopenharmony_ci} 1262498b56bSopenharmony_ci 1272498b56bSopenharmony_civoid LogPersisterRotator::Rotate() 1282498b56bSopenharmony_ci{ 1292498b56bSopenharmony_ci std::cout << __PRETTY_FUNCTION__ << "\n"; 1302498b56bSopenharmony_ci if (m_currentLogFileIdx + 1 >= m_maxLogFileNum) { 1312498b56bSopenharmony_ci RemoveOldFile(); 1322498b56bSopenharmony_ci } 1332498b56bSopenharmony_ci m_currentLogFileIdx++; 1342498b56bSopenharmony_ci CreateLogFile(); 1352498b56bSopenharmony_ci UpdateRotateNumber(); 1362498b56bSopenharmony_ci} 1372498b56bSopenharmony_ci 1382498b56bSopenharmony_civoid LogPersisterRotator::CreateLogFile() 1392498b56bSopenharmony_ci{ 1402498b56bSopenharmony_ci std::cout << __PRETTY_FUNCTION__ << "\n"; 1412498b56bSopenharmony_ci time_t tnow = time(nullptr); 1422498b56bSopenharmony_ci struct tm *tmNow = localtime(&tnow); 1432498b56bSopenharmony_ci char timeBuf[MAX_TIME_BUF_SIZE] = {0}; 1442498b56bSopenharmony_ci if (tmNow != nullptr) { 1452498b56bSopenharmony_ci strftime(timeBuf, sizeof(timeBuf), "%Y%m%d-%H%M%S", tmNow); 1462498b56bSopenharmony_ci } 1472498b56bSopenharmony_ci std::stringstream newFile; 1482498b56bSopenharmony_ci newFile << m_logsPath << "." << GetFileNameIndex(m_currentLogFileIdx) << "." << timeBuf << m_fileNameSuffix; 1492498b56bSopenharmony_ci std::cout << "Filename: " << newFile.str() << std::endl; 1502498b56bSopenharmony_ci m_currentLogFileName = newFile.str(); 1512498b56bSopenharmony_ci if (m_currentLogOutput.is_open()) { 1522498b56bSopenharmony_ci m_currentLogOutput.close(); 1532498b56bSopenharmony_ci } 1542498b56bSopenharmony_ci m_currentLogOutput.open(newFile.str(), std::ios::out | std::ios::trunc); 1552498b56bSopenharmony_ci} 1562498b56bSopenharmony_ci 1572498b56bSopenharmony_civoid LogPersisterRotator::UpdateRotateNumber() 1582498b56bSopenharmony_ci{ 1592498b56bSopenharmony_ci m_info.index = static_cast<uint32_t>(m_currentLogFileIdx); 1602498b56bSopenharmony_ci WriteRecoveryInfo(); 1612498b56bSopenharmony_ci} 1622498b56bSopenharmony_ci 1632498b56bSopenharmony_civoid LogPersisterRotator::FinishInput() 1642498b56bSopenharmony_ci{ 1652498b56bSopenharmony_ci std::cout << __PRETTY_FUNCTION__ << "\n"; 1662498b56bSopenharmony_ci 1672498b56bSopenharmony_ci m_currentLogOutput.close(); 1682498b56bSopenharmony_ci m_needRotate = true; 1692498b56bSopenharmony_ci} 1702498b56bSopenharmony_ci 1712498b56bSopenharmony_civoid LogPersisterRotator::SetFileIndex(uint32_t index, bool forceRotate) 1722498b56bSopenharmony_ci{ 1732498b56bSopenharmony_ci m_currentLogOutput.close(); 1742498b56bSopenharmony_ci m_currentLogFileIdx = index; 1752498b56bSopenharmony_ci if (forceRotate) { 1762498b56bSopenharmony_ci m_needRotate = true; 1772498b56bSopenharmony_ci } 1782498b56bSopenharmony_ci} 1792498b56bSopenharmony_ci 1802498b56bSopenharmony_civoid LogPersisterRotator::WriteRecoveryInfo() 1812498b56bSopenharmony_ci{ 1822498b56bSopenharmony_ci if (!m_infoFile.is_open()) { 1832498b56bSopenharmony_ci std::cerr << "LogPersisterRotator has not been initialized!\n"; 1842498b56bSopenharmony_ci return; 1852498b56bSopenharmony_ci } 1862498b56bSopenharmony_ci 1872498b56bSopenharmony_ci std::cout << "Save Info file!\n"; 1882498b56bSopenharmony_ci uint64_t hash = GenerateHash(reinterpret_cast<char *>(&m_info), sizeof(PersistRecoveryInfo)); 1892498b56bSopenharmony_ci 1902498b56bSopenharmony_ci m_infoFile.seekp(0); 1912498b56bSopenharmony_ci m_infoFile.write(reinterpret_cast<const char*>(&m_info), sizeof(m_info)); 1922498b56bSopenharmony_ci m_infoFile.write(reinterpret_cast<const char*>(&hash), sizeof(hash)); 1932498b56bSopenharmony_ci m_infoFile.flush(); 1942498b56bSopenharmony_ci m_infoFile.sync(); 1952498b56bSopenharmony_ci} 1962498b56bSopenharmony_ci} // namespace HiviewDFX 1972498b56bSopenharmony_ci} // namespace OHOS 198