• 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 #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