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 "notification_rdb_data_mgr.h"
16
17 #include "ans_log_wrapper.h"
18 #include "os_account_manager_helper.h"
19 #include "rdb_errno.h"
20 #include <algorithm>
21 #include <cstddef>
22 #include <sstream>
23 #include <string>
24 #include <vector>
25 #include "notification_analytics_util.h"
26
27 namespace OHOS {
28 namespace Notification {
29 namespace {
30 const std::string NOTIFICATION_KEY = "KEY";
31 const std::string NOTIFICATION_VALUE = "VALUE";
32 const int32_t NOTIFICATION_KEY_INDEX = 0;
33 const int32_t NOTIFICATION_VALUE_INDEX = 1;
34 const std::ptrdiff_t MAX_SIZE_PER_BATCH = 100;
35 } // namespace
RdbStoreDataCallBackNotificationStorage(const NotificationRdbConfig & notificationRdbConfig)36 RdbStoreDataCallBackNotificationStorage::RdbStoreDataCallBackNotificationStorage(
37 const NotificationRdbConfig ¬ificationRdbConfig): notificationRdbConfig_(notificationRdbConfig)
38 {
39 ANS_LOGD("create rdb store callback instance");
40 }
41
~RdbStoreDataCallBackNotificationStorage()42 RdbStoreDataCallBackNotificationStorage::~RdbStoreDataCallBackNotificationStorage()
43 {
44 ANS_LOGD("destroy rdb store callback instance");
45 }
46
OnCreate(NativeRdb::RdbStore & rdbStore)47 int32_t RdbStoreDataCallBackNotificationStorage::OnCreate(NativeRdb::RdbStore &rdbStore)
48 {
49 ANS_LOGD("OnCreate");
50 int ret = NativeRdb::E_OK;
51 if (hasTableInit_) {
52 return ret;
53 }
54 std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + notificationRdbConfig_.tableName
55 + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
56 ret = rdbStore.ExecuteSql(createTableSql);
57 if (ret == NativeRdb::E_OK) {
58 hasTableInit_ = true;
59 ANS_LOGD("createTable succeed");
60 }
61 return ret;
62 }
63
OnUpgrade(NativeRdb::RdbStore & rdbStore,int32_t oldVersion,int32_t newVersion)64 int32_t RdbStoreDataCallBackNotificationStorage::OnUpgrade(
65 NativeRdb::RdbStore &rdbStore, int32_t oldVersion, int32_t newVersion)
66 {
67 ANS_LOGD("OnUpgrade currentVersion: %{public}d, targetVersion: %{public}d",
68 oldVersion, newVersion);
69 return NativeRdb::E_OK;
70 }
71
OnDowngrade(NativeRdb::RdbStore & rdbStore,int currentVersion,int targetVersion)72 int32_t RdbStoreDataCallBackNotificationStorage::OnDowngrade(
73 NativeRdb::RdbStore &rdbStore, int currentVersion, int targetVersion)
74 {
75 ANS_LOGD("OnDowngrade currentVersion: %{public}d, targetVersion: %{public}d",
76 currentVersion, targetVersion);
77 return NativeRdb::E_OK;
78 }
79
OnOpen(NativeRdb::RdbStore & rdbStore)80 int32_t RdbStoreDataCallBackNotificationStorage::OnOpen(NativeRdb::RdbStore &rdbStore)
81 {
82 ANS_LOGD("OnOpen");
83 return NativeRdb::E_OK;
84 }
85
onCorruption(std::string databaseFile)86 int32_t RdbStoreDataCallBackNotificationStorage::onCorruption(std::string databaseFile)
87 {
88 return NativeRdb::E_OK;
89 }
90
NotificationDataMgr(const NotificationRdbConfig & notificationRdbConfig)91 NotificationDataMgr::NotificationDataMgr(const NotificationRdbConfig ¬ificationRdbConfig)
92 : notificationRdbConfig_(notificationRdbConfig)
93 {
94 ANS_LOGD("create notification rdb data manager");
95 }
96
Init()97 int32_t NotificationDataMgr::Init()
98 {
99 ANS_LOGD("Create rdbStore");
100 {
101 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
102 if (rdbStore_ != nullptr) {
103 ANS_LOGD("notification rdb has existed");
104 return NativeRdb::E_OK;
105 }
106 }
107 NativeRdb::RdbStoreConfig rdbStoreConfig(
108 notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName,
109 NativeRdb::StorageMode::MODE_DISK,
110 false,
111 std::vector<uint8_t>(),
112 notificationRdbConfig_.journalMode,
113 notificationRdbConfig_.syncMode);
114 rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
115 rdbStoreConfig.SetHaMode(NativeRdb::HAMode::MAIN_REPLICA);
116 RdbStoreDataCallBackNotificationStorage rdbDataCallBack_(notificationRdbConfig_);
117 std::lock_guard<std::mutex> lock(createdTableMutex_);
118 {
119 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
120 int32_t ret = NativeRdb::E_OK;
121 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, notificationRdbConfig_.version,
122 rdbDataCallBack_, ret);
123 if (rdbStore_ == nullptr) {
124 ANS_LOGE("notification rdb init fail");
125 return NativeRdb::E_ERROR;
126 }
127 return InitCreatedTables();
128 }
129 }
130
InitCreatedTables()131 int32_t NotificationDataMgr::InitCreatedTables()
132 {
133 std::string queryTableSql = "SELECT name FROM sqlite_master WHERE type='table'";
134 auto absSharedResultSet = rdbStore_->QuerySql(queryTableSql);
135 int32_t ret = absSharedResultSet->GoToFirstRow();
136 if (ret != NativeRdb::E_OK) {
137 ANS_LOGE("Query tableName failed. It's empty!");
138 return NativeRdb::E_EMPTY_VALUES_BUCKET;
139 }
140
141 do {
142 std::string tableName;
143 ret = absSharedResultSet->GetString(0, tableName);
144 if (ret != NativeRdb::E_OK) {
145 ANS_LOGE("GetString string failed from sqlite_master table.");
146 return NativeRdb::E_ERROR;
147 }
148 createdTables_.insert(tableName);
149 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
150 absSharedResultSet->Close();
151 return NativeRdb::E_OK;
152 }
153
Destroy()154 int32_t NotificationDataMgr::Destroy()
155 {
156 ANS_LOGD("Destory rdbStore");
157 std::lock_guard<std::mutex> lock(createdTableMutex_);
158 createdTables_.clear();
159 {
160 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
161 if (rdbStore_ == nullptr) {
162 ANS_LOGE("notification rdb is null");
163 return NativeRdb::E_ERROR;
164 }
165
166 rdbStore_ = nullptr;
167 }
168 int32_t ret = NativeRdb::RdbHelper::DeleteRdbStore(notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName);
169 if (ret != NativeRdb::E_OK) {
170 ANS_LOGE("failed to destroy db store");
171 return NativeRdb::E_ERROR;
172 }
173 ANS_LOGD("destroy db store successfully");
174 return NativeRdb::E_OK;
175 }
176
InsertData(const std::string & key,const std::string & value,const int32_t & userId)177 int32_t NotificationDataMgr::InsertData(const std::string &key, const std::string &value, const int32_t &userId)
178 {
179 ANS_LOGD("InsertData start");
180 {
181 std::string tableName;
182 int32_t ret = GetUserTableName(userId, tableName);
183 if (ret != NativeRdb::E_OK) {
184 ANS_LOGE("Get user table name failed.");
185 return NativeRdb::E_ERROR;
186 }
187 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
188 if (rdbStore_ == nullptr) {
189 ANS_LOGE("notification rdb is null");
190 return NativeRdb::E_ERROR;
191 }
192 int64_t rowId = -1;
193 NativeRdb::ValuesBucket valuesBucket;
194 valuesBucket.PutString(NOTIFICATION_KEY, key);
195 valuesBucket.PutString(NOTIFICATION_VALUE, value);
196 ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
197 NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
198 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
199 RestoreForMasterSlaver();
200 }
201 if (ret != NativeRdb::E_OK) {
202 ANS_LOGE("Insert operation failed, result: %{public}d, key=%{public}s.", ret, key.c_str());
203 return NativeRdb::E_ERROR;
204 }
205 }
206 return NativeRdb::E_OK;
207 }
208
InsertData(const std::string & key,const std::vector<uint8_t> & value,const int32_t & userId)209 int32_t NotificationDataMgr::InsertData(const std::string &key, const std::vector<uint8_t> &value,
210 const int32_t &userId)
211 {
212 std::string tableName;
213 int32_t ret = GetUserTableName(userId, tableName);
214 if (ret != NativeRdb::E_OK) {
215 ANS_LOGE("Get user table name failed.");
216 return NativeRdb::E_ERROR;
217 }
218 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
219 if (rdbStore_ == nullptr) {
220 ANS_LOGE("notification rdb is null");
221 return NativeRdb::E_ERROR;
222 }
223 int64_t rowId = -1;
224 NativeRdb::ValuesBucket valuesBucket;
225 valuesBucket.PutString(NOTIFICATION_KEY, key);
226 valuesBucket.PutBlob(NOTIFICATION_VALUE, value);
227 ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
228 NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
229 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
230 RestoreForMasterSlaver();
231 }
232 if (ret != NativeRdb::E_OK) {
233 ANS_LOGE("Insert operation failed, result: %{public}d, key=%{public}s.", ret, key.c_str());
234 return NativeRdb::E_ERROR;
235 }
236 return NativeRdb::E_OK;
237 }
238
InsertBatchData(const std::unordered_map<std::string,std::string> & values,const int32_t & userId)239 int32_t NotificationDataMgr::InsertBatchData(const std::unordered_map<std::string, std::string> &values,
240 const int32_t &userId)
241 {
242 ANS_LOGD("InsertBatchData start");
243 {
244 std::string tableName;
245 int32_t ret = GetUserTableName(userId, tableName);
246 if (ret != NativeRdb::E_OK) {
247 ANS_LOGE("Get user table name failed.");
248 return NativeRdb::E_ERROR;
249 }
250 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
251 if (rdbStore_ == nullptr) {
252 ANS_LOGE("notification rdb is null");
253 return NativeRdb::E_ERROR;
254 }
255 int64_t rowId = -1;
256 std::vector<NativeRdb::ValuesBucket> buckets;
257 for (auto &value : values) {
258 NativeRdb::ValuesBucket valuesBucket;
259 valuesBucket.PutString(NOTIFICATION_KEY, value.first);
260 valuesBucket.PutString(NOTIFICATION_VALUE, value.second);
261 buckets.emplace_back(valuesBucket);
262 }
263 ret = rdbStore_->BatchInsert(rowId, tableName, buckets);
264 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
265 RestoreForMasterSlaver();
266 }
267 if (ret != NativeRdb::E_OK) {
268 ANS_LOGE("Insert batch operation failed, result: %{public}d.", ret);
269 return NativeRdb::E_ERROR;
270 }
271 }
272 return NativeRdb::E_OK;
273 }
274
DeleteData(const std::string & key,const int32_t & userId)275 int32_t NotificationDataMgr::DeleteData(const std::string &key, const int32_t &userId)
276 {
277 ANS_LOGD("DeleteData start");
278 std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
279 std::reverse(operatedTables.begin(), operatedTables.end());
280 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
281 if (rdbStore_ == nullptr) {
282 ANS_LOGE("notification rdb is null");
283 return NativeRdb::E_ERROR;
284 }
285 int32_t ret = NativeRdb::E_OK;
286 int32_t rowId = -1;
287 for (auto tableName : operatedTables) {
288 ret = DeleteData(tableName, key, rowId);
289 if (ret != NativeRdb::E_OK) {
290 return ret;
291 }
292 }
293 return ret;
294 }
295
DeleteData(const std::string tableName,const std::string key,int32_t & rowId)296 int32_t NotificationDataMgr::DeleteData(const std::string tableName, const std::string key, int32_t &rowId)
297 {
298 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
299 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
300 int32_t ret = rdbStore_->Delete(rowId, absRdbPredicates);
301 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
302 RestoreForMasterSlaver();
303 }
304 if (ret != NativeRdb::E_OK) {
305 ANS_LOGW("Delete operation failed from %{public}s, result: %{public}d, key=%{public}s.",
306 tableName.c_str(), ret, key.c_str());
307 return NativeRdb::E_ERROR;
308 }
309 return NativeRdb::E_OK;
310 }
311
DeleteBatchData(const std::vector<std::string> & keys,const int32_t & userId)312 int32_t NotificationDataMgr::DeleteBatchData(const std::vector<std::string> &keys, const int32_t &userId)
313 {
314 ANS_LOGD("Delete Bathch Data start");
315 {
316 std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
317 std::reverse(operatedTables.begin(), operatedTables.end());
318 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
319 if (rdbStore_ == nullptr) {
320 ANS_LOGE("notification rdb is null");
321 return NativeRdb::E_ERROR;
322 }
323 std::vector<std::vector<std::string>> batchKeys;
324 auto start = keys.cbegin(), next = keys.cbegin(), end = keys.cend();
325 while (next != end) {
326 next = end - next < MAX_SIZE_PER_BATCH ? end : next + MAX_SIZE_PER_BATCH;
327 batchKeys.push_back(std::vector<std::string>(start, next));
328 start = next;
329 }
330
331 int32_t rowId = -1;
332 for (auto tableName : operatedTables) {
333 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
334 for (const auto &batchKey : batchKeys) {
335 absRdbPredicates.In(NOTIFICATION_KEY, batchKey);
336 int32_t ret = rdbStore_->Delete(rowId, absRdbPredicates);
337 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
338 RestoreForMasterSlaver();
339 }
340 if (ret != NativeRdb::E_OK) {
341 ANS_LOGW("Delete operation failed from %{public}s, result: %{public}d.",
342 tableName.c_str(), ret);
343 return NativeRdb::E_ERROR;
344 }
345 }
346 }
347 }
348 return NativeRdb::E_OK;
349 }
350
QueryData(const std::string & key,std::string & value,const int32_t & userId)351 int32_t NotificationDataMgr::QueryData(const std::string &key, std::string &value, const int32_t &userId)
352 {
353 ANS_LOGD("QueryData start");
354 std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
355 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
356 if (rdbStore_ == nullptr) {
357 ANS_LOGE("notification rdb is null");
358 return NativeRdb::E_ERROR;
359 }
360 int32_t ret = NativeRdb::E_OK;
361 for (auto tableName : operatedTables) {
362 ret = QueryData(tableName, key, value);
363 if (ret != NativeRdb::E_EMPTY_VALUES_BUCKET) {
364 return ret;
365 }
366 }
367 return ret;
368 }
369
QueryData(const std::string tableName,const std::string key,std::string & value)370 int32_t NotificationDataMgr::QueryData(const std::string tableName, const std::string key, std::string &value)
371 {
372 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
373 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
374 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
375 if (absSharedResultSet == nullptr) {
376 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
377 return NativeRdb::E_ERROR;
378 }
379
380 int32_t ret = absSharedResultSet->GoToFirstRow();
381 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
382 RestoreForMasterSlaver();
383 }
384 if (ret != NativeRdb::E_OK) {
385 ANS_LOGW("GoToFirstRow failed from %{public}s table. It is empty!, key=%{public}s",
386 tableName.c_str(), key.c_str());
387 return NativeRdb::E_EMPTY_VALUES_BUCKET;
388 }
389 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, value);
390 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
391 RestoreForMasterSlaver();
392 }
393 if (ret != NativeRdb::E_OK) {
394 ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
395 return NativeRdb::E_ERROR;
396 }
397 absSharedResultSet->Close();
398 return NativeRdb::E_OK;
399 }
400
QueryData(const std::string & key,std::vector<uint8_t> & values,const int32_t & userId)401 int32_t NotificationDataMgr::QueryData(const std::string &key, std::vector<uint8_t> &values, const int32_t &userId)
402 {
403 std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
404 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
405 if (rdbStore_ == nullptr) {
406 ANS_LOGE("notification rdb is null");
407 return NativeRdb::E_ERROR;
408 }
409 int32_t ret = NativeRdb::E_OK;
410 for (auto tableName : operatedTables) {
411 ret = QueryData(tableName, key, values);
412 if (ret != NativeRdb::E_EMPTY_VALUES_BUCKET) {
413 return ret;
414 }
415 }
416 return ret;
417 }
418
QueryData(const std::string tableName,const std::string key,std::vector<uint8_t> & value)419 int32_t NotificationDataMgr::QueryData(const std::string tableName, const std::string key, std::vector<uint8_t> &value)
420 {
421 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
422 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
423 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
424 if (absSharedResultSet == nullptr) {
425 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
426 return NativeRdb::E_ERROR;
427 }
428
429 int32_t ret = absSharedResultSet->GoToFirstRow();
430 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
431 RestoreForMasterSlaver();
432 }
433 if (ret != NativeRdb::E_OK) {
434 ANS_LOGW("GoToFirstRow failed from %{public}s table. It is empty!, key=%{public}s",
435 tableName.c_str(), key.c_str());
436 return NativeRdb::E_EMPTY_VALUES_BUCKET;
437 }
438 ret = absSharedResultSet->GetBlob(NOTIFICATION_VALUE_INDEX, value);
439 if (ret != NativeRdb::E_OK) {
440 ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
441 return NativeRdb::E_ERROR;
442 }
443 absSharedResultSet->Close();
444
445 return NativeRdb::E_OK;
446 }
447
QueryDataBeginWithKey(const std::string & key,std::unordered_map<std::string,std::string> & values,const int32_t & userId)448 int32_t NotificationDataMgr::QueryDataBeginWithKey(
449 const std::string &key, std::unordered_map<std::string, std::string> &values, const int32_t &userId)
450 {
451 ANS_LOGD("QueryData BeginWithKey start");
452 std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
453 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
454 if (rdbStore_ == nullptr) {
455 ANS_LOGE("notification rdb is null");
456 return NativeRdb::E_ERROR;
457 }
458 int32_t ret = NativeRdb::E_OK;
459 for (auto tableName : operatedTables) {
460 ret = QueryDataBeginWithKey(tableName, key, values);
461 if (ret == NativeRdb::E_ERROR) {
462 return ret;
463 }
464 }
465 if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && values.empty()) {
466 return NativeRdb::E_EMPTY_VALUES_BUCKET;
467 }
468 return NativeRdb::E_OK;
469 }
470
QueryDataBeginWithKey(const std::string tableName,const std::string key,std::unordered_map<std::string,std::string> & values)471 int32_t NotificationDataMgr::QueryDataBeginWithKey(
472 const std::string tableName, const std::string key, std::unordered_map<std::string, std::string> &values)
473 {
474 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
475 absRdbPredicates.BeginsWith(NOTIFICATION_KEY, key);
476 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
477 if (absSharedResultSet == nullptr) {
478 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
479 return NativeRdb::E_ERROR;
480 }
481
482 int32_t ret = absSharedResultSet->GoToFirstRow();
483 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
484 RestoreForMasterSlaver();
485 }
486 if (ret != NativeRdb::E_OK) {
487 ANS_LOGD("GoToFirstRow failed from %{public}s table.It is empty!, key=%{public}s",
488 tableName.c_str(), key.c_str());
489 return NativeRdb::E_EMPTY_VALUES_BUCKET;
490 }
491
492 do {
493 std::string resultKey;
494 ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
495 if (ret != NativeRdb::E_OK) {
496 ANS_LOGE("Failed to GetString key from %{public}s table.", tableName.c_str());
497 return NativeRdb::E_ERROR;
498 }
499
500 std::string resultValue;
501 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
502 if (ret != NativeRdb::E_OK) {
503 ANS_LOGE("GetString value failed from %{public}s table", tableName.c_str());
504 return NativeRdb::E_ERROR;
505 }
506
507 values.emplace(resultKey, resultValue);
508 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
509 absSharedResultSet->Close();
510
511 return NativeRdb::E_OK;
512 }
513
QueryAllData(std::unordered_map<std::string,std::string> & datas,const int32_t & userId)514 int32_t NotificationDataMgr::QueryAllData(std::unordered_map<std::string, std::string> &datas, const int32_t &userId)
515 {
516 ANS_LOGD("QueryAllData start");
517 std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
518 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
519 if (rdbStore_ == nullptr) {
520 ANS_LOGE("notification rdb is null");
521 return NativeRdb::E_ERROR;
522 }
523 int32_t ret = NativeRdb::E_OK;
524 for (auto tableName : operatedTables) {
525 ret = QueryAllData(tableName, datas);
526 if (ret == NativeRdb::E_ERROR) {
527 return ret;
528 }
529 }
530 if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && datas.empty()) {
531 return NativeRdb::E_EMPTY_VALUES_BUCKET;
532 }
533 return NativeRdb::E_OK;
534 }
535
QueryAllData(const std::string tableName,std::unordered_map<std::string,std::string> & datas)536 int32_t NotificationDataMgr::QueryAllData(
537 const std::string tableName, std::unordered_map<std::string, std::string> &datas)
538 {
539 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
540 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
541 if (absSharedResultSet == nullptr) {
542 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
543 return NativeRdb::E_ERROR;
544 }
545
546 int32_t ret = absSharedResultSet->GoToFirstRow();
547 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
548 RestoreForMasterSlaver();
549 }
550 if (ret != NativeRdb::E_OK) {
551 ANS_LOGD("GoToFirstRow failed from %{public}s table. It is empty!", tableName.c_str());
552 return NativeRdb::E_EMPTY_VALUES_BUCKET;
553 }
554
555 do {
556 std::string resultKey;
557 ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
558 if (ret != NativeRdb::E_OK) {
559 ANS_LOGE("GetString key failed from %{public}s table.", tableName.c_str());
560 return NativeRdb::E_ERROR;
561 }
562
563 std::string resultValue;
564 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
565 if (ret != NativeRdb::E_OK) {
566 ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
567 return NativeRdb::E_ERROR;
568 }
569
570 datas.emplace(resultKey, resultValue);
571 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
572 absSharedResultSet->Close();
573
574 return NativeRdb::E_OK;
575 }
576
DropUserTable(const int32_t userId)577 int32_t NotificationDataMgr::DropUserTable(const int32_t userId)
578 {
579 const char *keySpliter = "_";
580 std::stringstream stream;
581 stream << notificationRdbConfig_.tableName << keySpliter << userId;
582 std::string tableName = stream.str();
583 std::lock_guard<std::mutex> lock(createdTableMutex_);
584 int32_t ret = NativeRdb::E_OK;
585 {
586 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
587 if (rdbStore_ == nullptr) {
588 return NativeRdb::E_ERROR;
589 }
590 std::string dropTableSql = "DROP TABLE IF EXISTS " + tableName;
591 ret = rdbStore_->ExecuteSql(dropTableSql);
592 }
593 if (ret == NativeRdb::E_OK) {
594 createdTables_.erase(tableName);
595 ANS_LOGD("drop Table %{public}s succeed", tableName.c_str());
596 return ret;
597 }
598 return ret;
599 }
600
GetUserTableName(const int32_t & userId,std::string & tableName)601 int32_t NotificationDataMgr::GetUserTableName(const int32_t &userId, std::string &tableName)
602 {
603 if (!OsAccountManagerHelper::IsSystemAccount(userId)) {
604 tableName = notificationRdbConfig_.tableName;
605 return NativeRdb::E_OK;
606 }
607
608 const char *keySpliter = "_";
609 std::stringstream stream;
610 stream << notificationRdbConfig_.tableName << keySpliter << userId;
611 tableName = stream.str();
612 if (createdTables_.find(tableName) == createdTables_.end()) {
613 std::lock_guard<std::mutex> lock(createdTableMutex_);
614 if (createdTables_.find(tableName) == createdTables_.end()) {
615 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
616 if (rdbStore_ == nullptr) {
617 return NativeRdb::E_ERROR;
618 }
619 std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName
620 + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
621 int32_t ret = rdbStore_->ExecuteSql(createTableSql);
622 if (ret != NativeRdb::E_OK) {
623 ANS_LOGW("createTable %{public}s failed, code: %{public}d", tableName.c_str(), ret);
624 return ret;
625 }
626 createdTables_.insert(tableName);
627 ANS_LOGD("createTable %{public}s succeed", tableName.c_str());
628 return NativeRdb::E_OK;
629 }
630 }
631 return NativeRdb::E_OK;
632 }
633
GenerateOperatedTables(const int32_t & userId)634 std::vector<std::string> NotificationDataMgr::GenerateOperatedTables(const int32_t &userId)
635 {
636 std::vector<std::string> operatedTables;
637 if (OsAccountManagerHelper::IsSystemAccount(userId)) {
638 const char *keySpliter = "_";
639 std::stringstream stream;
640 stream << notificationRdbConfig_.tableName << keySpliter << userId;
641 std::string tableName = stream.str();
642 std::lock_guard<std::mutex> lock(createdTableMutex_);
643 if (createdTables_.find(tableName) != createdTables_.end()) {
644 operatedTables.emplace_back(tableName);
645 }
646 }
647 operatedTables.emplace_back(notificationRdbConfig_.tableName);
648 return operatedTables;
649 }
650
RestoreForMasterSlaver()651 int32_t NotificationDataMgr::RestoreForMasterSlaver()
652 {
653 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_1)
654 .ErrorCode(NativeRdb::E_SQLITE_CORRUPT).Message("Rdb is corruped.");
655 NotificationAnalyticsUtil::ReportModifyEvent(message);
656 ANS_LOGI("RestoreForMasterSlaver start");
657 int32_t result = rdbStore_->Restore("");
658 ANS_LOGI("RestoreForMasterSlaver result = %{public}d", result);
659 return result;
660 }
661 }
662 }