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<std::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<std::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 return NativeRdb::E_OK;
116 }
117
Destroy()118 int32_t DistributedRdbHelper::Destroy()
119 {
120 ANS_LOGD("Destory rdbStore");
121
122 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
123 if (rdbStore_ == nullptr) {
124 ANS_LOGE("notification rdb is null");
125 return NativeRdb::E_ERROR;
126 }
127 rdbStore_ = nullptr;
128 int32_t ret = NativeRdb::RdbHelper::DeleteRdbStore(notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName);
129 if (ret != NativeRdb::E_OK) {
130 ANS_LOGE("failed to destroy db store");
131 return NativeRdb::E_ERROR;
132 }
133 ANS_LOGD("destroy db store successfully");
134 return NativeRdb::E_OK;
135 }
136
InsertData(const std::string & key,const std::string & value)137 int32_t DistributedRdbHelper::InsertData(const std::string &key, const std::string &value)
138 {
139 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
140 if (rdbStore_ == nullptr) {
141 ANS_LOGE("notification rdb is null");
142 return NativeRdb::E_ERROR;
143 }
144 int64_t rowId = -1;
145 NativeRdb::ValuesBucket valuesBucket;
146 valuesBucket.PutString(NOTIFICATION_KEY, key);
147 valuesBucket.PutString(NOTIFICATION_VALUE, value);
148 int32_t ret = rdbStore_->InsertWithConflictResolution(rowId, notificationRdbConfig_.tableName,
149 valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
150 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
151 RestoreForMasterSlaver();
152 }
153 if (ret != NativeRdb::E_OK) {
154 ANS_LOGE("Insert operation failed, result: %{public}d, key=%{public}s.", ret, key.c_str());
155 return NativeRdb::E_ERROR;
156 }
157 return NativeRdb::E_OK;
158 }
159
InsertBatchData(const std::unordered_map<std::string,std::string> & values)160 int32_t DistributedRdbHelper::InsertBatchData(const std::unordered_map<std::string, std::string> &values)
161 {
162 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
163 if (rdbStore_ == nullptr) {
164 ANS_LOGE("notification rdb is null");
165 return NativeRdb::E_ERROR;
166 }
167 int64_t rowId = -1;
168 std::vector<NativeRdb::ValuesBucket> buckets;
169 for (auto &value : values) {
170 NativeRdb::ValuesBucket valuesBucket;
171 valuesBucket.PutString(NOTIFICATION_KEY, value.first);
172 valuesBucket.PutString(NOTIFICATION_VALUE, value.second);
173 buckets.emplace_back(valuesBucket);
174 }
175 int32_t ret = rdbStore_->BatchInsert(rowId, notificationRdbConfig_.tableName, buckets);
176 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
177 RestoreForMasterSlaver();
178 }
179 if (ret != NativeRdb::E_OK) {
180 ANS_LOGE("Insert batch operation failed, result: %{public}d.", ret);
181 return NativeRdb::E_ERROR;
182 }
183 return NativeRdb::E_OK;
184 }
185
DeleteData(const std::string & key)186 int32_t DistributedRdbHelper::DeleteData(const std::string &key)
187 {
188 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
189 if (rdbStore_ == nullptr) {
190 ANS_LOGE("notification rdb is null");
191 return NativeRdb::E_ERROR;
192 }
193 int32_t ret = NativeRdb::E_OK;
194 int32_t rowId = -1;
195 ret = DeleteData(notificationRdbConfig_.tableName, key, rowId);
196 if (ret != NativeRdb::E_OK) {
197 ANS_LOGE("Delete operation failed, result: %{public}d.", ret);
198 return NativeRdb::E_ERROR;
199 }
200 return NativeRdb::E_OK;
201 }
202
QueryData(const std::string & key,std::string & value)203 int32_t DistributedRdbHelper::QueryData(const std::string &key, std::string &value)
204 {
205 ANS_LOGD("QueryData start");
206 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
207 if (rdbStore_ == nullptr) {
208 ANS_LOGE("notification rdb is null");
209 return NativeRdb::E_ERROR;
210 }
211 int32_t ret = QueryData(notificationRdbConfig_.tableName, key, value);
212 if (ret != NativeRdb::E_OK) {
213 ANS_LOGE("Delete operation failed, result: %{public}d.", ret);
214 return NativeRdb::E_ERROR;
215 }
216 return NativeRdb::E_OK;
217 }
218
QueryDataBeginWithKey(const std::string & key,std::unordered_map<std::string,std::string> & values)219 int32_t DistributedRdbHelper::QueryDataBeginWithKey(
220 const std::string &key, std::unordered_map<std::string, std::string> &values)
221 {
222 ANS_LOGD("QueryData BeginWithKey start");
223 std::lock_guard<std::mutex> lock(rdbStorePtrMutex_);
224 if (rdbStore_ == nullptr) {
225 ANS_LOGE("notification rdb is null");
226 return NativeRdb::E_ERROR;
227 }
228 int32_t ret = QueryDataBeginWithKey(notificationRdbConfig_.tableName, key, values);
229 if (ret == NativeRdb::E_ERROR) {
230 return ret;
231 }
232 if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && values.empty()) {
233 ANS_LOGI("notification rdb is empty.");
234 return NativeRdb::E_EMPTY_VALUES_BUCKET;
235 }
236 return NativeRdb::E_OK;
237 }
238
QueryDataBeginWithKey(const std::string tableName,const std::string key,std::unordered_map<std::string,std::string> & values)239 int32_t DistributedRdbHelper::QueryDataBeginWithKey(
240 const std::string tableName, const std::string key, std::unordered_map<std::string, std::string> &values)
241 {
242 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
243 absRdbPredicates.BeginsWith(NOTIFICATION_KEY, key);
244 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
245 if (absSharedResultSet == nullptr) {
246 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
247 return NativeRdb::E_ERROR;
248 }
249
250 int32_t ret = absSharedResultSet->GoToFirstRow();
251 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
252 RestoreForMasterSlaver();
253 }
254 if (ret != NativeRdb::E_OK) {
255 ANS_LOGD("GoToFirstRow failed from %{public}s table.It is empty!, key=%{public}s",
256 tableName.c_str(), key.c_str());
257 return NativeRdb::E_EMPTY_VALUES_BUCKET;
258 }
259
260 do {
261 std::string resultKey;
262 ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
263 if (ret != NativeRdb::E_OK) {
264 ANS_LOGE("Failed to GetString key from %{public}s table.", tableName.c_str());
265 return NativeRdb::E_ERROR;
266 }
267
268 std::string resultValue;
269 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
270 if (ret != NativeRdb::E_OK) {
271 ANS_LOGE("GetString value failed from %{public}s table", tableName.c_str());
272 return NativeRdb::E_ERROR;
273 }
274 values.emplace(resultKey, resultValue);
275 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
276 absSharedResultSet->Close();
277 return NativeRdb::E_OK;
278 }
279
QueryData(const std::string tableName,const std::string key,std::string & value)280 int32_t DistributedRdbHelper::QueryData(const std::string tableName, const std::string key, std::string &value)
281 {
282 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
283 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
284 auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
285 if (absSharedResultSet == nullptr) {
286 ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
287 return NativeRdb::E_ERROR;
288 }
289
290 int32_t ret = absSharedResultSet->GoToFirstRow();
291 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
292 RestoreForMasterSlaver();
293 }
294 if (ret != NativeRdb::E_OK) {
295 ANS_LOGW("GoToFirstRow failed from %{public}s table. It is empty!, key=%{public}s",
296 tableName.c_str(), key.c_str());
297 return NativeRdb::E_EMPTY_VALUES_BUCKET;
298 }
299 ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, value);
300 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
301 RestoreForMasterSlaver();
302 }
303 if (ret != NativeRdb::E_OK) {
304 ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
305 return NativeRdb::E_ERROR;
306 }
307 absSharedResultSet->Close();
308 return NativeRdb::E_OK;
309 }
310
DeleteData(const std::string tableName,const std::string key,int32_t & rowId)311 int32_t DistributedRdbHelper::DeleteData(const std::string tableName, const std::string key, int32_t &rowId)
312 {
313 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
314 absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
315 int32_t ret = rdbStore_->Delete(rowId, absRdbPredicates);
316 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
317 RestoreForMasterSlaver();
318 }
319 if (ret != NativeRdb::E_OK) {
320 ANS_LOGW("Delete operation failed from %{public}s, result: %{public}d, key=%{public}s.",
321 tableName.c_str(), ret, key.c_str());
322 return NativeRdb::E_ERROR;
323 }
324 return NativeRdb::E_OK;
325 }
326
RestoreForMasterSlaver()327 int32_t DistributedRdbHelper::RestoreForMasterSlaver()
328 {
329 ANS_LOGI("RestoreForMasterSlaver start");
330 int32_t result = rdbStore_->Restore("");
331 ANS_LOGI("RestoreForMasterSlaver result = %{public}d", result);
332 return result;
333 }
334 }
335 }
336