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 #ifdef ENABLE_DIRTY_EVENT_CLEAR
194 EventStore::SysEventDao::ClearDirtyEventFiles(); // must clear before restore and deal new events
195 #endif
196 if (!Parameter::IsOversea() && !FileUtil::FileExists(GetSequenceFile())) {
197 EventStore::SysEventDao::Restore();
198 }
199 int64_t seq = 0;
200 ReadSeqFromFile(seq);
201 startSeq_ = seq + SEQ_INCREMENT;
202 HIVIEW_LOGI("start seq=%{public}" PRId64, startSeq_);
203 WriteSeqToFile(startSeq_);
204 curSeq_.store(startSeq_, std::memory_order_release);
205 }
206
SetSequence(int64_t seq)207 void SysEventSequenceManager::SetSequence(int64_t seq)
208 {
209 curSeq_.store(seq, std::memory_order_release);
210 static int64_t setCount = 0;
211 ++setCount;
212 if (setCount % SEQ_INCREMENT == 0) {
213 WriteSeqToFile(seq);
214 }
215 }
216
GetSequence()217 int64_t SysEventSequenceManager::GetSequence()
218 {
219 return curSeq_.load(std::memory_order_acquire);
220 }
221
GetStartSequence()222 int64_t SysEventSequenceManager::GetStartSequence()
223 {
224 return startSeq_;
225 }
226
WriteSeqToFile(int64_t seq)227 void SysEventSequenceManager::WriteSeqToFile(int64_t seq)
228 {
229 WriteEventSeqToFile(seq, GetSequenceFile());
230 WriteEventSeqToFile(seq, GetSequenceBackupFile());
231 }
232
ReadSeqFromFile(int64_t & seq)233 void SysEventSequenceManager::ReadSeqFromFile(int64_t& seq)
234 {
235 std::string seqFilePath = GetSequenceFile();
236 bool isSeqFileExist = false;
237 CheckFileExistThenReadSeq(seqFilePath, isSeqFileExist, seq);
238 std::string seqBackupFilePath = GetSequenceBackupFile();
239 bool isSeqBackupFileExist = false;
240 int64_t seqBackup = 0;
241 CheckFileExistThenReadSeq(seqBackupFilePath, isSeqBackupFileExist, seqBackup);
242 if (seq == seqBackup && (!isSeqFileExist || seq != 0)) {
243 HIVIEW_LOGI("succeed to read event sequence, value is %{public}" PRId64 "", seq);
244 return;
245 }
246 LogEventSeqReadException(seq, seqBackup);
247 HIVIEW_LOGW("seq[%{public}" PRId64 "] is different with backup seq[%{public}" PRId64 "]", seq, seqBackup);
248 if (seq == 0) {
249 int64_t seqReadFromLocalFile = GetEventMaxSeqFromLocalDbFiles();
250 WriteSeqReadExcpetionEvent(isSeqFileExist, seq, isSeqBackupFileExist, seqBackup, seqReadFromLocalFile);
251 seq = seqReadFromLocalFile;
252 HIVIEW_LOGI("adjust seq to %{public}" PRId64 "", seq);
253 } else {
254 WriteSeqReadExcpetionEvent(isSeqFileExist, seq, isSeqBackupFileExist, seqBackup);
255 }
256 if (seq > seqBackup) {
257 WriteEventSeqToFile(seq, seqBackupFilePath);
258 } else {
259 seq = seqBackup;
260 WriteEventSeqToFile(seq, seqFilePath);
261 }
262 }
263
GetSequenceFile() const264 std::string SysEventSequenceManager::GetSequenceFile() const
265 {
266 return EventStore::SysEventDao::GetDatabaseDir() + SEQ_PERSISTS_FILE_NAME;
267 }
268 } // EventStore
269 } // HiviewDFX
270 } // OHOS