1 /*
2 * Copyright (c) 2021 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 #define LOG_TAG "KvStoreAppManager"
17
18 #include "kvstore_app_manager.h"
19
20 #include <directory_ex.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include <thread>
26
27 #include "account_delegate.h"
28 #include "broadcast_sender.h"
29 #include "checker/checker_manager.h"
30 #include "constant.h"
31 #include "device_kvstore_impl.h"
32 #include "directory_utils.h"
33 #include "ikvstore.h"
34 #include "kv_store_delegate.h"
35 #include "kvstore_app_accessor.h"
36 #include "kvstore_utils.h"
37 #include "log_print.h"
38 #include "permission_validator.h"
39 #include "reporter.h"
40 #include "route_head_handler_impl.h"
41 #include "types.h"
42
43 namespace OHOS {
44 namespace DistributedKv {
45 using namespace OHOS::DistributedData;
KvStoreAppManager(const std::string & bundleName,pid_t uid)46 KvStoreAppManager::KvStoreAppManager(const std::string &bundleName, pid_t uid)
47 : bundleName_(bundleName), uid_(uid), flowCtrl_(BURST_CAPACITY, SUSTAINED_CAPACITY)
48 {
49 ZLOGI("begin.");
50 deviceAccountId_ = AccountDelegate::GetInstance()->GetDeviceAccountIdByUID(uid);
51 GetDelegateManager(PATH_DE);
52 GetDelegateManager(PATH_CE);
53 }
54
~KvStoreAppManager()55 KvStoreAppManager::~KvStoreAppManager()
56 {
57 ZLOGD("begin.");
58 stores_[PATH_DE].clear();
59 stores_[PATH_CE].clear();
60
61 {
62 std::lock_guard<std::mutex> guard(delegateMutex_);
63 delete delegateManagers_[PATH_DE];
64 delete delegateManagers_[PATH_CE];
65 delegateManagers_[PATH_DE] = nullptr;
66 delegateManagers_[PATH_CE] = nullptr;
67 }
68 }
69
ConvertErrorStatus(DistributedDB::DBStatus dbStatus,bool createIfMissing)70 Status KvStoreAppManager::ConvertErrorStatus(DistributedDB::DBStatus dbStatus, bool createIfMissing)
71 {
72 if (dbStatus != DistributedDB::DBStatus::OK) {
73 ZLOGE("delegate return error: %d.", static_cast<int>(dbStatus));
74 switch (dbStatus) {
75 case DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB:
76 return Status::CRYPT_ERROR;
77 case DistributedDB::DBStatus::SCHEMA_MISMATCH:
78 return Status::SCHEMA_MISMATCH;
79 case DistributedDB::DBStatus::INVALID_SCHEMA:
80 return Status::INVALID_SCHEMA;
81 case DistributedDB::DBStatus::NOT_SUPPORT:
82 return Status::NOT_SUPPORT;
83 case DistributedDB::DBStatus::EKEYREVOKED_ERROR: // fallthrough
84 case DistributedDB::DBStatus::SECURITY_OPTION_CHECK_ERROR:
85 return Status::SECURITY_LEVEL_ERROR;
86 default:
87 break;
88 }
89 if (createIfMissing) {
90 return Status::DB_ERROR;
91 } else {
92 return Status::STORE_NOT_FOUND;
93 }
94 }
95 return Status::SUCCESS;
96 }
97
GetKvStore(const Options & options,const std::string & appId,const std::string & storeId,const std::vector<uint8_t> & cipherKey,sptr<KvStoreImpl> & kvStore)98 Status KvStoreAppManager::GetKvStore(const Options &options, const std::string &appId, const std::string &storeId,
99 const std::vector<uint8_t> &cipherKey, sptr<KvStoreImpl> &kvStore)
100 {
101 ZLOGI("begin");
102 kvStore = nullptr;
103 PathType type = ConvertPathType(uid_, bundleName_, options.securityLevel);
104 auto *delegateManager = GetDelegateManager(type);
105 if (delegateManager == nullptr) {
106 ZLOGE("delegateManagers[%d] is nullptr.", type);
107 return Status::ILLEGAL_STATE;
108 }
109
110 if (!flowCtrl_.IsTokenEnough()) {
111 ZLOGE("flow control denied");
112 return Status::EXCEED_MAX_ACCESS_RATE;
113 }
114
115 std::lock_guard<std::mutex> lg(storeMutex_);
116 auto it = stores_[type].find(storeId);
117 if (it != stores_[type].end()) {
118 kvStore = it->second;
119 ZLOGI("find store in map refcount: %d.", kvStore->GetSptrRefCount());
120 kvStore->IncreaseOpenCount();
121 return Status::SUCCESS;
122 }
123
124 if ((GetTotalKvStoreNum()) >= static_cast<size_t>(Constant::MAX_OPEN_KVSTORES)) {
125 ZLOGE("limit %d KvStores can be opened.", Constant::MAX_OPEN_KVSTORES);
126 return Status::ERROR;
127 }
128
129 DistributedDB::KvStoreDelegate::Option dbOption;
130 auto status = InitDbOption(options, cipherKey, dbOption);
131 if (status != Status::SUCCESS) {
132 ZLOGE("InitDbOption failed.");
133 return status;
134 }
135
136 DistributedDB::KvStoreDelegate *storeDelegate = nullptr;
137 DistributedDB::DBStatus dbStatusTmp;
138 delegateManager->GetKvStore(storeId, dbOption,
139 [&storeDelegate, &dbStatusTmp](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreDelegate *delegate) {
140 storeDelegate = delegate;
141 dbStatusTmp = dbStatus;
142 });
143
144 if (storeDelegate == nullptr) {
145 ZLOGE("storeDelegate is nullptr, status:%d.", static_cast<int>(dbStatusTmp));
146 return ConvertErrorStatus(dbStatusTmp, options.createIfMissing);
147 }
148
149 ZLOGD("get delegate");
150 kvStore = new (std::nothrow)KvStoreImpl(options, deviceAccountId_, bundleName_,
151 appId, storeId, GetDbDir(options), storeDelegate);
152 if (kvStore == nullptr) {
153 delegateManager->CloseKvStore(storeDelegate);
154 kvStore = nullptr;
155 return Status::ERROR;
156 }
157 auto result = stores_[type].emplace(storeId, kvStore);
158 if (!result.second) {
159 ZLOGE("emplace failed.");
160 delegateManager->CloseKvStore(storeDelegate);
161 kvStore = nullptr;
162 return Status::ERROR;
163 }
164
165 ZLOGD("after emplace refcount: %d", kvStore->GetSptrRefCount());
166 return Status::SUCCESS;
167 }
168
GetKvStore(const Options & options,const std::string & appId,const std::string & storeId,const std::vector<uint8_t> & cipherKey,sptr<SingleKvStoreImpl> & kvStore)169 Status KvStoreAppManager::GetKvStore(const Options &options, const std::string &appId, const std::string &storeId,
170 const std::vector<uint8_t> &cipherKey, sptr<SingleKvStoreImpl> &kvStore)
171 {
172 ZLOGI("begin");
173 kvStore = nullptr;
174 PathType type = ConvertPathType(uid_, bundleName_, options.securityLevel);
175 auto *delegateManager = GetDelegateManager(type);
176 if (delegateManager == nullptr) {
177 ZLOGE("delegateManagers[%d] is nullptr.", type);
178 return Status::ILLEGAL_STATE;
179 }
180
181 if (!flowCtrl_.IsTokenEnough()) {
182 ZLOGE("flow control denied");
183 return Status::EXCEED_MAX_ACCESS_RATE;
184 }
185 std::lock_guard<std::mutex> lg(storeMutex_);
186 auto it = singleStores_[type].find(storeId);
187 if (it != singleStores_[type].end()) {
188 kvStore = it->second;
189 ZLOGI("find store in map refcount: %d.", kvStore->GetSptrRefCount());
190 kvStore->IncreaseOpenCount();
191 return Status::SUCCESS;
192 }
193
194 if ((GetTotalKvStoreNum()) >= static_cast<size_t>(Constant::MAX_OPEN_KVSTORES)) {
195 ZLOGE("limit %d KvStores can be opened.", Constant::MAX_OPEN_KVSTORES);
196 return Status::ERROR;
197 }
198
199 DistributedDB::KvStoreNbDelegate::Option dbOption;
200 auto status = InitNbDbOption(options, cipherKey, dbOption);
201 if (status != Status::SUCCESS) {
202 ZLOGE("InitNbDbOption failed.");
203 return status;
204 }
205
206 DistributedDB::KvStoreNbDelegate *storeDelegate = nullptr;
207 DistributedDB::DBStatus dbStatusTmp;
208 delegateManager->GetKvStore(storeId, dbOption,
209 [&](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *kvStoreDelegate) {
210 storeDelegate = kvStoreDelegate;
211 dbStatusTmp = dbStatus;
212 });
213
214 if (storeDelegate == nullptr) {
215 ZLOGE("storeDelegate is nullptr.");
216 return ConvertErrorStatus(dbStatusTmp, options.createIfMissing);
217 }
218 std::string kvStorePath = GetDbDir(options);
219 switch (options.kvStoreType) {
220 case KvStoreType::DEVICE_COLLABORATION:
221 kvStore = new (std::nothrow) DeviceKvStoreImpl(
222 options, deviceAccountId_, bundleName_, storeId, trueAppId_, kvStorePath, storeDelegate);
223 break;
224 default:
225 kvStore = new (std::nothrow) SingleKvStoreImpl(
226 options, deviceAccountId_, bundleName_, storeId, trueAppId_, kvStorePath, storeDelegate);
227 break;
228 }
229 if (kvStore == nullptr) {
230 ZLOGE("store is nullptr.");
231 delegateManager->CloseKvStore(storeDelegate);
232 kvStore = nullptr;
233 return Status::ERROR;
234 }
235 kvStore->SetCompatibleIdentify();
236 auto result = singleStores_[type].emplace(storeId, kvStore);
237 if (!result.second) {
238 ZLOGE("emplace failed.");
239 delegateManager->CloseKvStore(storeDelegate);
240 kvStore = nullptr;
241 return Status::ERROR;
242 }
243
244 ZLOGI("after emplace refcount: %d autoSync: %d", kvStore->GetSptrRefCount(), static_cast<int>(options.autoSync));
245 if (options.autoSync) {
246 bool autoSync = true;
247 DistributedDB::PragmaData data = static_cast<DistributedDB::PragmaData>(&autoSync);
248 auto pragmaStatus = storeDelegate->Pragma(DistributedDB::PragmaCmd::AUTO_SYNC, data);
249 if (pragmaStatus != DistributedDB::DBStatus::OK) {
250 ZLOGE("pragmaStatus: %d", static_cast<int>(pragmaStatus));
251 }
252 }
253
254 DistributedDB::AutoLaunchOption launchOption = {
255 options.createIfMissing, options.encrypt, dbOption.cipher, dbOption.passwd, dbOption.schema,
256 dbOption.createDirByStoreIdOnly, kvStorePath, nullptr
257 };
258 launchOption.secOption = ConvertSecurity(options.securityLevel);
259 AppAccessorParam accessorParam = {Constant::DEFAULT_GROUP_ID, trueAppId_, storeId, launchOption};
260 KvStoreAppAccessor::GetInstance().EnableKvStoreAutoLaunch(accessorParam);
261 return Status::SUCCESS;
262 }
263
CloseKvStore(const std::string & storeId)264 Status KvStoreAppManager::CloseKvStore(const std::string &storeId)
265 {
266 ZLOGI("CloseKvStore");
267 if (!flowCtrl_.IsTokenEnough()) {
268 ZLOGE("flow control denied");
269 return Status::EXCEED_MAX_ACCESS_RATE;
270 }
271 std::lock_guard<std::mutex> lg(storeMutex_);
272 Status status = CloseKvStore(storeId, PATH_DE);
273 if (status != Status::STORE_NOT_OPEN) {
274 return status;
275 }
276
277 status = CloseKvStore(storeId, PATH_CE);
278 if (status != Status::STORE_NOT_OPEN) {
279 return status;
280 }
281
282 ZLOGW("store not open");
283 return Status::STORE_NOT_OPEN;
284 }
285
CloseAllKvStore()286 Status KvStoreAppManager::CloseAllKvStore()
287 {
288 ZLOGI("begin.");
289 std::lock_guard<std::mutex> lg(storeMutex_);
290 if (GetTotalKvStoreNum() == 0) {
291 return Status::STORE_NOT_OPEN;
292 }
293
294 ZLOGI("close %zu KvStores.", GetTotalKvStoreNum());
295 Status status = CloseAllKvStore(PATH_DE);
296 if (status == Status::DB_ERROR) {
297 return status;
298 }
299 status = CloseAllKvStore(PATH_CE);
300 if (status == Status::DB_ERROR) {
301 return status;
302 }
303 return Status::SUCCESS;
304 }
305
DeleteKvStore(const std::string & storeId)306 Status KvStoreAppManager::DeleteKvStore(const std::string &storeId)
307 {
308 ZLOGI("%s", storeId.c_str());
309 if (!flowCtrl_.IsTokenEnough()) {
310 ZLOGE("flow control denied");
311 return Status::EXCEED_MAX_ACCESS_RATE;
312 }
313
314 Status statusDE = DeleteKvStore(storeId, PATH_DE);
315 Status statusCE = DeleteKvStore(storeId, PATH_CE);
316 if (statusDE == Status::SUCCESS || statusCE == Status::SUCCESS) {
317 return Status::SUCCESS;
318 }
319
320 ZLOGE("delegate close error.");
321 return Status::DB_ERROR;
322 }
323
DeleteAllKvStore()324 Status KvStoreAppManager::DeleteAllKvStore()
325 {
326 ZLOGI("begin.");
327 std::lock_guard<std::mutex> lg(storeMutex_);
328 if (GetTotalKvStoreNum() == 0) {
329 return Status::STORE_NOT_OPEN;
330 }
331 ZLOGI("delete %d KvStores.", int32_t(GetTotalKvStoreNum()));
332
333 Status status = DeleteAllKvStore(PATH_DE);
334 if (status != Status::SUCCESS) {
335 ZLOGE("path de delegate delete error: %d.", static_cast<int>(status));
336 return Status::DB_ERROR;
337 }
338 status = DeleteAllKvStore(PATH_CE);
339 if (status != Status::SUCCESS) {
340 ZLOGE("path ce delegate delete error: %d.", static_cast<int>(status));
341 return Status::DB_ERROR;
342 }
343 return Status::SUCCESS;
344 }
345
MigrateAllKvStore(const std::string & harmonyAccountId)346 Status KvStoreAppManager::MigrateAllKvStore(const std::string &harmonyAccountId)
347 {
348 ZLOGI("begin");
349 if (PermissionValidator::IsAutoLaunchEnabled(bundleName_)) {
350 return Status::SUCCESS;
351 }
352
353 std::lock_guard<std::mutex> lg(storeMutex_);
354 // update userid in kvstore tuple map of permission adapter.
355 KvStoreTuple srcKvStoreTuple {userId_, bundleName_};
356 KvStoreTuple dstKvStoreTuple {harmonyAccountId, bundleName_};
357 PermissionValidator::UpdateKvStoreTupleMap(srcKvStoreTuple, dstKvStoreTuple);
358 userId_ = harmonyAccountId;
359 ZLOGI("path de migration begin.");
360 Status statusDE = MigrateAllKvStore(harmonyAccountId, PATH_DE);
361 ZLOGI("path ce migration begin.");
362 Status statusCE = MigrateAllKvStore(harmonyAccountId, PATH_CE);
363 return (statusCE != Status::SUCCESS) ? statusCE : statusDE;
364 }
365
InitDbOption(const Options & options,const std::vector<uint8_t> & cipherKey,DistributedDB::KvStoreDelegate::Option & dbOption)366 Status KvStoreAppManager::InitDbOption(const Options &options, const std::vector<uint8_t> &cipherKey,
367 DistributedDB::KvStoreDelegate::Option &dbOption)
368 {
369 DistributedDB::CipherPassword password;
370 auto status = password.SetValue(cipherKey.data(), cipherKey.size());
371 if (status != DistributedDB::CipherPassword::ErrorCode::OK) {
372 ZLOGE("Failed to set the passwd.");
373 return Status::DB_ERROR;
374 }
375 dbOption.createIfNecessary = options.createIfMissing;
376 dbOption.localOnly = false;
377 dbOption.isEncryptedDb = options.encrypt;
378 if (options.encrypt) {
379 dbOption.cipher = DistributedDB::CipherType::AES_256_GCM;
380 dbOption.passwd = password;
381 }
382 dbOption.createDirByStoreIdOnly = options.dataOwnership;
383 return Status::SUCCESS;
384 }
385
InitNbDbOption(const Options & options,const std::vector<uint8_t> & cipherKey,DistributedDB::KvStoreNbDelegate::Option & dbOption)386 Status KvStoreAppManager::InitNbDbOption(const Options &options, const std::vector<uint8_t> &cipherKey,
387 DistributedDB::KvStoreNbDelegate::Option &dbOption)
388 {
389 DistributedDB::CipherPassword password;
390 auto status = password.SetValue(cipherKey.data(), cipherKey.size());
391 if (status != DistributedDB::CipherPassword::ErrorCode::OK) {
392 ZLOGE("Failed to set the passwd.");
393 return Status::DB_ERROR;
394 }
395
396 dbOption.syncDualTupleMode = true; // tuple of (appid+storeid)
397 dbOption.createIfNecessary = options.createIfMissing;
398 dbOption.isEncryptedDb = options.encrypt;
399 if (options.encrypt) {
400 dbOption.cipher = DistributedDB::CipherType::AES_256_GCM;
401 dbOption.passwd = password;
402 }
403
404 if (options.kvStoreType == KvStoreType::SINGLE_VERSION) {
405 dbOption.conflictResolvePolicy = DistributedDB::LAST_WIN;
406 } else if (options.kvStoreType == KvStoreType::DEVICE_COLLABORATION) {
407 dbOption.conflictResolvePolicy = DistributedDB::DEVICE_COLLABORATION;
408 } else {
409 ZLOGE("kvStoreType is invalid");
410 return Status::INVALID_ARGUMENT;
411 }
412
413 dbOption.schema = options.schema;
414 dbOption.createDirByStoreIdOnly = options.dataOwnership;
415 dbOption.secOption = ConvertSecurity(options.securityLevel);
416 return Status::SUCCESS;
417 }
418
GetDbDir(const Options & options) const419 std::string KvStoreAppManager::GetDbDir(const Options &options) const
420 {
421 return GetDataStoragePath(deviceAccountId_, bundleName_, ConvertPathType(uid_, bundleName_, options.securityLevel));
422 }
423
ConvertPathType(int32_t uid,const std::string & bundleName,int securityLevel)424 KvStoreAppManager::PathType KvStoreAppManager::ConvertPathType(int32_t uid, const std::string &bundleName,
425 int securityLevel)
426 {
427 switch (securityLevel) {
428 case S0: // fallthrough
429 case S1:
430 return PATH_DE;
431 case S2: // fallthrough
432 case S3_EX: // fallthrough
433 case S3: // fallthrough
434 case S4: // fallthrough
435 return PATH_CE;
436 default:
437 break;
438 }
439 auto *checker = CheckerManager::GetInstance().GetChecker(CheckerManager::SYSTEM_CHECKER);
440 if (checker == nullptr || !checker->IsValid(uid, bundleName)) {
441 return PATH_CE;
442 }
443 return PATH_DE;
444 }
445
GetDelegateManager(PathType type)446 DistributedDB::KvStoreDelegateManager *KvStoreAppManager::GetDelegateManager(PathType type)
447 {
448 std::lock_guard<std::mutex> guard(delegateMutex_);
449 if (delegateManagers_[type] != nullptr) {
450 return delegateManagers_[type];
451 }
452
453 std::string directory = GetDataStoragePath(deviceAccountId_, bundleName_, type);
454 bool ret = ForceCreateDirectory(directory);
455 if (!ret) {
456 ZLOGE("create directory[%s] failed, errstr=[%d].", directory.c_str(), errno);
457 return nullptr;
458 }
459 // change mode for directories to 0755, and for files to 0600.
460 DirectoryUtils::ChangeModeDirOnly(directory, Constant::DEFAULT_MODE_DIR);
461 DirectoryUtils::ChangeModeFileOnly(directory, Constant::DEFAULT_MODE_FILE);
462
463 trueAppId_ = CheckerManager::GetInstance().GetAppId(bundleName_, uid_);
464 if (trueAppId_.empty()) {
465 delegateManagers_[type] = nullptr;
466 ZLOGW("check bundleName:%{public}s uid:%{public}d failed.", bundleName_.c_str(), uid_);
467 return nullptr;
468 }
469
470 userId_ = AccountDelegate::GetInstance()->GetCurrentAccountId(bundleName_);
471 ZLOGD("accountId: %{public}s bundleName: %{public}s", deviceAccountId_.c_str(), bundleName_.c_str());
472 delegateManagers_[type] = new (std::nothrow) DistributedDB::KvStoreDelegateManager(trueAppId_, deviceAccountId_);
473 if (delegateManagers_[type] == nullptr) {
474 ZLOGE("delegateManagers_[%d] is nullptr.", type);
475 return nullptr;
476 }
477
478 DistributedDB::KvStoreConfig kvStoreConfig;
479 kvStoreConfig.dataDir = directory;
480 delegateManagers_[type]->SetKvStoreConfig(kvStoreConfig);
481 return delegateManagers_[type];
482 }
483
SwitchDelegateManager(PathType type,DistributedDB::KvStoreDelegateManager * delegateManager)484 DistributedDB::KvStoreDelegateManager *KvStoreAppManager::SwitchDelegateManager(PathType type,
485 DistributedDB::KvStoreDelegateManager *delegateManager)
486 {
487 std::lock_guard<std::mutex> guard(delegateMutex_);
488 DistributedDB::KvStoreDelegateManager *oldDelegateManager = delegateManagers_[type];
489 delegateManagers_[type] = delegateManager;
490 return oldDelegateManager;
491 }
492
CloseKvStore(const std::string & storeId,PathType type)493 Status KvStoreAppManager::CloseKvStore(const std::string &storeId, PathType type)
494 {
495 auto *delegateManager = GetDelegateManager(type);
496 if (delegateManager == nullptr) {
497 ZLOGE("delegateManager[%d] is null.", type);
498 return Status::ILLEGAL_STATE;
499 }
500
501 auto it = stores_[type].find(storeId);
502 if (it != stores_[type].end()) {
503 ZLOGD("find store and close delegate.");
504 InnerStatus status = it->second->Close(delegateManager);
505 if (status == InnerStatus::SUCCESS) {
506 stores_[type].erase(it);
507 return Status::SUCCESS;
508 }
509 if (status == InnerStatus::DECREASE_REFCOUNT) {
510 return Status::SUCCESS;
511 }
512 ZLOGE("delegate close error: %d.", static_cast<int>(status));
513 return Status::DB_ERROR;
514 }
515
516 auto itSingle = singleStores_[type].find(storeId);
517 if (itSingle != singleStores_[type].end()) {
518 ZLOGD("find single store and close delegate.");
519 InnerStatus status = itSingle->second->Close(delegateManager);
520 if (status == InnerStatus::SUCCESS) {
521 singleStores_[type].erase(itSingle);
522 return Status::SUCCESS;
523 }
524 if (status == InnerStatus::DECREASE_REFCOUNT) {
525 return Status::SUCCESS;
526 }
527 ZLOGE("delegate close error: %d.", static_cast<int>(status));
528 return Status::DB_ERROR;
529 }
530
531 return Status::STORE_NOT_OPEN;
532 }
533
CloseAllKvStore(PathType type)534 Status KvStoreAppManager::CloseAllKvStore(PathType type)
535 {
536 auto *delegateManager = GetDelegateManager(type);
537 if (delegateManager == nullptr) {
538 ZLOGE("delegateManager[%d] is null.", type);
539 return Status::ILLEGAL_STATE;
540 }
541
542 for (auto it = stores_[type].begin(); it != stores_[type].end(); it = stores_[type].erase(it)) {
543 KvStoreImpl *currentStore = it->second.GetRefPtr();
544 ZLOGI("close kvstore, refcount %d.", it->second->GetSptrRefCount());
545 Status status = currentStore->ForceClose(delegateManager);
546 if (status != Status::SUCCESS) {
547 ZLOGE("delegate close error: %d.", static_cast<int>(status));
548 return Status::DB_ERROR;
549 }
550 }
551 stores_[type].clear();
552
553 for (auto it = singleStores_[type].begin(); it != singleStores_[type].end(); it = singleStores_[type].erase(it)) {
554 SingleKvStoreImpl *currentStore = it->second.GetRefPtr();
555 ZLOGI("close kvstore, refcount %d.", it->second->GetSptrRefCount());
556 Status status = currentStore->ForceClose(delegateManager);
557 if (status != Status::SUCCESS) {
558 ZLOGE("delegate close error: %d.", static_cast<int>(status));
559 return Status::DB_ERROR;
560 }
561 }
562 singleStores_[type].clear();
563 return Status::SUCCESS;
564 }
565
DeleteKvStore(const std::string & storeId,PathType type)566 Status KvStoreAppManager::DeleteKvStore(const std::string &storeId, PathType type)
567 {
568 auto *delegateManager = GetDelegateManager(type);
569 if (delegateManager == nullptr) {
570 ZLOGE("delegateManager[%d] is null.", type);
571 return Status::ILLEGAL_STATE;
572 }
573 std::lock_guard<std::mutex> lg(storeMutex_);
574 auto it = stores_[type].find(storeId);
575 if (it != stores_[type].end()) {
576 Status status = it->second->ForceClose(delegateManager);
577 if (status != Status::SUCCESS) {
578 return Status::DB_ERROR;
579 }
580 stores_[type].erase(it);
581 }
582
583 auto itSingle = singleStores_[type].find(storeId);
584 if (itSingle != singleStores_[type].end()) {
585 Status status = itSingle->second->ForceClose(delegateManager);
586 if (status != Status::SUCCESS) {
587 return Status::DB_ERROR;
588 }
589 singleStores_[type].erase(itSingle);
590 }
591
592 DistributedDB::DBStatus status = delegateManager->DeleteKvStore(storeId);
593 if (singleStores_[type].empty() && stores_[type].empty()) {
594 SwitchDelegateManager(type, nullptr);
595 delete delegateManager;
596 }
597 return (status != DistributedDB::DBStatus::OK) ? Status::DB_ERROR : Status::SUCCESS;
598 }
599
DeleteAllKvStore(PathType type)600 Status KvStoreAppManager::DeleteAllKvStore(PathType type)
601 {
602 auto *delegateManager = GetDelegateManager(type);
603 if (delegateManager == nullptr) {
604 ZLOGE("delegateManager[%d] is null.", type);
605 return Status::ILLEGAL_STATE;
606 }
607
608 for (auto it = stores_[type].begin(); it != stores_[type].end(); it = stores_[type].erase(it)) {
609 std::string storeId = it->first;
610 KvStoreImpl *currentStore = it->second.GetRefPtr();
611 Status status = currentStore->ForceClose(delegateManager);
612 if (status != Status::SUCCESS) {
613 ZLOGE("delegate delete close failed error: %d.", static_cast<int>(status));
614 return Status::DB_ERROR;
615 }
616
617 ZLOGI("delete kvstore, refcount %d.", it->second->GetSptrRefCount());
618 DistributedDB::DBStatus dbStatus = delegateManager->DeleteKvStore(storeId);
619 if (dbStatus != DistributedDB::DBStatus::OK) {
620 ZLOGE("delegate delete error: %d.", static_cast<int>(dbStatus));
621 return Status::DB_ERROR;
622 }
623 }
624 stores_[type].clear();
625
626 for (auto it = singleStores_[type].begin(); it != singleStores_[type].end(); it = singleStores_[type].erase(it)) {
627 std::string storeId = it->first;
628 SingleKvStoreImpl *currentStore = it->second.GetRefPtr();
629 Status status = currentStore->ForceClose(delegateManager);
630 if (status != Status::SUCCESS) {
631 ZLOGE("delegate delete close failed error: %d.", static_cast<int>(status));
632 return Status::DB_ERROR;
633 }
634
635 ZLOGI("close kvstore, refcount %d.", it->second->GetSptrRefCount());
636 DistributedDB::DBStatus dbStatus = delegateManager->DeleteKvStore(storeId);
637 if (dbStatus != DistributedDB::DBStatus::OK) {
638 ZLOGE("delegate delete error: %d.", static_cast<int>(dbStatus));
639 return Status::DB_ERROR;
640 }
641 }
642 singleStores_[type].clear();
643 SwitchDelegateManager(type, nullptr);
644 delete delegateManager;
645 return Status::SUCCESS;
646 }
647
MigrateAllKvStore(const std::string & harmonyAccountId,PathType type)648 Status KvStoreAppManager::MigrateAllKvStore(const std::string &harmonyAccountId, PathType type)
649 {
650 auto *delegateManager = GetDelegateManager(type);
651 if (delegateManager == nullptr) {
652 ZLOGE("delegateManager is nullptr.");
653 return Status::ILLEGAL_STATE;
654 }
655
656 std::string dirPath = GetDataStoragePath(deviceAccountId_, bundleName_, type);
657 DistributedDB::KvStoreDelegateManager *newDelegateManager = nullptr;
658 Status status = Status::SUCCESS;
659 ZLOGI("KvStore migration begin.");
660 for (auto &it : stores_[type]) {
661 sptr<KvStoreImpl> impl = it.second;
662 if (impl->MigrateKvStore(harmonyAccountId, dirPath, delegateManager, newDelegateManager) != Status::SUCCESS) {
663 status = Status::MIGRATION_KVSTORE_FAILED;
664 ZLOGE("migrate kvstore for appId-%s failed.", bundleName_.c_str());
665 // skip this failed, continue to migrate other kvstore.
666 }
667 }
668
669 ZLOGI("SingleKvStore migration begin.");
670 for (auto &it : singleStores_[type]) {
671 sptr<SingleKvStoreImpl> impl = it.second;
672 if (impl->MigrateKvStore(harmonyAccountId, dirPath, delegateManager, newDelegateManager) != Status::SUCCESS) {
673 status = Status::MIGRATION_KVSTORE_FAILED;
674 ZLOGE("migrate single kvstore for appId-%s failed.", bundleName_.c_str());
675 // skip this failed, continue to migrate other kvstore.
676 }
677 }
678
679 if (newDelegateManager != nullptr) {
680 delegateManager = SwitchDelegateManager(type, newDelegateManager);
681 delete delegateManager;
682 }
683 return status;
684 }
685
GetTotalKvStoreNum() const686 size_t KvStoreAppManager::GetTotalKvStoreNum() const
687 {
688 size_t total = stores_[PATH_DE].size();
689 total += stores_[PATH_CE].size();
690 total += singleStores_[PATH_DE].size();
691 total += singleStores_[PATH_CE].size();
692 return int(total);
693 };
694
GetDataStoragePath(const std::string & userId,const std::string & bundleName,PathType type)695 std::string KvStoreAppManager::GetDataStoragePath(const std::string &userId, const std::string &bundleName,
696 PathType type)
697 {
698 std::string miscPath = (type == PATH_DE) ? Constant::ROOT_PATH_DE : Constant::ROOT_PATH_CE;
699 return Constant::Concatenate({
700 miscPath, "/", Constant::SERVICE_NAME, "/", userId, "/", Constant::GetDefaultHarmonyAccountName(),
701 "/", bundleName, "/"
702 });
703 }
704
ConvertSecurity(int securityLevel)705 DistributedDB::SecurityOption KvStoreAppManager::ConvertSecurity(int securityLevel)
706 {
707 if (securityLevel < SecurityLevel::NO_LABEL || securityLevel > SecurityLevel::S4) {
708 return {DistributedDB::NOT_SET, DistributedDB::ECE};
709 }
710 switch (securityLevel) {
711 case SecurityLevel::S3:
712 return {DistributedDB::S3, DistributedDB::SECE};
713 case SecurityLevel::S4:
714 return {DistributedDB::S4, DistributedDB::ECE};
715 default:
716 return {securityLevel, DistributedDB::ECE};
717 }
718 }
719
Dump(int fd) const720 void KvStoreAppManager::Dump(int fd) const
721 {
722 const std::string prefix(8, ' ');
723 std::string dePath = GetDataStoragePath(deviceAccountId_, bundleName_, PATH_DE);
724 std::string cePath = GetDataStoragePath(deviceAccountId_, bundleName_, PATH_CE);
725 size_t singleStoreNum = singleStores_[PATH_DE].size() + singleStores_[PATH_CE].size();
726 dprintf(fd, "%s----------------------------------------------------------\n", prefix.c_str());
727 dprintf(fd, "%sAppID : %s\n", prefix.c_str(), trueAppId_.c_str());
728 dprintf(fd, "%sBundleName : %s\n", prefix.c_str(), bundleName_.c_str());
729 dprintf(fd, "%sAppDEDirectory: %s\n", prefix.c_str(), dePath.c_str());
730 dprintf(fd, "%sAppCEDirectory: %s\n", prefix.c_str(), cePath.c_str());
731 dprintf(fd, "%sStore count : %u\n", prefix.c_str(), static_cast<uint32_t>(singleStoreNum));
732 for (const auto &singleStoreMap : singleStores_) {
733 for (const auto &pair : singleStoreMap) {
734 pair.second->OnDump(fd);
735 }
736 }
737 }
738
IsStoreOpened(const std::string & storeId) const739 bool KvStoreAppManager::IsStoreOpened(const std::string &storeId) const
740 {
741 return (!singleStores_[PATH_DE].empty() && singleStores_->find(storeId) != singleStores_->end())
742 || (!singleStores_[PATH_CE].empty() && singleStores_->find(storeId) != singleStores_->end());
743 }
744
SetCompatibleIdentify(const std::string & deviceId) const745 void KvStoreAppManager::SetCompatibleIdentify(const std::string &deviceId) const
746 {
747 for (const auto &storeType : singleStores_) {
748 for (const auto &item : storeType) {
749 if (item.second == nullptr) {
750 continue;
751 }
752 item.second->SetCompatibleIdentify(deviceId);
753 }
754 }
755 }
756 } // namespace DistributedKv
757 } // namespace OHOS
758