• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sys_event_sequence_mgr.h"
17 
18 #include <fstream>
19 
20 #include "event_db_file_util.h"
21 #include "file_util.h"
22 #include "hisysevent.h"
23 #include "hiview_logger.h"
24 #include "parameter_ex.h"
25 #include "running_status_logger.h"
26 #include "sys_event_dao.h"
27 #include "sys_event_doc_reader.h"
28 #include "time_util.h"
29 
30 namespace OHOS {
31 namespace HiviewDFX {
32 namespace EventStore {
33 namespace {
34 DEFINE_LOG_TAG("HiView-SysEventSeqMgr");
35 constexpr int64_t SEQ_INCREMENT = 100; // increment of seq each time it is read from the file
36 static constexpr char READ_UNEXPECTED_SEQ[] = "READ_UNEXPECTED_SEQ";
37 
SaveStringToFile(const std::string & filePath,const std::string & content)38 bool SaveStringToFile(const std::string& filePath, const std::string& content)
39 {
40     std::ofstream file;
41     file.open(filePath.c_str(), std::ios::in | std::ios::out);
42     if (!file.is_open()) {
43         file.open(filePath.c_str(), std::ios::out);
44         if (!file.is_open()) {
45             return false;
46         }
47     }
48     file.seekp(0);
49     file.write(content.c_str(), content.length() + 1);
50     bool ret = !file.fail();
51     file.close();
52     return ret;
53 }
54 
GetSequenceBackupFile()55 inline std::string GetSequenceBackupFile()
56 {
57     return EventStore::SysEventDao::GetDatabaseDir() + SEQ_PERSISTS_BACKUP_FILE_NAME;
58 }
59 
WriteEventSeqToFile(int64_t seq,const std::string & file)60 void WriteEventSeqToFile(int64_t seq, const std::string& file)
61 {
62     std::string content(std::to_string(seq));
63     if (!SaveStringToFile(file, content)) {
64         HIVIEW_LOGE("failed to write sequence %{public}s to %{public}s", content.c_str(), file.c_str());
65     }
66 }
67 
ReadEventSeqFromFile(int64_t & seq,const std::string & file)68 inline void ReadEventSeqFromFile(int64_t& seq, const std::string& file)
69 {
70     std::string content;
71     if (!FileUtil::LoadStringFromFile(file, content)) {
72         HIVIEW_LOGE("failed to read sequence value from %{public}s", file.c_str());
73     }
74     seq = static_cast<int64_t>(strtoll(content.c_str(), nullptr, 0));
75 }
76 
LogEventSeqReadException(int64_t seq,int64_t backupSeq)77 void LogEventSeqReadException(int64_t seq, int64_t backupSeq)
78 {
79     std::string info { "read seq failed; time=[" };
80     info.append(std::to_string(TimeUtil::GetMilliseconds())).append("]; ");
81     info.append("seq=[").append(std::to_string(seq)).append("]; ");
82     info.append("backup_seq=[").append(std::to_string(backupSeq)).append("]");
83     RunningStatusLogger::GetInstance().LogEventRunningLogInfo(info);
84 }
85 
WriteSeqReadExcpetionEvent(bool isSeqFileExist,int64_t seq,bool isSeqBackupFileExist,int64_t seqBackup,int64_t maxSeqReadFromFile=0)86 void WriteSeqReadExcpetionEvent(bool isSeqFileExist, int64_t seq, bool isSeqBackupFileExist, int64_t seqBackup,
87     int64_t maxSeqReadFromFile = 0)
88 {
89     int ret = HiSysEventWrite(HiSysEvent::Domain::HIVIEWDFX, READ_UNEXPECTED_SEQ, HiSysEvent::EventType::FAULT,
90         "IS_SEQ_FILE_EXIST", isSeqFileExist, "SEQ", seq,
91         "IS_SEQ_BACKUP_FILE_EXIST", isSeqBackupFileExist, "SEQ_BACKUP", seqBackup,
92         "MAX_SEQ_FROM_DB_FILE", maxSeqReadFromFile);
93     if (ret < 0) {
94         HIVIEW_LOGI("failed to write seq read event, ret is %{public}d", ret);
95     }
96 }
97 
CheckFileExistThenReadSeq(const std::string & filePath,bool & isFileExist,int64_t & seq)98 void CheckFileExistThenReadSeq(const std::string& filePath, bool& isFileExist, int64_t& seq)
99 {
100     isFileExist = FileUtil::FileExists(filePath);
101     if (!isFileExist) {
102         HIVIEW_LOGI("%{public}s is not exist", filePath.c_str());
103         return;
104     }
105     ReadEventSeqFromFile(seq, filePath);
106 }
107 
UpdateFileInfos(std::map<std::string,std::pair<int64_t,std::string>> & dbFileInfos,const std::string & eventFile,const std::string & eventName,int64_t eventSeq)108 void UpdateFileInfos(std::map<std::string, std::pair<int64_t, std::string>>& dbFileInfos,
109     const std::string& eventFile, const std::string& eventName, int64_t eventSeq)
110 {
111     auto findRet = dbFileInfos.find(eventName);
112     if (findRet == dbFileInfos.end()) {
113         dbFileInfos.emplace(eventName, std::make_pair(eventSeq, eventFile));
114         return;
115     }
116     auto& seqInfo = findRet->second;
117     if (seqInfo.first > eventSeq) {
118         return;
119     }
120     seqInfo.first = eventSeq;
121     seqInfo.second = eventFile;
122 }
123 
GetEventMaxSeqFileWithSameDomain(const std::string & domainDir,std::vector<std::string> & eventDbFiles)124 void GetEventMaxSeqFileWithSameDomain(const std::string& domainDir, std::vector<std::string>& eventDbFiles)
125 {
126     std::vector<std::string> eventFiles;
127     FileUtil::GetDirFiles(domainDir, eventFiles);
128     if (eventFiles.empty()) {
129         HIVIEW_LOGW("no event db file has been found in %{public}s", domainDir.c_str());
130         return;
131     }
132     std::map<std::string, std::pair<int64_t, std::string>> dbFileInfos;
133     for (const auto& eventFile : eventFiles) {
134         if (!EventDbFileUtil::IsValidDbFilePath(eventFile)) {
135             HIVIEW_LOGW("not valid event db file, path=%{public}s", eventFile.c_str());
136             continue;
137         }
138         SplitedEventInfo eventInfo;
139         std::string fileName = FileUtil::ExtractFileName(eventFile);
140         if (!EventDbFileUtil::ParseEventInfoFromDbFileName(fileName, eventInfo, NAME_ONLY | SEQ_ONLY)) {
141             HIVIEW_LOGW("failed to parse event info from: %{public}s", eventFile.c_str());
142             continue;
143         }
144         UpdateFileInfos(dbFileInfos, eventFile, eventInfo.name, eventInfo.seq);
145     }
146     // merge result
147     for (const auto& dbFileInfo : dbFileInfos) {
148         eventDbFiles.emplace_back(dbFileInfo.second.second);
149     }
150 }
151 
GetEventMaxSeqFileList(std::vector<std::string> & eventDbFiles)152 void GetEventMaxSeqFileList(std::vector<std::string>& eventDbFiles)
153 {
154     std::vector<std::string> domainDirs;
155     FileUtil::GetDirDirs(EventStore::SysEventDao::GetDatabaseDir(), domainDirs);
156     if (domainDirs.empty()) {
157         HIVIEW_LOGW("no domain directiry has been found");
158         return;
159     }
160     for (const auto& domainDir : domainDirs) {
161         if (!EventDbFileUtil::IsValidDbDir(domainDir)) {
162             HIVIEW_LOGW("not valid domain directory, path=%{public}s", domainDir.c_str());
163             continue;
164         }
165         GetEventMaxSeqFileWithSameDomain(domainDir, eventDbFiles);
166     }
167 }
168 
GetEventMaxSeqFromLocalDbFiles()169 int64_t GetEventMaxSeqFromLocalDbFiles()
170 {
171     int64_t seq = 0;
172     std::vector<std::string> eventDbFiles;
173     GetEventMaxSeqFileList(eventDbFiles);
174     for (const auto& eventDbFile : eventDbFiles) {
175         SysEventDocReader reader(eventDbFile);
176         int64_t curSeq = reader.ReadMaxEventSequence();
177         if (seq < curSeq) {
178             seq = curSeq;
179         }
180     }
181     return seq;
182 }
183 }
184 
GetInstance()185 SysEventSequenceManager& SysEventSequenceManager::GetInstance()
186 {
187     static SysEventSequenceManager instance;
188     return instance;
189 }
190 
SysEventSequenceManager()191 SysEventSequenceManager::SysEventSequenceManager()
192 {
193     if (!Parameter::IsOversea() && !FileUtil::FileExists(GetSequenceFile())) {
194         EventStore::SysEventDao::Restore();
195     }
196     int64_t seq = 0;
197     ReadSeqFromFile(seq);
198     startSeq_ = seq + SEQ_INCREMENT;
199     HIVIEW_LOGI("start seq=%{public}" PRId64, startSeq_);
200     WriteSeqToFile(startSeq_);
201     curSeq_.store(startSeq_, std::memory_order_release);
202 }
203 
SetSequence(int64_t seq)204 void SysEventSequenceManager::SetSequence(int64_t seq)
205 {
206     curSeq_.store(seq, std::memory_order_release);
207     static int64_t setCount = 0;
208     ++setCount;
209     if (setCount % SEQ_INCREMENT == 0) {
210         WriteSeqToFile(seq);
211     }
212 }
213 
GetSequence()214 int64_t SysEventSequenceManager::GetSequence()
215 {
216     return curSeq_.load(std::memory_order_acquire);
217 }
218 
GetStartSequence()219 int64_t SysEventSequenceManager::GetStartSequence()
220 {
221     return startSeq_;
222 }
223 
WriteSeqToFile(int64_t seq)224 void SysEventSequenceManager::WriteSeqToFile(int64_t seq)
225 {
226     WriteEventSeqToFile(seq, GetSequenceFile());
227     WriteEventSeqToFile(seq, GetSequenceBackupFile());
228 }
229 
ReadSeqFromFile(int64_t & seq)230 void SysEventSequenceManager::ReadSeqFromFile(int64_t& seq)
231 {
232     std::string seqFilePath = GetSequenceFile();
233     bool isSeqFileExist = false;
234     CheckFileExistThenReadSeq(seqFilePath, isSeqFileExist, seq);
235     std::string seqBackupFilePath = GetSequenceBackupFile();
236     bool isSeqBackupFileExist = false;
237     int64_t seqBackup = 0;
238     CheckFileExistThenReadSeq(seqBackupFilePath, isSeqBackupFileExist, seqBackup);
239     if (seq == seqBackup && (!isSeqFileExist || seq != 0)) {
240         HIVIEW_LOGI("succeed to read event sequence, value is %{public}" PRId64 "", seq);
241         return;
242     }
243     LogEventSeqReadException(seq, seqBackup);
244     HIVIEW_LOGW("seq[%{public}" PRId64 "] is different with backup seq[%{public}" PRId64 "]", seq, seqBackup);
245     if (seq == 0) {
246         int64_t seqReadFromLocalFile = GetEventMaxSeqFromLocalDbFiles();
247         WriteSeqReadExcpetionEvent(isSeqFileExist, seq, isSeqBackupFileExist, seqBackup, seqReadFromLocalFile);
248         seq = seqReadFromLocalFile;
249         HIVIEW_LOGI("adjust seq to %{public}" PRId64 "", seq);
250     } else {
251         WriteSeqReadExcpetionEvent(isSeqFileExist, seq, isSeqBackupFileExist, seqBackup);
252     }
253     if (seq > seqBackup) {
254         WriteEventSeqToFile(seq, seqBackupFilePath);
255     } else {
256         seq = seqBackup;
257         WriteEventSeqToFile(seq, seqFilePath);
258     }
259 }
260 
GetSequenceFile() const261 std::string SysEventSequenceManager::GetSequenceFile() const
262 {
263     return EventStore::SysEventDao::GetDatabaseDir() + SEQ_PERSISTS_FILE_NAME;
264 }
265 } // EventStore
266 } // HiviewDFX
267 } // OHOS