• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_repeat_db.h"
17 
18 #include "hiview_logger.h"
19 #include "rdb_helper.h"
20 #include "sql_util.h"
21 #include "sys_event_database.h"
22 
23 namespace OHOS {
24 namespace HiviewDFX {
25 DEFINE_LOG_TAG("HiView-SysEvent-Repeat-Db");
26 namespace {
27     inline constexpr char DB_FILE_NAME[] = "sys_event_history.db";
28     inline constexpr char TABLE_NAME[] = "sys_event_history";
29     constexpr int32_t DB_VERSION = 1;
30 
31     inline constexpr char COLUMN_DOMAIN[] = "domain";
32     inline constexpr char COLUMN_NAME[] = "name";
33     inline constexpr char COLUMN_EVENT_HASH[] = "eventHash";
34     inline constexpr char COLUMN_HAPPENTIME[] = "happentime";
35     constexpr int32_t MAX_DB_COUNT = 10000;
36 
37 class SysEventRepeatDbCallback : public NativeRdb::RdbOpenCallback {
38 public:
39     int OnCreate(NativeRdb::RdbStore &rdbStore) override;
40     int OnUpgrade(NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override;
41 };
42 
OnCreate(NativeRdb::RdbStore & rdbStore)43 int SysEventRepeatDbCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
44 {
45     /**
46      * table: sys_event_history
47      *
48      * describe: store data that app task
49      * |---------|------|-----------|------------|
50      * |  domain | name | eventHash | happentime |
51      * |---------|------|-----------|------------|
52      * |  TEXT   | TEXT |   TEXT    |    INT64   |
53      * |---------|------|-----------|------------|
54      */
55     const std::vector<std::pair<std::string, std::string>> fields = {
56         {COLUMN_DOMAIN, SqlUtil::COLUMN_TYPE_STR},
57         {COLUMN_NAME, SqlUtil::COLUMN_TYPE_STR},
58         {COLUMN_EVENT_HASH, SqlUtil::COLUMN_TYPE_STR},
59         {COLUMN_HAPPENTIME, SqlUtil::COLUMN_TYPE_INT},
60     };
61     std::string sql = SqlUtil::GenerateCreateSql(TABLE_NAME, fields);
62     if (int32_t ret = rdbStore.ExecuteSql(sql); ret != NativeRdb::E_OK) {
63         HIVIEW_LOGE("failed to create table, sql=%{public}s", sql.c_str());
64         return ret;
65     }
66 
67     std::string indexSql = "create index sys_event_his_index1 on ";
68     indexSql.append(TABLE_NAME).append("(").append(COLUMN_DOMAIN).append(", ")
69         .append(COLUMN_NAME).append(",").append(COLUMN_EVENT_HASH).append(");");
70     if (int32_t ret = rdbStore.ExecuteSql(indexSql); ret != NativeRdb::E_OK) {
71         HIVIEW_LOGE("failed to create index1, sql=%{public}s", indexSql.c_str());
72         return ret;
73     }
74 
75     std::string indexHappentimeSql = "create index sys_event_his_index2 on ";
76     indexHappentimeSql.append(TABLE_NAME).append("(").append(COLUMN_HAPPENTIME).append(");");
77     if (int32_t ret = rdbStore.ExecuteSql(indexHappentimeSql); ret != NativeRdb::E_OK) {
78         HIVIEW_LOGE("failed to create index2, sql=%{public}s", indexHappentimeSql.c_str());
79         return ret;
80     }
81     return NativeRdb::E_OK;
82 }
83 
OnUpgrade(NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)84 int SysEventRepeatDbCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion)
85 {
86     HIVIEW_LOGI("oldVersion=%{public}d, newVersion=%{public}d", oldVersion, newVersion);
87     return NativeRdb::E_OK;
88 }
89 }
90 
SysEventRepeatDb()91 SysEventRepeatDb::SysEventRepeatDb()
92 {
93     InitDbStore();
94     RefreshDbCount();
95 }
96 
CheckAndRepairDbFile(const int32_t errCode)97 void SysEventRepeatDb::CheckAndRepairDbFile(const int32_t errCode)
98 {
99     if (errCode != NativeRdb::E_SQLITE_CORRUPT) {
100         return;
101     }
102 
103     HIVIEW_LOGE("db damaged.");
104     dbStore_ = nullptr;
105     auto dbFullName = EventStore::SysEventDatabase::GetInstance().GetDatabaseDir() + DB_FILE_NAME;
106     if (NativeRdb::RdbHelper::DeleteRdbStore(dbFullName) != NativeRdb::E_OK) {
107         HIVIEW_LOGE("delete db failed.");
108         return;
109     }
110 }
111 
CheckDbStoreValid()112 bool SysEventRepeatDb::CheckDbStoreValid()
113 {
114     if (dbStore_ != nullptr) {
115         return true;
116     }
117     InitDbStore();
118     RefreshDbCount();
119     return dbStore_ != nullptr;
120 }
121 
InitDbStore()122 void SysEventRepeatDb::InitDbStore()
123 {
124     auto dbFullName = EventStore::SysEventDatabase::GetInstance().GetDatabaseDir() + DB_FILE_NAME;
125     NativeRdb::RdbStoreConfig config(dbFullName);
126     config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
127     SysEventRepeatDbCallback callback;
128     auto ret = NativeRdb::E_OK;
129     dbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, DB_VERSION, callback, ret);
130     if (dbStore_ == nullptr) {
131         HIVIEW_LOGE("failed to init db store, db store path=%{public}s", dbFullName.c_str());
132         CheckAndRepairDbFile(ret);
133         return;
134     }
135 }
136 
Release()137 void SysEventRepeatDb::Release()
138 {
139     std::lock_guard<std::mutex> lock(dbMutex_);
140     dbStore_ = nullptr;
141 }
142 
CheckAndClearDb(const int64_t happentime)143 void SysEventRepeatDb::CheckAndClearDb(const int64_t happentime)
144 {
145     std::lock_guard<std::mutex> lock(dbMutex_);
146     if (dbCount_ <= MAX_DB_COUNT) {
147         return;
148     }
149     ClearHistory(happentime);
150     RefreshDbCount();
151 }
152 
Clear(const int64_t happentime)153 void SysEventRepeatDb::Clear(const int64_t happentime)
154 {
155     std::lock_guard<std::mutex> lock(dbMutex_);
156     ClearHistory(happentime);
157     RefreshDbCount();
158 }
159 
Insert(const SysEventHashRecord & sysEventHashRecord)160 bool SysEventRepeatDb::Insert(const SysEventHashRecord &sysEventHashRecord)
161 {
162     std::lock_guard<std::mutex> lock(dbMutex_);
163     if (!CheckDbStoreValid()) {
164         HIVIEW_LOGE("dbStore_ not valid.");
165         return false;
166     }
167     NativeRdb::ValuesBucket bucket;
168     bucket.PutString(COLUMN_DOMAIN, sysEventHashRecord.domain);
169     bucket.PutString(COLUMN_NAME, sysEventHashRecord.name);
170     bucket.PutString(COLUMN_EVENT_HASH, sysEventHashRecord.eventHash);
171     bucket.PutLong(COLUMN_HAPPENTIME, sysEventHashRecord.happentime);
172     int64_t seq = 0;
173     if (int32_t ret = dbStore_->Insert(seq, TABLE_NAME, bucket); ret != NativeRdb::E_OK) {
174         HIVIEW_LOGE("failed to insert app event task, ret=%{public}d", ret);
175         CheckAndRepairDbFile(ret);
176         return false;
177     }
178     ++dbCount_;
179     return true;
180 }
181 
Update(const SysEventHashRecord & sysEventHashRecord)182 bool SysEventRepeatDb::Update(const SysEventHashRecord &sysEventHashRecord)
183 {
184     std::lock_guard<std::mutex> lock(dbMutex_);
185     if (!CheckDbStoreValid()) {
186         return false;
187     }
188     NativeRdb::AbsRdbPredicates predicates(TABLE_NAME);
189     predicates.EqualTo(COLUMN_DOMAIN, sysEventHashRecord.domain);
190     predicates.EqualTo(COLUMN_NAME, sysEventHashRecord.name);
191     predicates.EqualTo(COLUMN_EVENT_HASH, sysEventHashRecord.eventHash);
192     NativeRdb::ValuesBucket bucket;
193     bucket.PutLong(COLUMN_HAPPENTIME, sysEventHashRecord.happentime);
194     int updateRowNum = 0;
195     if (int32_t ret = dbStore_->Update(updateRowNum, bucket, predicates); ret != NativeRdb::E_OK) {
196         HIVIEW_LOGE("failed to update table.");
197         CheckAndRepairDbFile(ret);
198         return false;
199     }
200     return true;
201 }
202 
ClearHistory(const int64_t happentime)203 void SysEventRepeatDb::ClearHistory(const int64_t happentime)
204 {
205     if (!CheckDbStoreValid()) {
206         return;
207     }
208     std::string whereClause = COLUMN_HAPPENTIME;
209         whereClause.append(" < ").append(std::to_string(happentime));
210     int deleteRows = 0;
211     if (int32_t ret = dbStore_->Delete(deleteRows, TABLE_NAME, whereClause); ret != NativeRdb::E_OK) {
212         HIVIEW_LOGE("failed to delete, whereClause=%{public}s", whereClause.c_str());
213         CheckAndRepairDbFile(ret);
214         return;
215     }
216 }
217 
RefreshDbCount()218 void SysEventRepeatDb::RefreshDbCount()
219 {
220     if (dbStore_ == nullptr) {
221         return;
222     }
223     std::string sql;
224     sql.append("SELECT count(*) from ").append(TABLE_NAME).append(";");
225     std::shared_ptr<NativeRdb::ResultSet> resultSet = dbStore_->QuerySql(sql, std::vector<std::string> {});
226     if (resultSet == nullptr) {
227         HIVIEW_LOGE("failed to query from table %{public}s, db is null", TABLE_NAME);
228         return;
229     }
230     if (int32_t ret = resultSet->GoToNextRow(); ret != NativeRdb::E_OK) {
231         resultSet->Close();
232         CheckAndRepairDbFile(ret);
233         return;
234     }
235 
236     resultSet->GetLong(0, dbCount_);
237     resultSet->Close();
238 }
239 
QueryHappentime(SysEventHashRecord & sysEventHashRecord)240 int64_t SysEventRepeatDb::QueryHappentime(SysEventHashRecord &sysEventHashRecord)
241 {
242     std::lock_guard<std::mutex> lock(dbMutex_);
243     if (!CheckDbStoreValid()) {
244         return 0;
245     }
246     NativeRdb::AbsRdbPredicates predicates(TABLE_NAME);
247     predicates.EqualTo(COLUMN_DOMAIN, sysEventHashRecord.domain);
248     predicates.EqualTo(COLUMN_NAME, sysEventHashRecord.name);
249     predicates.EqualTo(COLUMN_EVENT_HASH, sysEventHashRecord.eventHash);
250     auto resultSet = dbStore_->Query(predicates, {COLUMN_HAPPENTIME});
251     if (resultSet == nullptr) {
252         HIVIEW_LOGE("failed to query from table %{public}s, db is null", TABLE_NAME);
253         return 0;
254     }
255 
256     if (int32_t ret = resultSet->GoToNextRow(); ret != NativeRdb::E_OK) {
257         resultSet->Close();
258         CheckAndRepairDbFile(ret);
259         return 0;
260     }
261 
262     int64_t happentime = 0;
263     resultSet->GetLong(0, happentime);   // 0 is result of happentime
264     resultSet->Close();
265     return happentime;
266 }
267 
268 } // HiviewDFX
269 } // OHOS