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
16 #include "rdb_data_manager.h"
17
18 #include "app_log_wrapper.h"
19 #include "bundle_memory_guard.h"
20 #include "bundle_util.h"
21 #include "scope_guard.h"
22
23 #include <thread>
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 const std::string BMS_KEY = "KEY";
29 const std::string BMS_VALUE = "VALUE";
30 const int32_t BMS_KEY_INDEX = 0;
31 const int32_t BMS_VALUE_INDEX = 1;
32 const int32_t CLOSE_TIME = 20; // delay 20s stop rdbStore
33 }
34
RdbDataManager(const BmsRdbConfig & bmsRdbConfig)35 RdbDataManager::RdbDataManager(const BmsRdbConfig &bmsRdbConfig)
36 : bmsRdbConfig_(bmsRdbConfig)
37 {
38 }
39
~RdbDataManager()40 RdbDataManager::~RdbDataManager()
41 {
42 rdbStore_ = nullptr;
43 }
44
ClearCache()45 void RdbDataManager::ClearCache()
46 {
47 NativeRdb::RdbHelper::ClearCache();
48 }
49
GetRdbStore()50 std::shared_ptr<NativeRdb::RdbStore> RdbDataManager::GetRdbStore()
51 {
52 std::lock_guard<std::mutex> lock(rdbMutex_);
53 if (rdbStore_ != nullptr) {
54 return rdbStore_;
55 }
56 NativeRdb::RdbStoreConfig rdbStoreConfig(bmsRdbConfig_.dbPath + bmsRdbConfig_.dbName);
57 rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
58 int32_t errCode = NativeRdb::E_OK;
59 BmsRdbOpenCallback bmsRdbOpenCallback(bmsRdbConfig_);
60 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(
61 rdbStoreConfig,
62 bmsRdbConfig_.version,
63 bmsRdbOpenCallback,
64 errCode);
65 DelayCloseRdbStore();
66 return rdbStore_;
67 }
68
InsertData(const std::string & key,const std::string & value)69 bool RdbDataManager::InsertData(const std::string &key, const std::string &value)
70 {
71 APP_LOGD("InsertData start");
72 auto rdbStore = GetRdbStore();
73 if (rdbStore == nullptr) {
74 APP_LOGE("RdbStore is null");
75 return false;
76 }
77
78 int64_t rowId = -1;
79 NativeRdb::ValuesBucket valuesBucket;
80 valuesBucket.PutString(BMS_KEY, key);
81 valuesBucket.PutString(BMS_VALUE, value);
82 auto ret = rdbStore->InsertWithConflictResolution(
83 rowId, bmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
84 return ret == NativeRdb::E_OK;
85 }
86
InsertData(const NativeRdb::ValuesBucket & valuesBucket)87 bool RdbDataManager::InsertData(const NativeRdb::ValuesBucket &valuesBucket)
88 {
89 APP_LOGD("InsertData start");
90 auto rdbStore = GetRdbStore();
91 if (rdbStore == nullptr) {
92 APP_LOGE("RdbStore is null");
93 return false;
94 }
95
96 int64_t rowId = -1;
97 auto ret = rdbStore->InsertWithConflictResolution(
98 rowId, bmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
99 return ret == NativeRdb::E_OK;
100 }
101
BatchInsert(int64_t & outInsertNum,const std::vector<NativeRdb::ValuesBucket> & valuesBuckets)102 bool RdbDataManager::BatchInsert(int64_t &outInsertNum, const std::vector<NativeRdb::ValuesBucket> &valuesBuckets)
103 {
104 APP_LOGD("BatchInsert start");
105 auto rdbStore = GetRdbStore();
106 if (rdbStore == nullptr) {
107 APP_LOGE("RdbStore is null");
108 return false;
109 }
110 auto ret = rdbStore->BatchInsert(outInsertNum, bmsRdbConfig_.tableName, valuesBuckets);
111 return ret == NativeRdb::E_OK;
112 }
113
UpdateData(const std::string & key,const std::string & value)114 bool RdbDataManager::UpdateData(const std::string &key, const std::string &value)
115 {
116 APP_LOGD("UpdateData start");
117 auto rdbStore = GetRdbStore();
118 if (rdbStore == nullptr) {
119 APP_LOGE("RdbStore is null");
120 return false;
121 }
122
123 int32_t rowId = -1;
124 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
125 absRdbPredicates.EqualTo(BMS_KEY, key);
126 NativeRdb::ValuesBucket valuesBucket;
127 valuesBucket.PutString(BMS_KEY, key);
128 valuesBucket.PutString(BMS_VALUE, value);
129 auto ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
130 return ret == NativeRdb::E_OK;
131 }
132
UpdateData(const NativeRdb::ValuesBucket & valuesBucket,const NativeRdb::AbsRdbPredicates & absRdbPredicates)133 bool RdbDataManager::UpdateData(
134 const NativeRdb::ValuesBucket &valuesBucket, const NativeRdb::AbsRdbPredicates &absRdbPredicates)
135 {
136 APP_LOGD("UpdateData start");
137 auto rdbStore = GetRdbStore();
138 if (rdbStore == nullptr) {
139 APP_LOGE("RdbStore is null");
140 return false;
141 }
142 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
143 APP_LOGE("RdbStore table is invalid");
144 return false;
145 }
146 int32_t rowId = -1;
147 auto ret = rdbStore->Update(rowId, valuesBucket, absRdbPredicates);
148 return ret == NativeRdb::E_OK;
149 }
150
DeleteData(const std::string & key)151 bool RdbDataManager::DeleteData(const std::string &key)
152 {
153 APP_LOGD("DeleteData start");
154 auto rdbStore = GetRdbStore();
155 if (rdbStore == nullptr) {
156 APP_LOGE("RdbStore is null");
157 return false;
158 }
159
160 int32_t rowId = -1;
161 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
162 absRdbPredicates.EqualTo(BMS_KEY, key);
163 auto ret = rdbStore->Delete(rowId, absRdbPredicates);
164 return ret == NativeRdb::E_OK;
165 }
166
DeleteData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)167 bool RdbDataManager::DeleteData(const NativeRdb::AbsRdbPredicates &absRdbPredicates)
168 {
169 auto rdbStore = GetRdbStore();
170 if (rdbStore == nullptr) {
171 APP_LOGE("RdbStore is null");
172 return false;
173 }
174 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
175 APP_LOGE("RdbStore table is invalid");
176 return false;
177 }
178 int32_t rowId = -1;
179 auto ret = rdbStore->Delete(rowId, absRdbPredicates);
180 return ret == NativeRdb::E_OK;
181 }
182
QueryData(const std::string & key,std::string & value)183 bool RdbDataManager::QueryData(const std::string &key, std::string &value)
184 {
185 APP_LOGD("QueryData start");
186 auto rdbStore = GetRdbStore();
187 if (rdbStore == nullptr) {
188 APP_LOGE("RdbStore is null");
189 return false;
190 }
191
192 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
193 absRdbPredicates.EqualTo(BMS_KEY, key);
194 auto absSharedResultSet = rdbStore->Query(absRdbPredicates, std::vector<std::string>());
195 if (absSharedResultSet == nullptr) {
196 APP_LOGE("absSharedResultSet failed");
197 return false;
198 }
199 ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
200 if (!absSharedResultSet->HasBlock()) {
201 APP_LOGE("absSharedResultSet has no block");
202 return false;
203 }
204 auto ret = absSharedResultSet->GoToFirstRow();
205 if (ret != NativeRdb::E_OK) {
206 APP_LOGE("GoToFirstRow failed, ret: %{public}d", ret);
207 return false;
208 }
209
210 ret = absSharedResultSet->GetString(BMS_VALUE_INDEX, value);
211 if (ret != NativeRdb::E_OK) {
212 APP_LOGE("QueryData failed, ret: %{public}d", ret);
213 return false;
214 }
215
216 return true;
217 }
218
QueryData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)219 std::shared_ptr<NativeRdb::AbsSharedResultSet> RdbDataManager::QueryData(
220 const NativeRdb::AbsRdbPredicates &absRdbPredicates)
221 {
222 APP_LOGD("QueryData start");
223 auto rdbStore = GetRdbStore();
224 if (rdbStore == nullptr) {
225 APP_LOGE("RdbStore is null");
226 return nullptr;
227 }
228 if (absRdbPredicates.GetTableName() != bmsRdbConfig_.tableName) {
229 APP_LOGE("RdbStore table is invalid");
230 return nullptr;
231 }
232 auto absSharedResultSet = rdbStore->Query(absRdbPredicates, std::vector<std::string>());
233 if (absSharedResultSet == nullptr || !absSharedResultSet->HasBlock()) {
234 APP_LOGE("absSharedResultSet failed");
235 return nullptr;
236 }
237 return absSharedResultSet;
238 }
239
QueryAllData(std::map<std::string,std::string> & datas)240 bool RdbDataManager::QueryAllData(std::map<std::string, std::string> &datas)
241 {
242 APP_LOGD("QueryAllData start");
243 auto rdbStore = GetRdbStore();
244 if (rdbStore == nullptr) {
245 APP_LOGE("RdbStore is null");
246 return false;
247 }
248
249 NativeRdb::AbsRdbPredicates absRdbPredicates(bmsRdbConfig_.tableName);
250 auto absSharedResultSet = rdbStore->Query(absRdbPredicates, std::vector<std::string>());
251 if (absSharedResultSet == nullptr) {
252 APP_LOGE("absSharedResultSet failed");
253 return false;
254 }
255 ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
256 if (!absSharedResultSet->HasBlock()) {
257 APP_LOGE("absSharedResultSet has no block");
258 return false;
259 }
260
261 if (absSharedResultSet->GoToFirstRow() != NativeRdb::E_OK) {
262 APP_LOGE("GoToFirstRow failed");
263 return false;
264 }
265
266 do {
267 std::string key;
268 if (absSharedResultSet->GetString(BMS_KEY_INDEX, key) != NativeRdb::E_OK) {
269 APP_LOGE("GetString key failed");
270 return false;
271 }
272
273 std::string value;
274 if (absSharedResultSet->GetString(BMS_VALUE_INDEX, value) != NativeRdb::E_OK) {
275 APP_LOGE("GetString value failed");
276 return false;
277 }
278
279 datas.emplace(key, value);
280 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
281 return !datas.empty();
282 }
283
CreateTable()284 bool RdbDataManager::CreateTable()
285 {
286 std::string createTableSql;
287 if (bmsRdbConfig_.createTableSql.empty()) {
288 createTableSql = std::string(
289 "CREATE TABLE IF NOT EXISTS "
290 + bmsRdbConfig_.tableName
291 + "(KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);");
292 } else {
293 createTableSql = bmsRdbConfig_.createTableSql;
294 }
295 auto rdbStore = GetRdbStore();
296 if (rdbStore == nullptr) {
297 APP_LOGE("RdbStore is null");
298 return false;
299 }
300 int ret = rdbStore->ExecuteSql(createTableSql);
301 if (ret != NativeRdb::E_OK) {
302 APP_LOGE("CreateTable failed, ret: %{public}d", ret);
303 return false;
304 }
305 for (const auto &sql : bmsRdbConfig_.insertColumnSql) {
306 int32_t insertRet = rdbStore->ExecuteSql(sql);
307 if (insertRet != NativeRdb::E_OK) {
308 APP_LOGW("ExecuteSql insertColumnSql failed, insertRet: %{public}d", insertRet);
309 }
310 }
311 return true;
312 }
313
DelayCloseRdbStore()314 void RdbDataManager::DelayCloseRdbStore()
315 {
316 APP_LOGD("RdbDataManager DelayCloseRdbStore start");
317 std::weak_ptr<RdbDataManager> weakPtr = shared_from_this();
318 auto task = [weakPtr]() {
319 APP_LOGD("RdbDataManager DelayCloseRdbStore thread begin");
320 std::this_thread::sleep_for(std::chrono::seconds(CLOSE_TIME));
321 auto sharedPtr = weakPtr.lock();
322 if (sharedPtr == nullptr) {
323 return;
324 }
325 std::lock_guard<std::mutex> lock(sharedPtr->rdbMutex_);
326 sharedPtr->rdbStore_ = nullptr;
327 APP_LOGD("RdbDataManager DelayCloseRdbStore thread end");
328 };
329 std::thread closeRdbStoreThread(task);
330 closeRdbStoreThread.detach();
331 }
332 } // namespace AppExecFwk
333 } // namespace OHOS
334