1 /*
2 * Copyright (c) 2022-2023 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 #include "event_db_helper.h"
16
17 #include "file_util.h"
18 #include "json_parser.h"
19 #include "logger.h"
20 #include "plugin_stats_event_factory.h"
21 #include "rdb_helper.h"
22 #include "sql_util.h"
23 #include "sys_usage_event.h"
24 #include "usage_event_common.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28 DEFINE_LOG_TAG("HiView-EventDbHelper");
29 namespace {
30 const std::string DB_DIR = "sys_event_logger/";
31 const std::string DB_NAME = "event.db";
32 const std::string DB_COLUMIN_EVNET = "event";
33 const std::string DB_COLUMIN_PLUGIN = "plugin";
34 const std::string DB_TABLE_PLUGIN_STATS = "plugin_stats";
35 const char SQL_TEXT_TYPE[] = "TEXT NOT NULL";
36 constexpr int DB_VERSION = 1;
37 }
38
39 class EventDbStoreCallback : public NativeRdb::RdbOpenCallback {
40 public:
41 int OnCreate(NativeRdb::RdbStore &rdbStore) override;
42 int OnUpgrade(NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override;
43 };
44
OnCreate(NativeRdb::RdbStore & rdbStore)45 int EventDbStoreCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
46 {
47 HIVIEW_LOGD("create dbStore");
48 return NativeRdb::E_OK;
49 }
50
OnUpgrade(NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)51 int EventDbStoreCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion)
52 {
53 HIVIEW_LOGD("oldVersion=%{public}d, newVersion=%{public}d", oldVersion, newVersion);
54 return NativeRdb::E_OK;
55 }
56
EventDbHelper(const std::string workPath)57 EventDbHelper::EventDbHelper(const std::string workPath) : dbPath_(workPath), rdbStore_(nullptr)
58 {
59 InitDbStore();
60 }
61
~EventDbHelper()62 EventDbHelper::~EventDbHelper()
63 {}
64
InitDbStore()65 void EventDbHelper::InitDbStore()
66 {
67 std::string workPath = dbPath_;
68 if (workPath.back() != '/') {
69 dbPath_ += "/";
70 }
71 dbPath_ += DB_DIR;
72 if (!FileUtil::FileExists(dbPath_)) {
73 if (FileUtil::ForceCreateDirectory(dbPath_, FileUtil::FILE_PERM_770)) {
74 HIVIEW_LOGI("create sys_event_logger path successfully");
75 } else {
76 dbPath_ = workPath;
77 HIVIEW_LOGE("failed to create sys_event_logger path, use default path");
78 }
79 }
80 dbPath_ += DB_NAME;
81
82 NativeRdb::RdbStoreConfig config(dbPath_);
83 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
84 EventDbStoreCallback callback;
85 int ret = NativeRdb::E_OK;
86 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, DB_VERSION, callback, ret);
87 if (ret != NativeRdb::E_OK || rdbStore_ == nullptr) {
88 HIVIEW_LOGE("failed to create db store, ret=%{public}d", ret);
89 }
90 }
91
InsertPluginStatsEvent(std::shared_ptr<LoggerEvent> event)92 int EventDbHelper::InsertPluginStatsEvent(std::shared_ptr<LoggerEvent> event)
93 {
94 if (event == nullptr) {
95 HIVIEW_LOGI("event is null");
96 return -1;
97 }
98 if (rdbStore_ == nullptr) {
99 HIVIEW_LOGE("dbStore is null");
100 return -1;
101 }
102 std::vector<std::shared_ptr<LoggerEvent>> oldEvents;
103 std::string pluginName = event->GetValue(PluginStatsEventSpace::KEY_OF_PLUGIN_NAME).GetString();
104 return QueryPluginStatsEvent(oldEvents, pluginName) != 0 ?
105 InsertPluginStatsTable(pluginName, event->ToJsonString()) :
106 UpdatePluginStatsTable(pluginName, event->ToJsonString());
107 }
108
InsertSysUsageEvent(std::shared_ptr<LoggerEvent> event,const std::string & table)109 int EventDbHelper::InsertSysUsageEvent(std::shared_ptr<LoggerEvent> event, const std::string& table)
110 {
111 if (event == nullptr) {
112 HIVIEW_LOGI("event is null");
113 return -1;
114 }
115 if (rdbStore_ == nullptr) {
116 HIVIEW_LOGE("dbStore is null");
117 return -1;
118 }
119 std::shared_ptr<LoggerEvent> oldEvent = nullptr;
120 return QuerySysUsageEvent(oldEvent, table) != 0 ?
121 InsertSysUsageTable(table, event->ToJsonString()) :
122 UpdateSysUsageTable(table, event->ToJsonString());
123 }
124
QueryPluginStatsEvent(std::vector<std::shared_ptr<LoggerEvent>> & events,const std::string & pluginName)125 int EventDbHelper::QueryPluginStatsEvent(std::vector<std::shared_ptr<LoggerEvent>>& events,
126 const std::string& pluginName)
127 {
128 if (rdbStore_ == nullptr) {
129 HIVIEW_LOGE("dbStore is null");
130 return -1;
131 }
132
133 std::vector<std::string> eventStrs;
134 if (QueryPluginStatsTable(eventStrs, pluginName) != 0 || eventStrs.empty()) {
135 HIVIEW_LOGI("failed to query pluginStats table, pluginName=%{public}s", pluginName.c_str());
136 return -1;
137 }
138 auto factory = std::make_unique<PluginStatsEventFactory>();
139 for (auto eventStr : eventStrs) {
140 std::shared_ptr<LoggerEvent> event = factory->Create();
141 if (!JsonParser::ParsePluginStatsEvent(event, eventStr)) {
142 HIVIEW_LOGE("failed to parse the database records=%{public}s", eventStr.c_str());
143 continue;
144 }
145 events.push_back(event);
146 }
147 HIVIEW_LOGI("query plugin_stats events size=%{public}zu", events.size());
148 return 0;
149 }
150
QuerySysUsageEvent(std::shared_ptr<LoggerEvent> & event,const std::string & table)151 int EventDbHelper::QuerySysUsageEvent(std::shared_ptr<LoggerEvent>& event, const std::string& table)
152 {
153 if (rdbStore_ == nullptr) {
154 HIVIEW_LOGE("dbStore is null");
155 return -1;
156 }
157 std::string eventStr;
158 if (QuerySysUsageTable(eventStr, table) != 0 || eventStr.empty()) {
159 HIVIEW_LOGD("failed to query sysUsage table=%{public}s", table.c_str());
160 return -1;
161 }
162 event = std::make_shared<SysUsageEvent>(SysUsageEventSpace::EVENT_NAME, HiSysEvent::STATISTIC);
163 if (!JsonParser::ParseSysUsageEvent(event, eventStr)) {
164 HIVIEW_LOGE("failed to parse the database record=%{public}s", eventStr.c_str());
165 return -1;
166 }
167 return 0;
168 }
169
DeletePluginStatsEvent()170 int EventDbHelper::DeletePluginStatsEvent()
171 {
172 if (rdbStore_ == nullptr) {
173 HIVIEW_LOGE("dbStore is null");
174 return -1;
175 }
176 return DeleteTableData(DB_TABLE_PLUGIN_STATS);
177 }
178
DeleteSysUsageEvent(const std::string & table)179 int EventDbHelper::DeleteSysUsageEvent(const std::string& table)
180 {
181 if (rdbStore_ == nullptr) {
182 HIVIEW_LOGE("dbStore is null");
183 return -1;
184 }
185 return DeleteTableData(table);
186 }
187
CreateTable(const std::string & table,const std::vector<std::pair<std::string,std::string>> & fields)188 int EventDbHelper::CreateTable(const std::string& table,
189 const std::vector<std::pair<std::string, std::string>>& fields)
190 {
191 std::string sql = SqlUtil::GenerateCreateSql(table, fields);
192 if (rdbStore_->ExecuteSql(sql) != NativeRdb::E_OK) {
193 HIVIEW_LOGE("failed to create table=%{public}s, sql=%{public}s", table.c_str(), sql.c_str());
194 return -1;
195 }
196 return 0;
197 }
198
CreatePluginStatsTable(const std::string & table)199 int EventDbHelper::CreatePluginStatsTable(const std::string& table)
200 {
201 /**
202 * table: plugin_stats
203 *
204 * |----|--------|-------|
205 * | id | plugin | event |
206 * |----|--------|-------|
207 */
208 std::vector<std::pair<std::string, std::string>> fields = {
209 {DB_COLUMIN_EVNET, SQL_TEXT_TYPE}, {DB_COLUMIN_PLUGIN, SQL_TEXT_TYPE}
210 };
211 return CreateTable(table, fields);
212 }
213
CreateSysUsageTable(const std::string & table)214 int EventDbHelper::CreateSysUsageTable(const std::string& table)
215 {
216 /**
217 * table: sys_usage / last_sys_usage
218 *
219 * |----|-------|
220 * | id | event |
221 * |----|-------|
222 */
223 std::vector<std::pair<std::string, std::string>> fields = {{DB_COLUMIN_EVNET, SQL_TEXT_TYPE}};
224 return CreateTable(table, fields);
225 }
226
InsertPluginStatsTable(const std::string & pluginName,const std::string & eventStr)227 int EventDbHelper::InsertPluginStatsTable(const std::string& pluginName, const std::string& eventStr)
228 {
229 if (CreatePluginStatsTable(DB_TABLE_PLUGIN_STATS) != 0) {
230 HIVIEW_LOGE("failed to create table=%{public}s", DB_TABLE_PLUGIN_STATS.c_str());
231 return -1;
232 }
233
234 HIVIEW_LOGD("insert db=%{public}s with %{public}s", dbPath_.c_str(), eventStr.c_str());
235 NativeRdb::ValuesBucket bucket;
236 bucket.PutString(DB_COLUMIN_PLUGIN, pluginName);
237 bucket.PutString(DB_COLUMIN_EVNET, eventStr);
238 int64_t seq = 0;
239 if (rdbStore_->Insert(seq, DB_TABLE_PLUGIN_STATS, bucket) != NativeRdb::E_OK) {
240 HIVIEW_LOGE("failed to insert pluginStats event=%{public}s", eventStr.c_str());
241 return -1;
242 }
243 return 0;
244 }
245
InsertSysUsageTable(const std::string & table,const std::string & eventStr)246 int EventDbHelper::InsertSysUsageTable(const std::string& table, const std::string& eventStr)
247 {
248 if (CreateSysUsageTable(table) != 0) {
249 HIVIEW_LOGE("failed to create table=%{public}s", table.c_str());
250 return -1;
251 }
252
253 HIVIEW_LOGD("insert db=%{public}s with %{public}s", dbPath_.c_str(), eventStr.c_str());
254 NativeRdb::ValuesBucket bucket;
255 bucket.PutString(DB_COLUMIN_EVNET, eventStr);
256 int64_t seq = 0;
257 if (rdbStore_->Insert(seq, table, bucket) != NativeRdb::E_OK) {
258 HIVIEW_LOGE("failed to insert sysUsage event=%{public}s", eventStr.c_str());
259 return -1;
260 }
261 return 0;
262 }
263
UpdatePluginStatsTable(const std::string & pluginName,const std::string & eventStr)264 int EventDbHelper::UpdatePluginStatsTable(const std::string& pluginName, const std::string& eventStr)
265 {
266 HIVIEW_LOGD("update db table %{public}s with %{public}s", DB_TABLE_PLUGIN_STATS.c_str(), eventStr.c_str());
267 NativeRdb::ValuesBucket bucket;
268 bucket.PutString(DB_COLUMIN_EVNET, eventStr);
269 NativeRdb::AbsRdbPredicates predicates(DB_TABLE_PLUGIN_STATS);
270 predicates.EqualTo(DB_COLUMIN_PLUGIN, pluginName);
271 int changeRows = 0;
272 if (rdbStore_->Update(changeRows, bucket, predicates) != NativeRdb::E_OK || changeRows == 0) {
273 HIVIEW_LOGE("failed to update pluginStats event=%{public}s", eventStr.c_str());
274 return -1;
275 }
276 return 0;
277 }
278
UpdateSysUsageTable(const std::string & table,const std::string & eventStr)279 int EventDbHelper::UpdateSysUsageTable(const std::string& table, const std::string& eventStr)
280 {
281 HIVIEW_LOGD("update db table %{public}s with %{public}s", table.c_str(), eventStr.c_str());
282 NativeRdb::ValuesBucket bucket;
283 bucket.PutString(DB_COLUMIN_EVNET, eventStr);
284 NativeRdb::AbsRdbPredicates predicates(table);
285 int changeRows = 0;
286 if (rdbStore_->Update(changeRows, bucket, predicates) != NativeRdb::E_OK || changeRows == 0) {
287 HIVIEW_LOGE("failed to update sysUsage event=%{public}s", eventStr.c_str());
288 return -1;
289 }
290 return 0;
291 }
292
QueryPluginStatsTable(std::vector<std::string> & eventStrs,const std::string & pluginName)293 int EventDbHelper::QueryPluginStatsTable(std::vector<std::string>& eventStrs, const std::string& pluginName)
294 {
295 return (QueryDb(eventStrs, DB_TABLE_PLUGIN_STATS, {{DB_COLUMIN_PLUGIN, pluginName}}) != NativeRdb::E_OK) ? -1 : 0;
296 }
297
QuerySysUsageTable(std::string & eventStr,const std::string & table)298 int EventDbHelper::QuerySysUsageTable(std::string& eventStr, const std::string& table)
299 {
300 std::vector<std::string> events;
301 if (QueryDb(events, table, {}) != NativeRdb::E_OK || events.empty()) {
302 return -1;
303 }
304 eventStr = events[0];
305 return 0;
306 }
307
QueryDb(std::vector<std::string> & eventStrs,const std::string & table,const std::vector<std::pair<std::string,std::string>> & queryConds)308 int EventDbHelper::QueryDb(std::vector<std::string>& eventStrs, const std::string& table,
309 const std::vector<std::pair<std::string, std::string>>& queryConds)
310 {
311 NativeRdb::AbsRdbPredicates predicates(table);
312 for (auto queryCond : queryConds) {
313 predicates.EqualTo(queryCond.first, queryCond.second);
314 }
315 auto resultSet = rdbStore_->Query(predicates, {DB_COLUMIN_EVNET});
316 if (resultSet == nullptr) {
317 HIVIEW_LOGI("failed to query table=%{public}s", table.c_str());
318 return -1;
319 }
320 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
321 std::string event;
322 if (resultSet->GetString(0, event) != NativeRdb::E_OK) {
323 HIVIEW_LOGI("failed to get %{public}s string from resultSet", DB_COLUMIN_EVNET.c_str());
324 continue;
325 }
326 eventStrs.emplace_back(event);
327 }
328 return 0;
329 }
330
DeleteTableData(const std::string & table)331 int EventDbHelper::DeleteTableData(const std::string& table)
332 {
333 HIVIEW_LOGI("delete data from the table=%{public}s", table.c_str());
334 int deleteRows = 0;
335 NativeRdb::AbsRdbPredicates predicates(table);
336 return rdbStore_->Delete(deleteRows, predicates) == NativeRdb::E_OK ? 0 : -1;
337 }
338 } // namespace HiviewDFX
339 } // namespace OHOS
340