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