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 #include "daily_db_helper.h"
16
17 #include "file_util.h"
18 #include "hisysevent.h"
19 #include "hiview_db_util.h"
20 #include "hiview_logger.h"
21 #include "rdb_predicates.h"
22 #include "sql_util.h"
23 #include "time_util.h"
24
25 namespace OHOS {
26 namespace HiviewDFX {
27 DEFINE_LOG_TAG("DailyController");
28 namespace {
29 const std::string EVENTS_TABLE = "events_count";
30 const std::string EVENTS_COLUMIN_DOMAIN = "domain";
31 const std::string EVENTS_COLUMIN_NAME = "name";
32 const std::string EVENTS_COLUMIN_COUNT = "count";
33 const std::string EVENTS_COLUMIN_EXCEED_TIME = "exceed_time";
34
CreateEventsTable(NativeRdb::RdbStore & dbStore)35 int32_t CreateEventsTable(NativeRdb::RdbStore& dbStore)
36 {
37 /**
38 * table: events_count
39 *
40 * |-----|-----------|---------|-------|-------------|
41 * | id | domain | name | count | exceed_time |
42 * |-----|-----------|---------|-------|-------------|
43 * | INT | VARCHAR | VARCHAR | INT | INT |
44 * |-----|-----------|---------|-------|-------------|
45 */
46 const std::vector<std::pair<std::string, std::string>> fields = {
47 {EVENTS_COLUMIN_DOMAIN, SqlUtil::COLUMN_TYPE_STR},
48 {EVENTS_COLUMIN_NAME, SqlUtil::COLUMN_TYPE_STR},
49 {EVENTS_COLUMIN_COUNT, SqlUtil::COLUMN_TYPE_INT},
50 {EVENTS_COLUMIN_EXCEED_TIME, SqlUtil::COLUMN_TYPE_INT},
51 };
52 std::string sql = SqlUtil::GenerateCreateSql(EVENTS_TABLE, fields);
53 if (auto ret = dbStore.ExecuteSql(sql); ret != NativeRdb::E_OK) {
54 HIVIEW_LOGW("failed to create table=%{public}s, ret=%{public}d", EVENTS_TABLE.c_str(), ret);
55 return ret;
56 }
57 return NativeRdb::E_OK;
58 }
59 }
OnCreate(NativeRdb::RdbStore & rdbStore)60 int32_t DailyDbHelper::DailyDbOpenCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
61 {
62 HIVIEW_LOGI("create daily database");
63 return CreateEventsTable(rdbStore);
64 }
65
OnUpgrade(NativeRdb::RdbStore & rdbStore,int32_t oldVersion,int32_t newVersion)66 int32_t DailyDbHelper::DailyDbOpenCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore,
67 int32_t oldVersion, int32_t newVersion)
68 {
69 HIVIEW_LOGI("oldVersion=%{public}d, newVersion=%{public}d", oldVersion, newVersion);
70 return NativeRdb::E_OK;
71 }
72
DailyDbHelper(const std::string & workPath)73 DailyDbHelper::DailyDbHelper(const std::string& workPath) : workPath_(workPath), dbStore_(nullptr)
74 {
75 InitDb();
76 }
77
InitDb()78 void DailyDbHelper::InitDb()
79 {
80 if (!InitDbPath()) {
81 return;
82 }
83 InitDbStore();
84 }
85
InitDbPath()86 bool DailyDbHelper::InitDbPath()
87 {
88 if (workPath_.empty()) {
89 HIVIEW_LOGW("db path is null");
90 return false;
91 }
92
93 const std::string thresholdDir = "sys_event_threshold/";
94 std::string tempDbPath = FileUtil::IncludeTrailingPathDelimiter(workPath_).append(thresholdDir);
95 if (!FileUtil::IsDirectory(tempDbPath) && !FileUtil::ForceCreateDirectory(tempDbPath)) {
96 HIVIEW_LOGE("failed to create dir=%{public}s", tempDbPath.c_str());
97 return false;
98 }
99 tempDbPath.append(HiviewDbUtil::CreateFileNameByDate("events_"));
100 dbPath_ = tempDbPath;
101 HIVIEW_LOGI("succ to init db store path=%{public}s", dbPath_.c_str());
102 return true;
103 }
104
InitDbStore()105 void DailyDbHelper::InitDbStore()
106 {
107 NativeRdb::RdbStoreConfig config(dbPath_);
108 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
109 constexpr int32_t dbVersion = 1;
110 DailyDbOpenCallback callback;
111 auto ret = NativeRdb::E_OK;
112 dbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, dbVersion, callback, ret);
113 if (ret != NativeRdb::E_OK || dbStore_ == nullptr) {
114 HIVIEW_LOGW("failed to create db, ret=%{public}d", ret);
115 }
116 }
117
InsertEventInfo(const EventInfo & info)118 int32_t DailyDbHelper::InsertEventInfo(const EventInfo& info)
119 {
120 if (dbStore_ == nullptr) {
121 return -1;
122 }
123
124 NativeRdb::ValuesBucket bucket;
125 bucket.PutString(EVENTS_COLUMIN_DOMAIN, info.domain);
126 bucket.PutString(EVENTS_COLUMIN_NAME, info.name);
127 bucket.PutInt(EVENTS_COLUMIN_COUNT, info.count);
128 bucket.PutLong(EVENTS_COLUMIN_EXCEED_TIME, info.exceedTime);
129 int64_t seq = 0;
130 if (auto ret = dbStore_->Insert(seq, EVENTS_TABLE, bucket); ret != NativeRdb::E_OK) {
131 HIVIEW_LOGW("failed to insert event, domain=%{public}s, name=%{public}s",
132 info.domain.c_str(), info.name.c_str());
133 return -1;
134 }
135 HIVIEW_LOGD("succ to insert event, domain=%{public}s, name=%{public}s",
136 info.domain.c_str(), info.name.c_str());
137 return 0;
138 }
139
UpdateEventInfo(const EventInfo & info)140 int32_t DailyDbHelper::UpdateEventInfo(const EventInfo& info)
141 {
142 if (dbStore_ == nullptr) {
143 return -1;
144 }
145
146 NativeRdb::ValuesBucket bucket;
147 bucket.PutInt(EVENTS_COLUMIN_COUNT, info.count);
148 if (info.exceedTime != 0) {
149 bucket.PutLong(EVENTS_COLUMIN_EXCEED_TIME, info.exceedTime);
150 }
151 NativeRdb::AbsRdbPredicates predicates(EVENTS_TABLE);
152 predicates.EqualTo(EVENTS_COLUMIN_DOMAIN, info.domain);
153 predicates.EqualTo(EVENTS_COLUMIN_NAME, info.name);
154 int32_t changeRows = 0;
155 if (dbStore_->Update(changeRows, bucket, predicates) != NativeRdb::E_OK || changeRows == 0) {
156 HIVIEW_LOGW("failed to update event, domain=%{public}s, name=%{public}s, count=%{public}d",
157 info.domain.c_str(), info.name.c_str(), info.count);
158 return -1;
159 }
160 return 0;
161 }
162
QueryEventInfo(EventInfo & info)163 int32_t DailyDbHelper::QueryEventInfo(EventInfo& info)
164 {
165 if (dbStore_ == nullptr) {
166 return -1;
167 }
168
169 NativeRdb::AbsRdbPredicates predicates(EVENTS_TABLE);
170 predicates.EqualTo(EVENTS_COLUMIN_DOMAIN, info.domain);
171 predicates.EqualTo(EVENTS_COLUMIN_NAME, info.name);
172 auto resultSet = dbStore_->Query(predicates, {EVENTS_COLUMIN_COUNT});
173 if (resultSet == nullptr) {
174 HIVIEW_LOGW("failed to query table, domain=%{public}s, name=%{public}s",
175 info.domain.c_str(), info.name.c_str());
176 return -1;
177 }
178
179 // means that the event record is empty
180 if (resultSet->GoToNextRow() != NativeRdb::E_OK) {
181 resultSet->Close();
182 return 0;
183 }
184
185 if (resultSet->GetInt(0, info.count) != NativeRdb::E_OK || info.count < 0) {
186 HIVIEW_LOGW("failed to get count value, domain=%{public}s, name=%{public}s",
187 info.domain.c_str(), info.name.c_str());
188 resultSet->Close();
189 return -1;
190 }
191 resultSet->Close();
192 HIVIEW_LOGD("succ to query event, domain=%{public}s, name=%{public}s, count=%{public}d",
193 info.domain.c_str(), info.name.c_str(), info.count);
194 return 0;
195 }
196
NeedReport(int64_t nowTime)197 bool DailyDbHelper::NeedReport(int64_t nowTime)
198 {
199 std::string dateOfDbFile = HiviewDbUtil::GetDateFromDbFile(dbPath_);
200 std::string curDate = TimeUtil::TimestampFormatToDate(nowTime, "%Y%m%d");
201 return dateOfDbFile != curDate;
202 }
203
Report()204 void DailyDbHelper::Report()
205 {
206 HIVIEW_LOGI("start to report event infos");
207 PrepareOldDbFilesBeforeReport();
208 ReportDailyEvent();
209 PrepareNewDbFilesAfterReport();
210 }
211
PrepareOldDbFilesBeforeReport()212 void DailyDbHelper::PrepareOldDbFilesBeforeReport()
213 {
214 // 1. Close the current db file
215 CloseDbStore();
216
217 // 2. Init upload directory
218 if (!HiviewDbUtil::InitDbUploadPath(dbPath_, uploadPath_)) {
219 return;
220 }
221
222 // 3. Move the db file to the upload directory
223 HiviewDbUtil::MoveDbFilesToUploadDir(dbPath_, uploadPath_);
224
225 // 4. Aging upload db files, only the latest 7 db files are retained
226 HiviewDbUtil::TryToAgeUploadDbFiles(uploadPath_);
227 }
228
CloseDbStore()229 void DailyDbHelper::CloseDbStore()
230 {
231 dbStore_ = nullptr;
232 }
233
ReportDailyEvent()234 void DailyDbHelper::ReportDailyEvent()
235 {
236 int32_t ret = HiSysEventWrite(HiSysEvent::Domain::HIVIEWDFX, "EVENTS_DAILY",
237 HiSysEvent::EventType::FAULT, "DATE", HiviewDbUtil::GetDateFromDbFile(dbPath_));
238 if (ret != 0) {
239 HIVIEW_LOGW("failed to report event, ret=%{public}d", ret);
240 }
241 }
242
PrepareNewDbFilesAfterReport()243 void DailyDbHelper::PrepareNewDbFilesAfterReport()
244 {
245 InitDb();
246 }
247 } // namespace HiviewDFX
248 } // namespace OHOS
249