1 /*
2 * Copyright (c) 2022 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 "app_event_store.h"
16
17 #include <utility>
18 #include <vector>
19
20 #include "app_event_cache_common.h"
21 #include "app_event_store_callback.h"
22 #include "file_util.h"
23 #include "hilog/log.h"
24 #include "rdb_errno.h"
25 #include "rdb_helper.h"
26
27 using namespace OHOS::HiviewDFX::AppEventCacheCommon;
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace {
31 const HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_Store" };
32 const char* DATABASE_NAME = "appevent.db";
33 const char* DATABASE_DIR = "databases";
34 const char* SQL_TEXT_TYPE = "TEXT NOT NULL";
35 const char* SQL_INT_TYPE = "INTEGER";
36 const char PATH_DELIMITER = '/';
37
GenerateCreateSql(const std::string & table,std::vector<std::pair<std::string,std::string>> fields)38 std::string GenerateCreateSql(const std::string& table, std::vector<std::pair<std::string, std::string>> fields)
39 {
40 std::string sql;
41 sql += "CREATE TABLE IF NOT EXISTS ";
42 sql += table;
43 sql += "(";
44 sql += "seq INTEGER PRIMARY KEY AUTOINCREMENT"; // default field: seq
45 for (auto field : fields) {
46 sql += ", ";
47 sql += field.first;
48 sql += " ";
49 sql += field.second;
50 }
51 sql += ")";
52 return sql;
53 }
54
GenerateDropSql(const std::string & table)55 std::string GenerateDropSql(const std::string& table)
56 {
57 std::string sql;
58 sql += "DROP TABLE IF EXISTS ";
59 sql += table;
60 return sql;
61 }
62 }
AppEventStore(const std::string & dir)63 AppEventStore::AppEventStore(const std::string& dir) : dbStore_(nullptr), dirPath_("")
64 {
65 InitDbStoreDir(dir);
66 }
67
OnCreate(NativeRdb::RdbStore & rdbStore)68 int AppEventStoreCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
69 {
70 std::vector<std::pair<std::string, std::string>> fields = {
71 {Blocks::FIELD_NAME, SQL_TEXT_TYPE}
72 };
73 std::string sql = GenerateCreateSql(Blocks::TABLE, fields);
74 if (int ret = rdbStore.ExecuteSql(sql); ret != NativeRdb::E_OK) {
75 HiLog::Error(LABEL, "failed to create blocks table, ret=%{public}d", ret);
76 return ret;
77 }
78 return NativeRdb::E_OK;
79 }
80
OnUpgrade(NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)81 int AppEventStoreCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion)
82 {
83 HiLog::Debug(LABEL, "OnUpgrade, oldVersion=%{public}d, newVersion=%{public}d", oldVersion, newVersion);
84 return NativeRdb::E_OK;
85 }
86
GetDbStore()87 std::shared_ptr<NativeRdb::RdbStore> AppEventStore::GetDbStore()
88 {
89 if (dbStore_ == nullptr) {
90 std::lock_guard<std::mutex> lockGuard(dbMutex_);
91 if (dbStore_ == nullptr) {
92 dbStore_ = CreateDbStore();
93 }
94 }
95 return dbStore_;
96 }
97
InitDbStoreDir(const std::string & dir)98 void AppEventStore::InitDbStoreDir(const std::string& dir)
99 {
100 if (dir.empty()) {
101 HiLog::Error(LABEL, "failed to init db dir, path is empty");
102 return;
103 }
104 dirPath_ = FileUtil::GetFilePathByDir(dir, DATABASE_DIR);
105 dirPath_.push_back(PATH_DELIMITER);
106 }
107
CreateBlockTable(const std::string & name)108 int AppEventStore::CreateBlockTable(const std::string& name)
109 {
110 auto dbStore = GetDbStore();
111 if (dbStore == nullptr) {
112 HiLog::Error(LABEL, "failed to create table %{public}s, db is null", name.c_str());
113 return DB_FAILED;
114 }
115
116 std::vector<std::pair<std::string, std::string>> fields = {
117 {Block::FIELD_PACKAGE, SQL_TEXT_TYPE},
118 {Block::FIELD_SIZE, SQL_INT_TYPE}
119 };
120 std::string sql = GenerateCreateSql(Block::TABLE_PREFIX + name, fields);
121 if (int ret = dbStore->ExecuteSql(sql); ret != NativeRdb::E_OK) {
122 HiLog::Error(LABEL, "failed to create table %{public}s, ret=%{pulic}d", name.c_str(), ret);
123 return DB_FAILED;
124 }
125 HiLog::Info(LABEL, "create table %{public}s successfully", name.c_str());
126 return DB_SUCC;
127 }
128
DropBlockTable(const std::string & name)129 int AppEventStore::DropBlockTable(const std::string& name)
130 {
131 auto dbStore = GetDbStore();
132 if (dbStore == nullptr) {
133 HiLog::Error(LABEL, "failed to drop table %{public}s, db is null", name.c_str());
134 return DB_FAILED;
135 }
136
137 std::string sql = GenerateDropSql(Block::TABLE_PREFIX + name);
138 if (int ret = dbStore->ExecuteSql(sql); ret != NativeRdb::E_OK) {
139 HiLog::Error(LABEL, "failed to drop table %{public}s, ret=%{pulic}d", name.c_str(), ret);
140 return DB_FAILED;
141 }
142 HiLog::Info(LABEL, "drop table %{public}s successfully", name.c_str());
143 return DB_SUCC;
144 }
145
CreateDbStore()146 std::shared_ptr<NativeRdb::RdbStore> AppEventStore::CreateDbStore()
147 {
148 if (dirPath_.empty()) {
149 HiLog::Error(LABEL, "failed to create db store, path is empty");
150 return nullptr;
151 }
152 if (!FileUtil::IsFileExists(dirPath_) && !FileUtil::ForceCreateDirectory(dirPath_)) {
153 HiLog::Error(LABEL, "failed to create database dir, errno=%{public}d", errno);
154 return nullptr;
155 }
156
157 int ret = NativeRdb::E_OK;
158 NativeRdb::RdbStoreConfig config(dirPath_ + DATABASE_NAME);
159 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
160 AppEventStoreCallback callback;
161 auto dbStore = NativeRdb::RdbHelper::GetRdbStore(config, 1, callback, ret);
162 if (ret != NativeRdb::E_OK || dbStore == nullptr) {
163 HiLog::Error(LABEL, "failed to create db store, ret=%{pulic}d", ret);
164 return nullptr;
165 }
166 HiLog::Info(LABEL, "create db store successfully");
167 return dbStore;
168 }
169
DestroyDbStore()170 int AppEventStore::DestroyDbStore()
171 {
172 if (dbStore_ == nullptr) {
173 return DB_SUCC;
174 }
175
176 dbStore_ = nullptr;
177 if (int ret = NativeRdb::RdbHelper::DeleteRdbStore(dirPath_ + DATABASE_NAME); ret != NativeRdb::E_OK) {
178 HiLog::Error(LABEL, "failed to destroy db store, ret=%{pulic}d", ret);
179 return DB_FAILED;
180 }
181 HiLog::Info(LABEL, "destroy db store successfully");
182 return DB_SUCC;
183 }
184 } // namespace HiviewDFX
185 } // namespace OHOS
186