1 /*
2 * Copyright (c) 2021-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 #include "account_data_storage.h"
16 #include <memory>
17 #include <unistd.h>
18 #include "account_log_wrapper.h"
19 #include "account_hisysevent_adapter.h"
20
21 namespace OHOS {
22 namespace AccountSA {
23 const int32_t MAX_TIMES = 10;
24 const int32_t SLEEP_INTERVAL = 100 * 1000;
25 constexpr char KV_STORE_EL1_BASE_DIR[] = "/data/service/el1/public/database/";
26
27 #ifndef SQLITE_DLCLOSE_ENABLE
AccountDataStorage(const std::string & appId,const std::string & storeId,const AccountDataStorageOptions & options)28 AccountDataStorage::AccountDataStorage(const std::string &appId, const std::string &storeId,
29 const AccountDataStorageOptions &options)
30 {
31 ACCOUNT_LOGI("Constructed");
32 appId_.appId = appId;
33 storeId_.storeId = storeId;
34 options_ = options;
35 if (options_.area == DistributedKv::EL1) {
36 baseDir_ = KV_STORE_EL1_BASE_DIR + appId;
37 } else {
38 baseDir_ = options.baseDir;
39 }
40 }
41 #else
AccountDataStorage(const std::string & appId,const std::string & storeId,const DbAdapterOptions & options)42 AccountDataStorage::AccountDataStorage(const std::string &appId, const std::string &storeId,
43 const DbAdapterOptions &options)
44 {
45 appId_ = appId;
46 storeId_ = storeId;
47 options_ = options;
48 dataManager_ = DatabaseAdapterLoader::GetInstance().GetDataManager();
49 if (options_.area == DbAdapterArea::EL1) {
50 baseDir_ = KV_STORE_EL1_BASE_DIR + appId;
51 } else {
52 baseDir_ = options.baseDir;
53 }
54 options_.baseDir = baseDir_;
55 }
56 #endif // SQLITE_DLCLOSE_ENABLE
57
~AccountDataStorage()58 AccountDataStorage::~AccountDataStorage()
59 {
60 ACCOUNT_LOGI("Destroyed");
61 if (kvStorePtr_ != nullptr) {
62 #ifndef SQLITE_DLCLOSE_ENABLE
63 dataManager_.CloseKvStore(appId_, kvStorePtr_);
64 #else
65 dataManager_->CloseKvStore(appId_, kvStorePtr_);
66 #endif // SQLITE_DLCLOSE_ENABLE
67 }
68 }
69
70 #ifndef SQLITE_DLCLOSE_ENABLE
TryTwice(const std::function<DistributedKv::Status ()> & func) const71 void AccountDataStorage::TryTwice(const std::function<DistributedKv::Status()> &func) const
72 {
73 OHOS::DistributedKv::Status status = func();
74 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
75 status = func();
76 ACCOUNT_LOGE("distribute database ipc error and try again, status = %{public}d", status);
77 }
78 }
79 #else
TryTwice(const std::function<DbAdapterStatus ()> & func) const80 void AccountDataStorage::TryTwice(const std::function<DbAdapterStatus()> &func) const
81 {
82 DbAdapterStatus status = func();
83 if (status == DbAdapterStatus::IPC_ERROR) {
84 status = func();
85 ACCOUNT_LOGE("distribute database ipc error and try again, status = %{public}d", status);
86 }
87 }
88 #endif // SQLITE_DLCLOSE_ENABLE
89
90 #ifndef SQLITE_DLCLOSE_ENABLE
GetKvStore()91 OHOS::DistributedKv::Status AccountDataStorage::GetKvStore()
92 {
93 OHOS::DistributedKv::Options options = {
94 .createIfMissing = true,
95 .encrypt = options_.encrypt,
96 .autoSync = options_.autoSync,
97 .syncable = options_.autoSync,
98 .securityLevel = options_.securityLevel,
99 .area = options_.area,
100 .kvStoreType = OHOS::DistributedKv::KvStoreType::SINGLE_VERSION,
101 .baseDir = baseDir_,
102 };
103
104 OHOS::DistributedKv::Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
105 if (status != OHOS::DistributedKv::Status::SUCCESS || kvStorePtr_ == nullptr) {
106 #else
107 DbAdapterStatus AccountDataStorage::GetKvStore()
108 {
109 DbAdapterStatus status = dataManager_->GetSingleKvStore(options_, appId_, storeId_, kvStorePtr_);
110 if (status != DbAdapterStatus::SUCCESS || kvStorePtr_ == nullptr) {
111 #endif // SQLITE_DLCLOSE_ENABLE
112 ACCOUNT_LOGE("GetSingleKvStore failed! status %{public}d, kvStorePtr_ is nullptr", status);
113 return status;
114 }
115 return status;
116 }
117
118 bool AccountDataStorage::CheckKvStore()
119 {
120 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
121
122 if (kvStorePtr_ != nullptr) {
123 return true;
124 }
125 int32_t tryTimes = MAX_TIMES;
126 #ifndef SQLITE_DLCLOSE_ENABLE
127 OHOS::DistributedKv::Status status = OHOS::DistributedKv::Status::SUCCESS;
128 #else
129 DbAdapterStatus status = DbAdapterStatus::SUCCESS;
130 #endif // SQLITE_DLCLOSE_ENABLE
131 while (tryTimes > 0) {
132 status = GetKvStore();
133 #ifndef SQLITE_DLCLOSE_ENABLE
134 if (status == OHOS::DistributedKv::Status::SUCCESS && kvStorePtr_ != nullptr) {
135 break;
136 }
137 #else
138 if (status == DbAdapterStatus::SUCCESS && kvStorePtr_ != nullptr) {
139 break;
140 }
141 #endif // SQLITE_DLCLOSE_ENABLE
142
143 usleep(SLEEP_INTERVAL);
144 tryTimes--;
145 }
146
147 if (kvStorePtr_ == nullptr) {
148 return false;
149 }
150
151 return true;
152 }
153
154 ErrCode AccountDataStorage::LoadAllData(std::map<std::string, std::shared_ptr<IAccountInfo>> &infos)
155 {
156 if (!CheckKvStore()) {
157 ACCOUNT_LOGE("kvStore is nullptr");
158 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
159 }
160 #ifndef SQLITE_DLCLOSE_ENABLE
161 OHOS::DistributedKv::Status status = DistributedKv::Status::SUCCESS;
162 std::vector<OHOS::DistributedKv::Entry> allEntries;
163 TryTwice([this, &status, &allEntries] {
164 status = GetEntries("", allEntries);
165 return status;
166 });
167
168 if (status != OHOS::DistributedKv::Status::SUCCESS) {
169 #else
170 DbAdapterStatus status = DbAdapterStatus::SUCCESS;
171 std::vector<DbAdapterEntry> allEntries;
172 TryTwice([this, &status, &allEntries] {
173 status = GetEntries("", allEntries);
174 return status;
175 });
176
177 if (status != DbAdapterStatus::SUCCESS) {
178 #endif // SQLITE_DLCLOSE_ENABLE
179 ACCOUNT_LOGE("get entries error: %{public}d", status);
180 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
181 }
182 infos.clear();
183 SaveEntries(allEntries, infos);
184 return ERR_OK;
185 }
186
187 ErrCode AccountDataStorage::AddAccountInfo(const IAccountInfo &iAccountInfo)
188 {
189 if (IsKeyExists(iAccountInfo.GetPrimeKey())) {
190 ACCOUNT_LOGE("the key already exists.");
191 return ERR_OSACCOUNT_SERVICE_DATA_STORAGE_KEY_EXISTED_ERROR;
192 }
193
194 std::string accountInfoStr = iAccountInfo.ToString();
195 if (accountInfoStr.empty()) {
196 ACCOUNT_LOGE("account info str is empty!");
197 return ERR_OSACCOUNT_SERVICE_ACCOUNT_INFO_EMPTY_ERROR;
198 }
199 return PutValueToKvStore(iAccountInfo.GetPrimeKey(), accountInfoStr);
200 }
201
202 ErrCode AccountDataStorage::SaveAccountInfo(const IAccountInfo &iAccountInfo)
203 {
204 if (!IsKeyExists(iAccountInfo.GetPrimeKey())) {
205 ACCOUNT_LOGE("the key does not exist");
206 return ERR_OSACCOUNT_SERVICE_DATA_STORAGE_KEY_NOT_EXISTS_ERROR;
207 }
208
209 std::string accountInfoStr = iAccountInfo.ToString();
210 if (accountInfoStr.empty()) {
211 ACCOUNT_LOGE("account info str is empty!");
212 return ERR_OSACCOUNT_SERVICE_ACCOUNT_INFO_EMPTY_ERROR;
213 }
214 return PutValueToKvStore(iAccountInfo.GetPrimeKey(), accountInfoStr);
215 }
216
217 #ifndef SQLITE_DLCLOSE_ENABLE
218 ErrCode AccountDataStorage::RemoveValueFromKvStore(const std::string &keyStr)
219 {
220 if (!CheckKvStore()) {
221 ACCOUNT_LOGE("kvStore is nullptr");
222 return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
223 }
224
225 OHOS::DistributedKv::Key key(keyStr);
226 OHOS::DistributedKv::Status status;
227 OHOS::DistributedKv::Value value;
228 {
229 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
230 // check exist
231 status = kvStorePtr_->Get(key, value);
232 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
233 ACCOUNT_LOGE("kvstore ipc error and try again, status = %{public}d", status);
234 status = kvStorePtr_->Get(key, value);
235 }
236 if (status != OHOS::DistributedKv::Status::SUCCESS) {
237 ACCOUNT_LOGI("key does not exist in kvStore.");
238 return ERR_OK;
239 }
240
241 // delete
242 status = kvStorePtr_->Delete(key);
243 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
244 status = kvStorePtr_->Delete(key);
245 ACCOUNT_LOGE("kvstore ipc error and try to call again, status = %{public}d", status);
246 }
247 }
248
249 if (status != OHOS::DistributedKv::Status::SUCCESS) {
250 ACCOUNT_LOGE("delete key from kvstore failed, status %{public}d.", status);
251 return ERR_ACCOUNT_COMMON_DELETE_KEY_FROM_KVSTORE_ERROR;
252 }
253
254 ACCOUNT_LOGD("delete key from kvStore succeed!");
255 return ERR_OK;
256 }
257 #else
258 ErrCode AccountDataStorage::RemoveValueFromKvStore(const std::string &keyStr)
259 {
260 if (!CheckKvStore()) {
261 ACCOUNT_LOGE("kvStore is nullptr");
262 return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
263 }
264
265 DbAdapterStatus status;
266 std::string value;
267 {
268 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
269 // check exist
270 status = kvStorePtr_->Get(keyStr, value);
271 if (status == DbAdapterStatus::IPC_ERROR) {
272 ACCOUNT_LOGE("kvstore ipc error and try again, status = %{public}d", status);
273 status = kvStorePtr_->Get(keyStr, value);
274 }
275 if (status != DbAdapterStatus::SUCCESS) {
276 ACCOUNT_LOGI("key does not exist in kvStore.");
277 return ERR_OK;
278 }
279
280 // delete
281 status = kvStorePtr_->Delete(keyStr);
282 if (status == DbAdapterStatus::IPC_ERROR) {
283 status = kvStorePtr_->Delete(keyStr);
284 ACCOUNT_LOGE("kvstore ipc error and try to call again, status = %{public}d", status);
285 }
286 }
287
288 if (status != DbAdapterStatus::SUCCESS) {
289 ACCOUNT_LOGE("delete key from kvstore failed, status %{public}d.", status);
290 return ERR_ACCOUNT_COMMON_DELETE_KEY_FROM_KVSTORE_ERROR;
291 }
292
293 ACCOUNT_LOGD("delete key from kvStore succeed!");
294 return ERR_OK;
295 }
296 #endif // SQLITE_DLCLOSE_ENABLE
297
298 #ifndef SQLITE_DLCLOSE_ENABLE
299 OHOS::DistributedKv::Status AccountDataStorage::GetEntries(
300 std::string subId, std::vector<OHOS::DistributedKv::Entry> &allEntries) const
301 {
302 OHOS::DistributedKv::Key allEntryKeyPrefix(subId);
303 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
304 OHOS::DistributedKv::Status status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
305
306 return status;
307 }
308 #else
309 DbAdapterStatus AccountDataStorage::GetEntries(
310 std::string subId, std::vector<DbAdapterEntry> &allEntries) const
311 {
312 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
313 DbAdapterStatus status = kvStorePtr_->GetEntries(subId, allEntries);
314
315 return status;
316 }
317 #endif // SQLITE_DLCLOSE_ENABLE
318
319 ErrCode AccountDataStorage::Close()
320 {
321 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
322 #ifndef SQLITE_DLCLOSE_ENABLE
323 ErrCode errCode = dataManager_.CloseKvStore(appId_, kvStorePtr_);
324 #else
325 ErrCode errCode = dataManager_->CloseKvStore(appId_, kvStorePtr_);
326 #endif // SQLITE_DLCLOSE_ENABLE
327 kvStorePtr_ = nullptr;
328 return errCode;
329 }
330
331 ErrCode AccountDataStorage::DeleteKvStore()
332 {
333 #ifndef SQLITE_DLCLOSE_ENABLE
334 if (!CheckKvStore()) {
335 ACCOUNT_LOGE("kvStore is nullptr");
336 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
337 }
338
339 OHOS::DistributedKv::Status status;
340 {
341 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
342 dataManager_.CloseKvStore(this->appId_, this->storeId_);
343 status = dataManager_.DeleteKvStore(this->appId_, this->storeId_, baseDir_);
344 }
345 if (status != OHOS::DistributedKv::Status::SUCCESS) {
346 ACCOUNT_LOGE("error, status = %{public}d", status);
347 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
348 }
349 #else
350 ACCOUNT_LOGI("DeleteKvStore not enabled.");
351 #endif // SQLITE_DLCLOSE_ENABLE
352 return ERR_OK;
353 }
354
355 ErrCode AccountDataStorage::GetAccountInfoById(const std::string id, IAccountInfo &iAccountInfo)
356 {
357 std::string valueStr;
358 ErrCode ret = GetValueFromKvStore(id, valueStr);
359 if (ret != ERR_OK) {
360 ACCOUNT_LOGE("get value from kvstore failed! id %{public}s.", id.c_str());
361 return ret;
362 }
363
364 nlohmann::json jsonObject = nlohmann::json::parse(valueStr, nullptr, false);
365 if (jsonObject.is_discarded() || !jsonObject.is_structured()) { // check format
366 ACCOUNT_LOGE("bad format of value from kvstore! id %{public}s.", id.c_str());
367 return ERR_ACCOUNT_COMMON_BAD_JSON_FORMAT_ERROR;
368 }
369 iAccountInfo.FromJson(jsonObject);
370 return ERR_OK;
371 }
372
373 ErrCode AccountDataStorage::LoadDataByLocalFuzzyQuery(
374 std::string subId, std::map<std::string, std::shared_ptr<IAccountInfo>> &infos)
375 {
376 if (!CheckKvStore()) {
377 ACCOUNT_LOGE("kvStore is nullptr");
378 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
379 }
380 #ifndef SQLITE_DLCLOSE_ENABLE
381 OHOS::DistributedKv::Status status = OHOS::DistributedKv::Status::SUCCESS;
382 std::vector<OHOS::DistributedKv::Entry> allEntries;
383 #else
384 DbAdapterStatus status = DbAdapterStatus::SUCCESS;
385 std::vector<DbAdapterEntry> allEntries;
386 #endif // SQLITE_DLCLOSE_ENABLE
387 TryTwice([this, &status, &allEntries, subId] {
388 status = GetEntries(subId, allEntries);
389 return status;
390 });
391 #ifndef SQLITE_DLCLOSE_ENABLE
392 if (status != OHOS::DistributedKv::Status::SUCCESS) {
393 #else
394 if (status != DbAdapterStatus::SUCCESS) {
395 #endif // SQLITE_DLCLOSE_ENABLE
396 ACCOUNT_LOGE("get entries error: %{public}d", status);
397 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
398 }
399 infos.clear();
400 SaveEntries(allEntries, infos);
401 return ERR_OK;
402 }
403
404 ErrCode AccountDataStorage::PutValueToKvStore(const std::string &keyStr, const std::string &valueStr)
405 {
406 if (!CheckKvStore()) {
407 ACCOUNT_LOGE("kvStore is nullptr");
408 return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
409 }
410 #ifndef SQLITE_DLCLOSE_ENABLE
411 OHOS::DistributedKv::Key key(keyStr);
412 OHOS::DistributedKv::Value value(valueStr);
413 OHOS::DistributedKv::Status status;
414
415 {
416 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
417 status = kvStorePtr_->Put(key, value);
418 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
419 status = kvStorePtr_->Put(key, value);
420 }
421 }
422
423 if (status != OHOS::DistributedKv::Status::SUCCESS) {
424 #else
425 DbAdapterStatus status = DbAdapterStatus::SUCCESS;
426 {
427 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
428 status = kvStorePtr_->Put(keyStr, valueStr);
429 if (status == DbAdapterStatus::IPC_ERROR) {
430 status = kvStorePtr_->Put(keyStr, valueStr);
431 }
432 }
433
434 if (status != DbAdapterStatus::SUCCESS) {
435 #endif // SQLITE_DLCLOSE_ENABLE
436 ACCOUNT_LOGE("put value to kvStore error, status = %{public}d", status);
437 return OHOS::ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
438 }
439
440 return ERR_OK;
441 }
442
443 ErrCode AccountDataStorage::GetValueFromKvStore(const std::string &keyStr, std::string &valueStr)
444 {
445 if (!CheckKvStore()) {
446 ACCOUNT_LOGE("kvStore is nullptr");
447 return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
448 }
449 #ifndef SQLITE_DLCLOSE_ENABLE
450 OHOS::DistributedKv::Key key(keyStr);
451 OHOS::DistributedKv::Value value;
452 OHOS::DistributedKv::Status status;
453
454 {
455 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
456 status = kvStorePtr_->Get(key, value);
457 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
458 ACCOUNT_LOGE("kvstore ipc error and try again, status = %{public}d", status);
459 status = kvStorePtr_->Get(key, value);
460 }
461 }
462
463 if (status != OHOS::DistributedKv::Status::SUCCESS) {
464 #else
465 DbAdapterStatus status;
466
467 {
468 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
469 status = kvStorePtr_->Get(keyStr, valueStr);
470 if (status == DbAdapterStatus::IPC_ERROR) {
471 ACCOUNT_LOGE("kvstore ipc error and try again, status = %{public}d", status);
472 status = kvStorePtr_->Get(keyStr, valueStr);
473 }
474 }
475
476 if (status != DbAdapterStatus::SUCCESS) {
477 #endif // SQLITE_DLCLOSE_ENABLE
478 ACCOUNT_LOGE("get value from kvstore error, status %{public}d.", status);
479 return ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
480 }
481 #ifndef SQLITE_DLCLOSE_ENABLE
482 valueStr = value.ToString();
483 #endif
484 return ERR_OK;
485 }
486
487 bool AccountDataStorage::IsKeyExists(const std::string keyStr)
488 {
489 std::string valueStr;
490 if (GetValueFromKvStore(keyStr, valueStr) != ERR_OK) {
491 return false;
492 }
493 return true;
494 }
495
496 ErrCode AccountDataStorage::MoveData(const std::shared_ptr<AccountDataStorage> &ptr)
497 {
498 #ifndef SQLITE_DLCLOSE_ENABLE
499 if (ptr == nullptr || !ptr->CheckKvStore() || !CheckKvStore()) {
500 ACCOUNT_LOGE("AccountDataStorage is nullptr");
501 return ERR_ACCOUNT_COMMON_CHECK_KVSTORE_ERROR;
502 }
503 std::vector<OHOS::DistributedKv::Entry> entries;
504 OHOS::DistributedKv::Status status = ptr->GetEntries("", entries);
505 if (status != OHOS::DistributedKv::Status::SUCCESS) {
506 ACCOUNT_LOGE("GetEntries failed, result=%{public}u", status);
507 return ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
508 }
509 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
510 status = kvStorePtr_->PutBatch(entries);
511 if (status != OHOS::DistributedKv::Status::SUCCESS) {
512 ACCOUNT_LOGE("PutBatch failed, result=%{public}u", status);
513 return ERR_OSACCOUNT_SERVICE_MANAGER_QUERY_DISTRIBUTE_DATA_ERROR;
514 }
515 #else
516 ACCOUNT_LOGI("MoveData not enabled.");
517 #endif
518 return ERR_OK;
519 }
520 } // namespace AccountSA
521 } // namespace OHOS
522