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