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 "distributed_rdb_helper.h"
16
17 #include "ans_log_wrapper.h"
18 namespace OHOS {
19 namespace Notification {
20
21 namespace {
22 const std::string NOTIFICATION_KEY = "KEY";
23 const std::string NOTIFICATION_VALUE = "VALUE";
24 const int32_t NOTIFICATION_KEY_INDEX = 0;
25 const int32_t NOTIFICATION_VALUE_INDEX = 1;
26 } // namespace
27
RdbCallBack(const DistributedRdbConfig & notificationRdbConfig)28 RdbCallBack::RdbCallBack(const DistributedRdbConfig ¬ificationRdbConfig)
29 : notificationRdbConfig_(notificationRdbConfig)
30 {
31 ANS_LOGD("create rdb store callback instance");
32 }
33
~RdbCallBack()34 RdbCallBack::~RdbCallBack()
35 {
36 ANS_LOGD("destroy rdb store callback instance");
37 }
38
OnCreate(NativeRdb::RdbStore & rdbStore)39 int32_t RdbCallBack::OnCreate(NativeRdb::RdbStore &rdbStore)
40 {
41 ANS_LOGD("OnCreate");
42 int ret = NativeRdb::E_OK;
43 if (hasTableInit_) {
44 return ret;
45 }
46 std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + notificationRdbConfig_.tableName
47 + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
48 ret = rdbStore.ExecuteSql(createTableSql);
49 if (ret == NativeRdb::E_OK) {
50 hasTableInit_ = true;
51 ANS_LOGD("createTable succeed");
52 }
53 return ret;
54 }
55
OnUpgrade(NativeRdb::RdbStore & rdbStore,int32_t oldVersion,int32_t newVersion)56 int32_t RdbCallBack::OnUpgrade(NativeRdb::RdbStore &rdbStore, int32_t oldVersion, int32_t newVersion)
57 {
58 ANS_LOGD("OnUpgrade currentVersion: %{public}d, targetVersion: %{public}d",
59 oldVersion, newVersion);
60 return NativeRdb::E_OK;
61 }
62
OnDowngrade(NativeRdb::RdbStore & rdbStore,int currentVersion,int targetVersion)63 int32_t RdbCallBack::OnDowngrade(NativeRdb::RdbStore &rdbStore, int currentVersion, int targetVersion)
64 {
65 ANS_LOGD("OnDowngrade currentVersion: %{public}d, targetVersion: %{public}d",
66 currentVersion, targetVersion);
67 return NativeRdb::E_OK;
68 }
69
OnOpen(NativeRdb::RdbStore & rdbStore)70 int32_t RdbCallBack::OnOpen(NativeRdb::RdbStore &rdbStore)
71 {
72 ANS_LOGD("OnOpen");
73 return NativeRdb::E_OK;
74 }
75
onCorruption(std::string databaseFile)76 int32_t RdbCallBack::onCorruption(std::string databaseFile)
77 {
78 return NativeRdb::E_OK;
79 }
80
DistributedRdbHelper(const DistributedRdbConfig & notificationRdbConfig)81 DistributedRdbHelper::DistributedRdbHelper(const DistributedRdbConfig ¬ificationRdbConfig)
82 : notificationRdbConfig_(notificationRdbConfig)
83 {
84 ANS_LOGD("create notification rdb data manager");
85 }
86
Init()87 int32_t DistributedRdbHelper::Init()
88 {
89 ANS_LOGD("Create rdbStore");
90 {
91 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
92 if (rdbStore_ != nullptr) {
93 ANS_LOGD("notification rdb has existed");
94 return NativeRdb::E_OK;
95 }
96 }
97 NativeRdb::RdbStoreConfig config(
98 notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName,
99 NativeRdb::StorageMode::MODE_DISK,
100 false,
101 std::vector<uint8_t>(),
102 notificationRdbConfig_.journalMode,
103 notificationRdbConfig_.syncMode);
104 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
105 config.SetHaMode(NativeRdb::HAMode::MAIN_REPLICA);
106 RdbCallBack rdbDataCallBack_(notificationRdbConfig_);
107 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
108 int32_t ret = NativeRdb::E_OK;
109 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, notificationRdbConfig_.version,
110 rdbDataCallBack_, ret);
111 if (rdbStore_ == nullptr) {
112 ANS_LOGE("notification rdb init fail");
113 return NativeRdb::E_ERROR;
114 }
115 ANS_LOGI("Create rdbStore successfully");
116 return NativeRdb::E_OK;
117 }
118
Destroy()119 int32_t DistributedRdbHelper::Destroy()
120 {
121 ANS_LOGD("Destory rdbStore");
122
123 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
124 if (rdbStore_ == nullptr) {
125 ANS_LOGE("notification rdb is null");
126 return NativeRdb::E_ERROR;
127 }
128 rdbStore_ = nullptr;
129 int32_t ret = NativeRdb::RdbHelper::DeleteRdbStore(notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName);
130 if (ret != NativeRdb::E_OK) {
131 ANS_LOGE("failed to destroy db store");
132 return NativeRdb::E_ERROR;
133 }
134 ANS_LOGI("destroy db store successfully");
135 return NativeRdb::E_OK;
136 }
137
InsertData(const std::string & key,const std::string & value)138 int32_t DistributedRdbHelper::InsertData(const std::string &key, const std::string &value)
139 {
140 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
141 if (rdbStore_ == nullptr) {
142 ANS_LOGE("notification rdb is null");
143 return NativeRdb::E_ERROR;
144 }
145 int64_t rowId = -1;
146 NativeRdb::ValuesBucket valuesBucket;
147 valuesBucket.PutString(NOTIFICATION_KEY, key);
148 valuesBucket.PutString(NOTIFICATION_VALUE, value);
149 int32_t ret = rdbStore_->InsertWithConflictResolution(rowId, notificationRdbConfig_.tableName,
150 valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
151 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
152 RestoreForMasterSlaver();
153 }
154 if (ret != NativeRdb::E_OK) {
155 ANS_LOGE("Insert operation failed, result: %{public}d, key=%{public}s.", ret, key.c_str());
156 return NativeRdb::E_ERROR;
157 }
158 return NativeRdb::E_OK;
159 }
160
InsertBatchData(const std::unordered_map<std::string,std::string> & values)161 int32_t DistributedRdbHelper::InsertBatchData(const std::unordered_map<std::string, std::string> &values)
162 {
163 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
164 if (rdbStore_ == nullptr) {
165 ANS_LOGE("notification rdb is null");
166 return NativeRdb::E_ERROR;
167 }
168 int64_t rowId = -1;
169 std::vector<NativeRdb::ValuesBucket> buckets;
170 for (auto &value : values) {
171 NativeRdb::ValuesBucket valuesBucket;
172 valuesBucket.PutString(NOTIFICATION_KEY, value.first);
173 valuesBucket.PutString(NOTIFICATION_VALUE, value.second);
174 buckets.emplace_back(valuesBucket);
175 }
176 int32_t ret = rdbStore_->BatchInsert(rowId, notificationRdbConfig_.tableName, buckets);
177 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
178 RestoreForMasterSlaver();
179 }
180 if (ret != NativeRdb::E_OK) {
181 ANS_LOGE("Insert batch operation failed, result: %{public}d.", ret);
182 return NativeRdb::E_ERROR;
183 }
184 return NativeRdb::E_OK;
185 }
186
DeleteData(const std::string & key)187 int32_t DistributedRdbHelper::DeleteData(const std::string &key)
188 {
189 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
190 if (rdbStore_ == nullptr) {
191 ANS_LOGE("notification rdb is null");
192 return NativeRdb::E_ERROR;
193 }
194 int32_t ret = NativeRdb::E_OK;
195 int32_t rowId = -1;
196 ret = DeleteData(notificationRdbConfig_.tableName, key, rowId);
197 if (ret != NativeRdb::E_OK) {
198 ANS_LOGE("Delete operation failed, result: %{public}d.", ret);
199 return NativeRdb::E_ERROR;
200 }
201 return NativeRdb::E_OK;
202 }
203
QueryData(const std::string & key,std::string & value)204 int32_t DistributedRdbHelper::QueryData(const std::string &key, std::string &value)
205 {
206 ANS_LOGD("QueryData start");
207 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
208 if (rdbStore_ == nullptr) {
209 ANS_LOGE("notification rdb is null");
210 return NativeRdb::E_ERROR;
211 }
212 int32_t ret = QueryData(notificationRdbConfig_.tableName, key, value);
213 if (ret != NativeRdb::E_OK) {
214 ANS_LOGE("Delete operation failed, result: %{public}d.", ret);
215 return NativeRdb::E_ERROR;
216 }
217 return NativeRdb::E_OK;
218 }
219
QueryDataBeginWithKey(const std::string & key,std::unordered_map<std::string,std::string> & values)220 int32_t DistributedRdbHelper::QueryDataBeginWithKey(
221 const std::string &key, std::unordered_map<std::string, std::string> &values)
222 {
223 ANS_LOGD("QueryData BeginWithKey start");
224 std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
225 if (rdbStore_ == nullptr) {
226 ANS_LOGE("notification rdb is null");
227 return NativeRdb::E_ERROR;
228 }
229 int32_t ret = QueryDataBeginWithKey(notificationRdbConfig_.tableName, key, values);
230 if (ret == NativeRdb::E_ERROR) {
231 return ret;
232 }
233 if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && values.empty()) {
234 ANS_LOGI("notification rdb is empty.");
235 return NativeRdb::E_EMPTY_VALUES_BUCKET;
236 }
237 return NativeRdb::E_OK;
238 }
239
QueryDataBeginWithKey(const std::string tableName,const std::string key,std::unordered_map<std::string,std::string> & values)240 int32_t DistributedRdbHelper::QueryDataBeginWithKey(
241 const std::string tableName, const std::string key, std::unordered_map<std::string, std::string> &values)
242 {
243 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
244 absRdbPredicates.BeginsWith(NOTIFICATION_KEY, key);
245 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
246 if (absSharedResultSet == nullptr) {
247 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
248 return NativeRdb::E_ERROR;
249 }
250
251 int32_t ret = absSharedResultSet->GoToFirstRow();
252 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
253 RestoreForMasterSlaver();
254 }
255 if (ret != NativeRdb::E_OK) {
256 ANS_LOGD("GoToFirstRow failed from %{public}s table.It is empty!, key=%{public}s",
257 tableName.c_str(), key.c_str());
258 absSharedResultSet->Close();
259 return NativeRdb::E_EMPTY_VALUES_BUCKET;
260 }
261
262 do {
263 std::string resultKey;
264 ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
265 if (ret != NativeRdb::E_OK) {
266 ANS_LOGE("Failed to GetString key from %{public}s table.", tableName.c_str());
267 absSharedResultSet->Close();
268 return NativeRdb::E_ERROR;
269 }
270
271 std::string resultValue;
272 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
273 if (ret != NativeRdb::E_OK) {
274 ANS_LOGE("GetString value failed from %{public}s table", tableName.c_str());
275 absSharedResultSet->Close();
276 return NativeRdb::E_ERROR;
277 }
278 values.emplace(resultKey, resultValue);
279 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
280 absSharedResultSet->Close();
281 return NativeRdb::E_OK;
282 }
283
QueryData(const std::string tableName,const std::string key,std::string & value)284 int32_t DistributedRdbHelper::QueryData(const std::string tableName, const std::string key, std::string &value)
285 {
286 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
287 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
288 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
289 if (absSharedResultSet == nullptr) {
290 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
291 return NativeRdb::E_ERROR;
292 }
293
294 int32_t ret = absSharedResultSet->GoToFirstRow();
295 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
296 RestoreForMasterSlaver();
297 }
298 if (ret != NativeRdb::E_OK) {
299 ANS_LOGW("GoToFirstRow failed from %{public}s table. It is empty!, key=%{public}s",
300 tableName.c_str(), key.c_str());
301 absSharedResultSet->Close();
302 return NativeRdb::E_EMPTY_VALUES_BUCKET;
303 }
304 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, value);
305 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
306 RestoreForMasterSlaver();
307 }
308 if (ret != NativeRdb::E_OK) {
309 ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
310 absSharedResultSet->Close();
311 return NativeRdb::E_ERROR;
312 }
313 absSharedResultSet->Close();
314 return NativeRdb::E_OK;
315 }
316
DeleteData(const std::string tableName,const std::string key,int32_t & rowId)317 int32_t DistributedRdbHelper::DeleteData(const std::string tableName, const std::string key, int32_t &rowId)
318 {
319 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
320 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
321 int32_t ret = rdbStore_->Delete(rowId, absRdbPredicates);
322 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
323 RestoreForMasterSlaver();
324 }
325 if (ret != NativeRdb::E_OK) {
326 ANS_LOGW("Delete operation failed from %{public}s, result: %{public}d, key=%{public}s.",
327 tableName.c_str(), ret, key.c_str());
328 return NativeRdb::E_ERROR;
329 }
330 return NativeRdb::E_OK;
331 }
332
RestoreForMasterSlaver()333 int32_t DistributedRdbHelper::RestoreForMasterSlaver()
334 {
335 ANS_LOGI("RestoreForMasterSlaver start");
336 int32_t result = rdbStore_->Restore("");
337 ANS_LOGI("RestoreForMasterSlaver result = %{public}d", result);
338 return result;
339 }
340 }
341 }
342